5 WRITES_PID = [:start, :restart]
7 attr_accessor :name, :uid, :gid, :log, :start, :stop, :restart
9 def initialize(options={})
18 # determine if we're tracking pid or not
23 # a name must be specified
26 puts "No name was specified"
29 # a start command must be specified
32 puts "No start command was specified"
35 # self-daemonizing processes must specify a stop command
36 if !@tracking_pid && self.stop.nil?
38 puts "No stop command was specified"
41 # self-daemonizing processes cannot specify log
42 if !@tracking_pid && self.log
44 puts "Self-daemonizing processes cannot specify a log file"
47 # uid must exist if specified
50 Etc.getpwnam(self.uid)
53 puts "UID for '#{self.uid}' does not exist"
57 # gid must exist if specified
60 Etc.getgrnam(self.gid)
63 puts "GID for '#{self.gid}' does not exist"
70 # DON'T USE THIS INTERNALLY. Use the instance variable. -- Kev
71 # No really, trust me. Use the instance variable.
80 @pid_file = default_pid_file
97 def call_action(action)
98 command = send(action)
100 if action == :stop && command.nil?
101 # command = "kill -9 `cat #{self.pid_file}`"
102 pid = File.read(self.pid_file).strip.to_i
104 # log_file = self.log
106 # File.open(log_file, 'a') do |logger|
107 # logger.puts "god stop [" + Time.now.strftime("%Y-%m-%d %H:%M:%S") + "] lambda killer"
110 puts "#{self.name} stop: default lambda killer"
112 ::Process.kill('HUP', pid) rescue nil
114 # Poll to see if it's dead
117 ::Process.kill(0, pid)
126 ::Process.kill('KILL', pid) rescue nil
131 if command.kind_of?(String)
133 unless test(?d, God.pid_file_directory)
135 FileUtils.mkdir_p(God.pid_file_directory)
136 rescue Errno::EACCES => e
137 abort "Failed to create pid file directory: #{e.message}"
141 unless test(?w, God.pid_file_directory)
142 abort "The pid file directory (#{God.pid_file_directory}) is not writable by #{Etc.getlogin}"
146 # fork/exec to setuid/gid
153 ::Process::Sys.setgid(Etc.getgrnam(self.gid).gid) if self.gid
154 ::Process::Sys.setuid(Etc.getpwnam(self.uid).uid) if self.uid
157 STDIN.reopen "/dev/null"
159 STDOUT.reopen self.log, "a"
161 STDOUT.reopen "/dev/null", "a"
165 # STDOUT.puts "god #{action} [" + Time.now.strftime("%Y-%m-%d %H:%M:%S") + "] " + command
168 exec command unless command.empty?
173 ::Process.waitpid(opid, 0)
177 if @tracking_pid or (@pid_file.nil? and WRITES_PID.include?(action))
178 File.open(default_pid_file, 'w') do |f|
183 @pid_file = default_pid_file
186 elsif command.kind_of?(Proc)
190 raise NotImplementedError
195 File.join(God.pid_file_directory, "#{self.name}.pid")