Created
February 4, 2014 11:40
-
-
Save tumani1/8802193 to your computer and use it in GitHub Desktop.
Fork LightDaemon. Главный процесс ответвляется от консоли и запускает набор задач на исполнение. Запущенный список задач мониторится на живучесть. В случае падения child worker перезапустит его.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module LightDaemon | |
class Daemon | |
DEFAULT_PID_FILE = "/tmp/light_daemon.pid" | |
class << self | |
def start(obj, options={}) | |
@options = self.parse_options(options) | |
@pid_file = @options[:pid_file] | |
if self.get_pid() | |
raise "The pid file \"#{@pid_file}\" existed already. You need to stop the daemon first." | |
end | |
self.new(obj).start() | |
end | |
def stop(pid_file=DEFAULT_PID_FILE) | |
@pid_file = pid_file | |
if (pid = self.get_pid()) | |
kill_flag = false | |
begin | |
Process.kill("TERM", pid) | |
kill_flag = true | |
rescue Errno::EPERM | |
p "No permission to query #{pid}!" | |
rescue Errno::ESRCH | |
"#{pid} is NOT running." | |
kill_flag = true | |
rescue Exception => e | |
p "Unable to determine status for #{pid}: #{e.message}" | |
ensure | |
if kill_flag | |
self.clear_pid | |
end | |
end | |
end | |
end | |
def get_pid() | |
return nil unless File.exist?(@pid_file) | |
begin | |
result = File.open(@pid_file) {|f| f.read}.to_i | |
rescue Exception => e | |
result = nil | |
end | |
return result | |
end | |
def set_pid(pid) | |
File.open(@pid_file, 'w') {|f| f.write(pid.to_s)} | |
end | |
def clear_pid() | |
File.unlink(@pid_file) | |
end | |
def parse_options(options) | |
options[:pid_file] ||= DEFAULT_PID_FILE | |
return options | |
end | |
def debugging() | |
# Not Implemented | |
end | |
end | |
def initialize(obj) | |
# Make our proccess as daemon | |
daemonize() | |
# Set pid in the file for current pid | |
self.class.set_pid(Process.pid) | |
# List objects for execute | |
@obj = (!obj.kind_of?(Array)) ? [obj] : obj | |
# Starting list pids | |
@processes = {} | |
# Flag for child | |
@is_child = false | |
# Running flag | |
@is_ranning_wait_pid = true | |
# Start execute observer | |
signal_handling() | |
end | |
def process_alive?(pid) | |
return false unless pid | |
begin | |
Process.kill(0, pid) | |
rescue Errno::EPERM | |
#p "No permission to query #{pid}!"; | |
rescue Errno::ESRCH | |
#p "#{pid} is NOT running."; | |
return false | |
rescue Exception => e | |
#p "Unable to determine status for #{pid} : #{e.message}" | |
end | |
return true | |
end | |
def start() | |
@obj.each do |obj| | |
pid = fork do | |
item.call() | |
end | |
@processes.merge!({pid => obj}) | |
end | |
keep_running() | |
end | |
private | |
def daemonize() | |
fork && exit | |
unless Process.setsid | |
raise 'Can not detach from controlling terminal' | |
end | |
trap 'SIGHUP', 'IGNORE' | |
exit if fork | |
begin; STDIN.reopen "/dev/null"; rescue ::Exception; end | |
begin; STDOUT.reopen "/dev/null"; rescue ::Exception; end | |
begin; STDERR.reopen STDOUT; rescue ::Exception; end | |
STDERR.sync = true | |
end | |
def signal_handling() | |
# Setup variable | |
$keep_running = true | |
Signal.trap "TERM" do | |
unless @is_child | |
$keep_running = false | |
@processes.each do |pid, obj| | |
begin | |
Process.kill("TERM", pid) | |
rescue Exception => e | |
end | |
end | |
# wait | |
sleep(5) | |
@processes.size.times do | |
pid, obj = @processes.shift | |
if process_alive?(pid) | |
@processes.merge!({pid => obj}) | |
sleep(5) | |
end | |
end | |
@processes.each do |pid, obj| | |
if process_alive?(pid) | |
Process.kill(9, pid) | |
end | |
end | |
# Clear pid file | |
self.class.clear_pid() | |
end | |
end | |
end | |
def keep_running() | |
while $keep_running do | |
wpid, status = Process.wait(-1, Process::WNOHANG) | |
if @processes.include?(wpid) | |
obj = @processes[wpid] | |
@processes.delete(wpid) | |
pid = fork do | |
obj.call() | |
end | |
@processes.merge!({pid => obj}) | |
end | |
sleep(5) | |
end | |
end | |
end | |
end | |
class Test | |
def initialize(value) | |
@value = value | |
end | |
def call() | |
while true do | |
`echo "process: #{Process.pid} - #{@value}" >> /tmp/my-daemon.txt` | |
sleep(3) | |
end | |
end | |
end | |
p "Start task:" | |
LightDaemon::Daemon.start([Test.new(2), Test.new(1), Test.new(3)]) | |
# p "Is running:" | |
# AMQP_Daemon::Daemon.process_alive?() | |
#p "Stop task:" | |
#AMQP_Daemon::Daemon.stop() | |
# p "Is running:" | |
# AMQP_Daemon::Daemon.process_alive?() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment