#!/usr/bin/env ruby # Copyright (c) 2010 Samuel Williams. Released under the GNU GPLv3. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . require 'rubygems' require 'rexec' require 'optparse' OPTIONS = { :out => "/tmp/daemon-exec.log", :err => "/tmp/daemon-exec-error.log", :in => "/dev/null", :print_pid => false, :root => "/", :verbose => false, :relocate => true, :read_stdin => false, } ARGV.options do |o| script_name = File.basename($0) o.set_summary_indent("\t") o.banner = "Usage: #{script_name} [-I stdin] [-O stdout] [-E stderr] [script/stdin]" o.define_head "Copyright (c) 2010 Samuel Williams ." o.on("-d [dir]", String, "Daemons working path, default /") do |dir| OPTIONS[:root] = dir end o.on("-s", "Don't attempt to relocate arguments to absolute paths") do OPTIONS[:relocate] = false end o.define "File / Pipe Options:" o.on("-I [path]", String, "File for STDIN, defaults to #{OPTIONS[:in]}") do |path| OPTIONS[:in] = path end o.on("--stdin", "Read from current STDIN to daemon process.") do OPTIONS[:in] = "-" end o.on("-O [path]", String, "File for STDOUT, defaults to #{OPTIONS[:out]}") do |path| OPTIONS[:out] = path end o.on("-E [path]", String, "File for STDERR, defaults to #{OPTIONS[:err]}") do |path| OPTIONS[:err] = path end o.define "Misc Options:" o.on("-p", "Print out the PID of the forked process") do OPTIONS[:print_pid] = true end o.on("-V", "Print verbose information about what is going on") do OPTIONS[:verbose] = true end o.on("-h", "Show this help/version information and exit") do puts o exit 0 end end.parse! if OPTIONS[:relocate] ARGV.collect! do |value| if File.exist?(value) File.expand_path(value) else value end end [:in, :out, :err].each do |path| OPTIONS[path] = File.expand_path(OPTIONS[path]) if File.exist?(OPTIONS[path]) end end if OPTIONS[:verbose] puts "Running #{ARGV.inspect}" end task_options = { :daemonize => true, :out => File.open(OPTIONS[:out], "a"), :err => File.open(OPTIONS[:err], "a") } if OPTIONS[:in] == '-' task_options[:passthrough] = [:in] end daemon = lambda do Dir.chdir(OPTIONS[:root]) system("env", *ARGV) end task = RExec::Task.open(daemon, task_options) if OPTIONS[:print_pid] puts task.pid end