daemons 1.1.9 → 1.4.1
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.
- checksums.yaml +7 -0
- data/LICENSE +1 -1
- data/README.md +207 -0
- data/Releases +85 -24
- data/examples/call/call.rb +13 -16
- data/examples/call/call_monitor.rb +13 -17
- data/examples/daemonize/daemonize.rb +4 -8
- data/examples/run/ctrl_crash.rb +0 -1
- data/examples/run/ctrl_custom_logfiles.rb +18 -0
- data/examples/run/ctrl_exec.rb +0 -1
- data/examples/run/ctrl_exit.rb +0 -1
- data/examples/run/ctrl_keep_pid_files.rb +1 -3
- data/examples/run/ctrl_monitor.rb +0 -1
- data/examples/run/ctrl_monitor_multiple.rb +17 -0
- data/examples/run/ctrl_monitor_nocrash.rb +15 -0
- data/examples/run/ctrl_multiple.rb +0 -1
- data/examples/run/ctrl_ontop.rb +0 -1
- data/examples/run/ctrl_optionparser.rb +5 -7
- data/examples/run/ctrl_proc.rb +8 -9
- data/examples/run/ctrl_proc_multiple.rb +4 -6
- data/examples/run/ctrl_proc_rand.rb +2 -4
- data/examples/run/ctrl_proc_simple.rb +0 -1
- data/examples/run/myserver.rb +0 -1
- data/examples/run/myserver_crashing.rb +5 -5
- data/examples/run/myserver_exiting.rb +2 -2
- data/examples/run/myserver_hanging.rb +4 -5
- data/examples/run/myserver_slowstop.rb +5 -6
- data/lib/daemons/application.rb +235 -229
- data/lib/daemons/application_group.rb +115 -100
- data/lib/daemons/change_privilege.rb +2 -4
- data/lib/daemons/cmdline.rb +75 -62
- data/lib/daemons/controller.rb +36 -54
- data/lib/daemons/daemonize.rb +74 -75
- data/lib/daemons/etc_extension.rb +3 -4
- data/lib/daemons/exceptions.rb +11 -13
- data/lib/daemons/monitor.rb +57 -77
- data/lib/daemons/pid.rb +26 -56
- data/lib/daemons/pidfile.rb +49 -44
- data/lib/daemons/pidmem.rb +5 -9
- data/lib/daemons/reporter.rb +54 -0
- data/lib/daemons/syslogio.rb +240 -0
- data/lib/daemons/version.rb +3 -0
- data/lib/daemons.rb +87 -77
- metadata +111 -46
- data/README +0 -214
- data/Rakefile +0 -90
- data/TODO +0 -2
- data/setup.rb +0 -1360
data/lib/daemons/daemonize.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
module Daemonize
|
2
|
-
|
3
2
|
# Try to fork if at all possible retrying every 5 sec if the
|
4
3
|
# maximum process limit for the system has been reached
|
5
4
|
def safefork
|
@@ -18,152 +17,152 @@ module Daemonize
|
|
18
17
|
end
|
19
18
|
end
|
20
19
|
module_function :safefork
|
21
|
-
|
22
|
-
|
20
|
+
|
23
21
|
# Simulate the daemonization process (:ontop mode)
|
24
|
-
# NOTE:
|
22
|
+
# NOTE: $stdout and $stderr will not be redirected to the logfile,
|
25
23
|
# because in :ontop mode, we normally want to see the output
|
26
|
-
def simulate(logfile_name = nil)
|
24
|
+
def simulate(logfile_name = nil, app_name = nil)
|
25
|
+
$0 = app_name if app_name
|
26
|
+
|
27
27
|
# Release old working directory
|
28
|
-
Dir.chdir
|
28
|
+
Dir.chdir '/'
|
29
|
+
|
30
|
+
close_io
|
29
31
|
|
30
|
-
|
32
|
+
# Free $stdin and point it to somewhere sensible
|
33
|
+
begin; $stdin.reopen '/dev/null'; rescue ::Exception; end
|
31
34
|
|
32
|
-
#
|
33
|
-
|
35
|
+
# Split rand streams between spawning and daemonized process
|
36
|
+
srand
|
34
37
|
end
|
35
38
|
module_function :simulate
|
36
|
-
|
37
|
-
|
39
|
+
|
38
40
|
# Call a given block as a daemon
|
39
41
|
def call_as_daemon(block, logfile_name = nil, app_name = nil)
|
40
42
|
# we use a pipe to return the PID of the daemon
|
41
43
|
rd, wr = IO.pipe
|
42
|
-
|
44
|
+
|
43
45
|
if tmppid = safefork
|
44
46
|
# in the parent
|
45
|
-
|
47
|
+
|
46
48
|
wr.close
|
47
49
|
pid = rd.read.to_i
|
48
50
|
rd.close
|
49
|
-
|
51
|
+
|
50
52
|
Process.waitpid(tmppid)
|
51
|
-
|
53
|
+
|
52
54
|
return pid
|
53
55
|
else
|
54
56
|
# in the child
|
55
|
-
|
57
|
+
|
56
58
|
rd.close
|
57
|
-
|
59
|
+
|
58
60
|
# Detach from the controlling terminal
|
59
|
-
unless
|
60
|
-
|
61
|
+
unless Process.setsid
|
62
|
+
fail Daemons.RuntimeException.new('cannot detach from controlling terminal')
|
61
63
|
end
|
62
|
-
|
64
|
+
|
63
65
|
# Prevent the possibility of acquiring a controlling terminal
|
64
66
|
trap 'SIGHUP', 'IGNORE'
|
65
67
|
exit if pid = safefork
|
66
|
-
|
68
|
+
|
67
69
|
wr.write Process.pid
|
68
70
|
wr.close
|
69
|
-
|
71
|
+
|
70
72
|
$0 = app_name if app_name
|
71
|
-
|
73
|
+
|
72
74
|
# Release old working directory
|
73
|
-
Dir.chdir
|
74
|
-
|
75
|
-
close_io
|
75
|
+
Dir.chdir '/'
|
76
|
+
|
77
|
+
close_io
|
78
|
+
|
79
|
+
redirect_io(logfile_name)
|
76
80
|
|
77
|
-
redirect_io(logfile_name)
|
78
|
-
|
79
81
|
# Split rand streams between spawning and daemonized process
|
80
82
|
srand
|
81
|
-
|
83
|
+
|
82
84
|
block.call
|
83
|
-
|
85
|
+
|
84
86
|
exit
|
85
87
|
end
|
86
88
|
end
|
87
89
|
module_function :call_as_daemon
|
88
|
-
|
89
|
-
|
90
|
+
|
90
91
|
# Transform the current process into a daemon
|
91
92
|
def daemonize(logfile_name = nil, app_name = nil)
|
92
93
|
# Fork and exit from the parent
|
93
|
-
safefork
|
94
|
+
safefork && exit
|
94
95
|
|
95
96
|
# Detach from the controlling terminal
|
96
97
|
unless sess_id = Process.setsid
|
97
|
-
|
98
|
+
fail Daemons.RuntimeException.new('cannot detach from controlling terminal')
|
98
99
|
end
|
99
100
|
|
100
101
|
# Prevent the possibility of acquiring a controlling terminal
|
101
102
|
trap 'SIGHUP', 'IGNORE'
|
102
|
-
exit if
|
103
|
-
|
103
|
+
exit if safefork
|
104
|
+
|
104
105
|
$0 = app_name if app_name
|
105
|
-
|
106
|
+
|
106
107
|
# Release old working directory
|
107
|
-
Dir.chdir
|
108
|
+
Dir.chdir '/'
|
108
109
|
|
109
|
-
close_io
|
110
|
+
close_io
|
110
111
|
|
111
112
|
redirect_io(logfile_name)
|
112
|
-
|
113
|
+
|
113
114
|
# Split rand streams between spawning and daemonized process
|
114
115
|
srand
|
115
|
-
|
116
|
-
|
116
|
+
|
117
|
+
sess_id
|
117
118
|
end
|
118
119
|
module_function :daemonize
|
119
|
-
|
120
|
-
|
121
|
-
def close_io()
|
120
|
+
|
121
|
+
def close_io
|
122
122
|
# Make sure all input/output streams are closed
|
123
|
-
# Part I: close all IO objects (except for
|
123
|
+
# Part I: close all IO objects (except for $stdin/$stdout/$stderr)
|
124
124
|
ObjectSpace.each_object(IO) do |io|
|
125
|
-
unless [
|
126
|
-
|
127
|
-
unless io.closed?
|
128
|
-
io.close
|
129
|
-
end
|
130
|
-
rescue ::Exception
|
131
|
-
end
|
125
|
+
unless [$stdin, $stdout, $stderr].include?(io)
|
126
|
+
io.close rescue nil
|
132
127
|
end
|
133
128
|
end
|
134
|
-
|
129
|
+
|
135
130
|
# Make sure all input/output streams are closed
|
136
|
-
# Part II: close all file decriptors (except for
|
137
|
-
|
138
|
-
|
139
|
-
next if io.fileno < 3
|
140
|
-
io.close
|
131
|
+
# Part II: close all file decriptors (except for $stdin/$stdout/$stderr)
|
132
|
+
3.upto(8192) do |i|
|
133
|
+
IO.for_fd(i).close rescue nil
|
141
134
|
end
|
142
135
|
end
|
143
136
|
module_function :close_io
|
144
|
-
|
145
|
-
|
146
|
-
# Free STDIN/STDOUT/STDERR file descriptors and
|
137
|
+
|
138
|
+
# Free $stdin/$stdout/$stderr file descriptors and
|
147
139
|
# point them somewhere sensible
|
148
140
|
def redirect_io(logfile_name)
|
149
|
-
begin;
|
150
|
-
|
151
|
-
if logfile_name
|
141
|
+
begin; $stdin.reopen '/dev/null'; rescue ::Exception; end
|
142
|
+
|
143
|
+
if logfile_name == 'SYSLOG'
|
144
|
+
# attempt to use syslog via syslogio
|
152
145
|
begin
|
153
|
-
|
154
|
-
|
155
|
-
|
146
|
+
require 'syslogio'
|
147
|
+
$stdout = ::Daemons::SyslogIO.new($0, :local0, :info, $stdout)
|
148
|
+
$stderr = ::Daemons::SyslogIO.new($0, :local0, :err, $stderr)
|
149
|
+
# error out early so we can fallback to null
|
150
|
+
$stdout.puts "no logfile provided, output redirected to syslog"
|
156
151
|
rescue ::Exception
|
157
|
-
|
152
|
+
# on unsupported platforms simply reopen /dev/null
|
153
|
+
begin; $stdout.reopen '/dev/null'; rescue ::Exception; end
|
154
|
+
begin; $stderr.reopen '/dev/null'; rescue ::Exception; end
|
158
155
|
end
|
156
|
+
elsif logfile_name
|
157
|
+
$stdout.reopen logfile_name, 'a'
|
158
|
+
File.chmod(0644, logfile_name)
|
159
|
+
$stdout.sync = true
|
160
|
+
begin; $stderr.reopen $stdout; rescue ::Exception; end
|
161
|
+
$stderr.sync = true
|
159
162
|
else
|
160
|
-
begin;
|
163
|
+
begin; $stdout.reopen '/dev/null'; rescue ::Exception; end
|
164
|
+
begin; $stderr.reopen '/dev/null'; rescue ::Exception; end
|
161
165
|
end
|
162
|
-
|
163
|
-
begin; STDERR.reopen STDOUT; rescue ::Exception; end
|
164
|
-
STDERR.sync = true
|
165
166
|
end
|
166
167
|
module_function :redirect_io
|
167
|
-
|
168
|
-
|
169
168
|
end
|
@@ -2,11 +2,10 @@ require 'etc'
|
|
2
2
|
|
3
3
|
Etc.instance_eval do
|
4
4
|
def groupname(gid)
|
5
|
-
Etc.group {|e| return e.name if gid == e.gid }
|
6
|
-
nil
|
5
|
+
Etc.group { |e| return e.name if gid == e.gid }
|
7
6
|
end
|
7
|
+
|
8
8
|
def username(uid)
|
9
|
-
Etc.passwd {|e| return e.name if uid == e.uid }
|
10
|
-
nil
|
9
|
+
Etc.passwd { |e| return e.name if uid == e.uid }
|
11
10
|
end
|
12
11
|
end
|
data/lib/daemons/exceptions.rb
CHANGED
@@ -1,28 +1,26 @@
|
|
1
|
-
|
2
1
|
module Daemons
|
3
|
-
|
4
|
-
class Exception < ::RuntimeError
|
2
|
+
class Exception < RuntimeError
|
5
3
|
end
|
6
|
-
|
4
|
+
|
7
5
|
class RuntimeException < Exception
|
8
6
|
end
|
9
|
-
|
7
|
+
|
10
8
|
class CmdException < Exception
|
11
9
|
end
|
12
|
-
|
10
|
+
|
13
11
|
class Error < Exception
|
14
12
|
end
|
15
|
-
|
13
|
+
|
16
14
|
class SystemError < Error
|
17
|
-
|
18
15
|
attr_reader :system_error
|
19
|
-
|
16
|
+
|
20
17
|
def initialize(msg, system_error)
|
21
18
|
super(msg)
|
22
|
-
|
19
|
+
|
23
20
|
@system_error = system_error
|
24
21
|
end
|
25
|
-
|
26
22
|
end
|
27
|
-
|
28
|
-
|
23
|
+
|
24
|
+
class TimeoutError < Error
|
25
|
+
end
|
26
|
+
end
|
data/lib/daemons/monitor.rb
CHANGED
@@ -1,95 +1,78 @@
|
|
1
|
+
require 'daemons/exceptions'
|
1
2
|
|
2
3
|
module Daemons
|
3
|
-
|
4
4
|
require 'daemons/daemonize'
|
5
|
-
|
5
|
+
|
6
6
|
class Monitor
|
7
|
-
|
8
7
|
def self.find(dir, app_name)
|
9
8
|
pid = PidFile.find_files(dir, app_name, false)[0]
|
10
|
-
|
9
|
+
|
11
10
|
if pid
|
12
11
|
pid = PidFile.existing(pid)
|
13
|
-
|
12
|
+
|
14
13
|
unless PidFile.running?(pid.pid)
|
15
14
|
begin; pid.cleanup; rescue ::Exception; end
|
16
15
|
return
|
17
16
|
end
|
18
|
-
|
19
|
-
monitor =
|
20
|
-
|
17
|
+
|
18
|
+
monitor = allocate
|
19
|
+
|
21
20
|
monitor.instance_variable_set(:@pid, pid)
|
22
|
-
|
21
|
+
|
23
22
|
return monitor
|
24
23
|
end
|
25
|
-
|
26
|
-
|
24
|
+
|
25
|
+
nil
|
27
26
|
end
|
28
|
-
|
29
|
-
|
30
|
-
def initialize(an_app)
|
27
|
+
|
28
|
+
def initialize(an_app, options = {})
|
31
29
|
@app = an_app
|
32
30
|
@app_name = an_app.group.app_name + '_monitor'
|
33
|
-
|
31
|
+
@monitor_interval = options[:monitor_interval] || 30
|
32
|
+
|
34
33
|
if an_app.pidfile_dir
|
35
34
|
@pid = PidFile.new(an_app.pidfile_dir, @app_name, false)
|
36
35
|
else
|
37
36
|
@pid = PidMem.new
|
38
37
|
end
|
39
38
|
end
|
40
|
-
|
41
|
-
def watch(
|
42
|
-
sleep(
|
43
|
-
|
39
|
+
|
40
|
+
def watch(application_group)
|
41
|
+
sleep(5)
|
42
|
+
|
44
43
|
loop do
|
45
|
-
applications.each
|
46
|
-
sleep(10)
|
47
|
-
|
44
|
+
application_group.applications.each do |a|
|
48
45
|
unless a.running?
|
49
46
|
a.zap!
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
47
|
+
|
48
|
+
sleep(1)
|
49
|
+
|
50
|
+
Process.detach(fork { a.start(true) })
|
51
|
+
|
52
|
+
sleep(5)
|
54
53
|
end
|
55
|
-
|
56
|
-
|
57
|
-
sleep(
|
54
|
+
end
|
55
|
+
|
56
|
+
sleep(@monitor_interval)
|
58
57
|
end
|
59
58
|
end
|
60
59
|
private :watch
|
61
|
-
|
62
|
-
|
63
|
-
def start_with_pidfile(applications)
|
60
|
+
|
61
|
+
def start_with_pidfile(application_group)
|
64
62
|
fork do
|
65
63
|
Daemonize.daemonize(nil, @app_name)
|
66
|
-
|
67
|
-
begin
|
64
|
+
|
65
|
+
begin
|
68
66
|
@pid.pid = Process.pid
|
69
|
-
|
70
|
-
# at_exit {
|
71
|
-
# begin; @pid.cleanup; rescue ::Exception; end
|
72
|
-
# }
|
73
|
-
|
74
|
-
# This part is needed to remove the pid-file if the application is killed by
|
75
|
-
# daemons or manually by the user.
|
76
|
-
# Note that the applications is not supposed to overwrite the signal handler for
|
77
|
-
# 'TERM'.
|
78
|
-
#
|
79
|
-
# trap('TERM') {
|
80
|
-
# begin; @pid.cleanup; rescue ::Exception; end
|
81
|
-
# exit
|
82
|
-
# }
|
83
|
-
|
84
|
-
watch(applications)
|
67
|
+
watch(application_group)
|
85
68
|
rescue ::Exception => e
|
86
69
|
begin
|
87
|
-
File.open(@app.logfile, 'a')
|
70
|
+
File.open(@app.logfile, 'a') do |f|
|
88
71
|
f.puts Time.now
|
89
72
|
f.puts e
|
90
73
|
f.puts e.backtrace.inspect
|
91
|
-
|
92
|
-
ensure
|
74
|
+
end
|
75
|
+
ensure
|
93
76
|
begin; @pid.cleanup; rescue ::Exception; end
|
94
77
|
exit!
|
95
78
|
end
|
@@ -97,42 +80,39 @@ module Daemons
|
|
97
80
|
end
|
98
81
|
end
|
99
82
|
private :start_with_pidfile
|
100
|
-
|
101
|
-
def start_without_pidfile(
|
102
|
-
Thread.new { watch(
|
83
|
+
|
84
|
+
def start_without_pidfile(application_group)
|
85
|
+
Thread.new { watch(application_group) }
|
103
86
|
end
|
104
87
|
private :start_without_pidfile
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
88
|
+
|
89
|
+
def start(application_group)
|
90
|
+
return if application_group.applications.empty?
|
91
|
+
|
110
92
|
if @pid.kind_of?(PidFile)
|
111
|
-
start_with_pidfile(
|
93
|
+
start_with_pidfile(application_group)
|
112
94
|
else
|
113
|
-
start_without_pidfile(
|
95
|
+
start_without_pidfile(application_group)
|
114
96
|
end
|
115
97
|
end
|
116
|
-
|
117
|
-
|
98
|
+
|
118
99
|
def stop
|
119
100
|
begin
|
120
101
|
pid = @pid.pid
|
121
102
|
Process.kill(Application::SIGNAL, pid)
|
122
|
-
|
123
|
-
|
124
|
-
|
103
|
+
Timeout.timeout(5, TimeoutError) do
|
104
|
+
while Pid.running?(pid)
|
105
|
+
sleep(0.1)
|
106
|
+
end
|
125
107
|
end
|
126
|
-
}
|
127
108
|
rescue ::Exception => e
|
128
|
-
puts "#{
|
129
|
-
puts "deleting pid-file."
|
109
|
+
$stderr.puts "exception while trying to stop monitor process #{pid}: #{e}"
|
110
|
+
$stderr.puts "deleting pid-file."
|
130
111
|
end
|
131
|
-
|
132
|
-
# We try to remove the pid-files by ourselves, in case the
|
112
|
+
|
113
|
+
# We try to remove the pid-files by ourselves, in case the monitor
|
133
114
|
# didn't clean it up.
|
134
|
-
begin; @pid.
|
115
|
+
begin; @pid.zap; rescue ::Exception; end
|
135
116
|
end
|
136
|
-
|
137
|
-
|
138
|
-
end
|
117
|
+
end
|
118
|
+
end
|
data/lib/daemons/pid.rb
CHANGED
@@ -1,12 +1,10 @@
|
|
1
|
-
|
1
|
+
require 'daemons/exceptions'
|
2
2
|
|
3
3
|
module Daemons
|
4
|
-
|
5
4
|
class Pid
|
6
|
-
|
7
|
-
def Pid.running?(pid)
|
5
|
+
def self.running?(pid)
|
8
6
|
return false unless pid
|
9
|
-
|
7
|
+
|
10
8
|
# Check if process is in existence
|
11
9
|
# The simplest way to do this is to send signal '0'
|
12
10
|
# (which is a single system call) that doesn't actually
|
@@ -14,95 +12,67 @@ module Daemons
|
|
14
12
|
begin
|
15
13
|
Process.kill(0, pid)
|
16
14
|
return true
|
15
|
+
rescue TimeoutError
|
16
|
+
raise
|
17
17
|
rescue Errno::ESRCH
|
18
18
|
return false
|
19
19
|
rescue ::Exception # for example on EPERM (process exists but does not belong to us)
|
20
20
|
return true
|
21
|
-
#rescue Errno::EPERM
|
22
|
-
# return false
|
23
21
|
end
|
24
22
|
end
|
25
|
-
|
26
|
-
# def Pid.running?(pid, additional = nil)
|
27
|
-
# match_pid = Regexp.new("^\\s*#{pid}\\s")
|
28
|
-
# got_match = false
|
29
|
-
#
|
30
|
-
# #ps_all = IO.popen('ps ax') # the correct syntax is without a dash (-) !
|
31
|
-
# ps_in, ps_out, ps_err = Open3.popen3('ps ax') # the correct syntax is without a dash (-) !
|
32
|
-
#
|
33
|
-
# return true unless ps_out.gets
|
34
|
-
#
|
35
|
-
# begin
|
36
|
-
# ps_out.each { |psline|
|
37
|
-
# next unless psline =~ match_pid
|
38
|
-
# got_match = true
|
39
|
-
# got_match = false if additional and psline !~ /#{additional}/
|
40
|
-
# break
|
41
|
-
# }
|
42
|
-
# ensure
|
43
|
-
# begin; begin; ps_in.close; rescue ::Exception; end; begin; ps_out.close; rescue ::Exception; end; ps_err.close; rescue ::Exception; end
|
44
|
-
# end
|
45
|
-
#
|
46
|
-
# # an alternative would be to use the code below, but I don't know whether this is portable
|
47
|
-
# # `ps axo pid=`.split.include? pid.to_s
|
48
|
-
#
|
49
|
-
# return got_match
|
50
|
-
# end
|
51
|
-
|
52
|
-
|
53
|
-
|
23
|
+
|
54
24
|
# Returns the directory that should be used to write the pid file to
|
55
25
|
# depending on the given mode.
|
56
|
-
#
|
57
|
-
# Some modes may require an additionaly hint, others may determine
|
26
|
+
#
|
27
|
+
# Some modes may require an additionaly hint, others may determine
|
58
28
|
# the directory automatically.
|
59
29
|
#
|
60
30
|
# If no valid directory is found, returns nil.
|
61
31
|
#
|
62
|
-
def
|
32
|
+
def self.dir(dir_mode, dir, script)
|
63
33
|
# nil script parameter is allowed as long as dir_mode is not :script
|
64
|
-
return nil if dir_mode == :script && script.nil?
|
65
|
-
|
34
|
+
return nil if dir_mode == :script && script.nil?
|
35
|
+
|
66
36
|
case dir_mode
|
67
37
|
when :normal
|
68
38
|
return File.expand_path(dir)
|
69
39
|
when :script
|
70
|
-
return File.expand_path(File.join(File.dirname(script),dir))
|
71
|
-
when :system
|
40
|
+
return File.expand_path(File.join(File.dirname(script), dir))
|
41
|
+
when :system
|
72
42
|
return '/var/run'
|
73
43
|
else
|
74
|
-
|
44
|
+
fail Error.new("pid file mode '#{dir_mode}' not implemented")
|
75
45
|
end
|
76
46
|
end
|
77
|
-
|
47
|
+
|
78
48
|
# Initialization method
|
79
49
|
def initialize
|
80
50
|
end
|
81
|
-
|
82
|
-
|
51
|
+
|
83
52
|
# Get method
|
84
53
|
def pid
|
85
54
|
end
|
86
|
-
|
55
|
+
|
87
56
|
# Set method
|
88
57
|
def pid=(p)
|
89
58
|
end
|
90
|
-
|
59
|
+
|
91
60
|
# Check whether the process is running
|
92
61
|
def running?
|
93
|
-
|
62
|
+
Pid.running?(pid)
|
94
63
|
end
|
95
|
-
|
64
|
+
|
96
65
|
# Cleanup method
|
97
66
|
def cleanup
|
98
67
|
end
|
99
68
|
|
69
|
+
# Zap method
|
70
|
+
def zap
|
71
|
+
end
|
72
|
+
|
100
73
|
# Exist? method
|
101
74
|
def exist?
|
102
75
|
true
|
103
76
|
end
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
end
|
77
|
+
end
|
78
|
+
end
|