light-daemon 0.9.0 → 0.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/light_daemon.rb +103 -50
- metadata +5 -5
data/lib/light_daemon.rb
CHANGED
@@ -1,49 +1,98 @@
|
|
1
1
|
module LightDaemon
|
2
2
|
class Daemon
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
DEFAULT_PID_FILE = "/tmp/light_daemon.pid"
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def start(obj, options={})
|
7
|
+
@options = self.make_options(options)
|
8
|
+
@pid_file = @options[:pid_file]
|
9
|
+
if self.get_pid
|
10
|
+
raise "The pid file \"#{@pid_file}\" existed already. You need to stop the daemon first."
|
11
|
+
end
|
12
|
+
self.new(obj, @options).start
|
13
|
+
end
|
14
|
+
|
15
|
+
def stop(pid_file=DEFAULT_PID_FILE)
|
16
|
+
@pid_file = pid_file
|
17
|
+
if(pid = self.get_pid)
|
18
|
+
begin
|
19
|
+
Process.kill("TERM", pid)
|
20
|
+
rescue Errno::ESRCH
|
21
|
+
# no such process. do nothing
|
22
|
+
end
|
23
|
+
self.clear_pid
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_pid
|
28
|
+
return nil unless File.exist?(@pid_file)
|
29
|
+
begin
|
30
|
+
File.open(@pid_file) {|f| f.read}.to_i
|
31
|
+
rescue
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def set_pid(pid)
|
37
|
+
File.open(@pid_file, 'w') {|f| f.write(pid.to_s)}
|
38
|
+
end
|
39
|
+
|
40
|
+
def clear_pid
|
41
|
+
File.unlink(@pid_file)
|
42
|
+
end
|
43
|
+
|
44
|
+
def make_options(options)
|
45
|
+
options[:children] ||= 1
|
46
|
+
options[:monitor_cycle] ||= 10 # seconds
|
47
|
+
options[:pid_file] ||= DEFAULT_PID_FILE
|
48
|
+
options
|
49
|
+
end
|
50
|
+
|
51
|
+
# for debugging
|
52
|
+
# def log(msg)
|
53
|
+
# File.open("/tmp/yi.txt", "a") do |f|
|
54
|
+
# f.puts msg
|
55
|
+
# end
|
56
|
+
# end
|
57
|
+
end
|
58
|
+
|
59
|
+
def initialize(obj, options)
|
7
60
|
daemonize
|
8
|
-
|
61
|
+
self.class.set_pid(Process.pid)
|
62
|
+
|
63
|
+
@options = options
|
64
|
+
@obj = obj
|
9
65
|
@processes = []
|
66
|
+
@is_child = false
|
10
67
|
signal_handling
|
11
68
|
end
|
12
69
|
|
13
|
-
def self.start(obj, options={})
|
14
|
-
self.new(obj, options).start
|
15
|
-
end
|
16
|
-
|
17
70
|
def signal_handling
|
18
|
-
$
|
71
|
+
$keep_running = true
|
19
72
|
Signal.trap "TERM" do
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
73
|
+
unless @is_child
|
74
|
+
@processes.each do |pid|
|
75
|
+
Process.kill("TERM", pid)
|
76
|
+
end
|
77
|
+
|
78
|
+
sleep(3)
|
79
|
+
options[:children].times do
|
80
|
+
@processes.size.times do
|
81
|
+
pid = @processes.shift
|
82
|
+
if process_alive?(pid)
|
83
|
+
@processes << pid
|
84
|
+
sleep(3)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
@processes.each do |pid|
|
89
|
+
Process.kill(9, pid)
|
90
|
+
end
|
37
91
|
end
|
38
|
-
$
|
92
|
+
$keep_running = false
|
39
93
|
end
|
40
94
|
end
|
41
95
|
|
42
|
-
def log(msg)
|
43
|
-
File.open("/tmp/yi.txt", "a") do |f|
|
44
|
-
f.puts msg
|
45
|
-
end
|
46
|
-
end
|
47
96
|
|
48
97
|
def process_alive?(pid)
|
49
98
|
return false unless pid
|
@@ -57,33 +106,45 @@ module LightDaemon
|
|
57
106
|
end
|
58
107
|
end
|
59
108
|
|
60
|
-
|
61
109
|
def start
|
62
|
-
|
110
|
+
@options[:children].times do
|
63
111
|
if pid = fork
|
64
112
|
@processes << pid
|
65
113
|
Process.detach(pid)
|
66
114
|
else
|
67
|
-
|
115
|
+
set_child
|
116
|
+
while($keep_running)
|
117
|
+
break unless @obj.send(:call)
|
118
|
+
end
|
119
|
+
return
|
68
120
|
end
|
69
121
|
end
|
70
122
|
|
71
|
-
while($
|
72
|
-
sleep(
|
123
|
+
while($keep_running)
|
124
|
+
sleep(@options[:monitor_cycle])
|
125
|
+
|
73
126
|
@processes.each_with_index do |pid, index|
|
74
127
|
unless process_alive?(pid)
|
75
128
|
if pid = fork
|
76
129
|
@processes[index] = pid
|
77
130
|
Process.detach(pid)
|
131
|
+
sleep(2)
|
78
132
|
else
|
79
|
-
|
133
|
+
set_child
|
134
|
+
while($keep_running)
|
135
|
+
break unless @obj.send(:call)
|
136
|
+
end
|
137
|
+
return
|
80
138
|
end
|
139
|
+
else
|
81
140
|
end
|
82
141
|
sleep(1)
|
83
142
|
end
|
84
143
|
end
|
144
|
+
self.class.clear_pid(@options[:pid_file])
|
85
145
|
end
|
86
146
|
|
147
|
+
# some code in this method is learned from gem daemons
|
87
148
|
def daemonize
|
88
149
|
fork && exit
|
89
150
|
unless Process.setsid
|
@@ -93,22 +154,14 @@ module LightDaemon
|
|
93
154
|
trap 'SIGHUP', 'IGNORE'
|
94
155
|
exit if fork
|
95
156
|
|
96
|
-
ObjectSpace.each_object(IO) do |io|
|
97
|
-
unless [STDIN, STDOUT, STDERR].include?(io)
|
98
|
-
begin
|
99
|
-
unless io.closed?
|
100
|
-
io.close
|
101
|
-
end
|
102
|
-
rescue ::Exception
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
157
|
begin; STDIN.reopen "/dev/null"; rescue ::Exception; end
|
108
158
|
begin; STDOUT.reopen "/dev/null"; rescue ::Exception; end
|
109
159
|
begin; STDERR.reopen STDOUT; rescue ::Exception; end
|
110
160
|
STDERR.sync = true
|
161
|
+
end
|
111
162
|
|
163
|
+
def set_child
|
164
|
+
@is_child = true
|
112
165
|
end
|
113
166
|
end
|
114
167
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: light-daemon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 49
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 9
|
9
|
-
-
|
10
|
-
version: 0.9.
|
9
|
+
- 5
|
10
|
+
version: 0.9.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Yi Zhang
|
@@ -15,11 +15,11 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-03-
|
18
|
+
date: 2012-03-10 00:00:00 -08:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
22
|
-
description: A simple and light daemon
|
22
|
+
description: A very simple and light ruby daemon API
|
23
23
|
email: yzhang.wa@gmail.com
|
24
24
|
executables: []
|
25
25
|
|