daemons 1.1.9 → 1.2.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 +206 -0
- data/Releases +17 -0
- 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_multiple.rb +0 -1
- data/examples/run/ctrl_ontop.rb +0 -1
- data/examples/run/ctrl_optionparser.rb +4 -6
- 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.rb +66 -68
- data/lib/daemons/application.rb +171 -188
- data/lib/daemons/application_group.rb +99 -92
- data/lib/daemons/change_privilege.rb +3 -3
- data/lib/daemons/cmdline.rb +43 -54
- data/lib/daemons/controller.rb +36 -53
- data/lib/daemons/daemonize.rb +54 -64
- data/lib/daemons/etc_extension.rb +3 -2
- data/lib/daemons/exceptions.rb +10 -11
- data/lib/daemons/monitor.rb +60 -62
- data/lib/daemons/pid.rb +24 -56
- data/lib/daemons/pidfile.rb +38 -40
- data/lib/daemons/pidmem.rb +5 -9
- data/lib/daemons/version.rb +3 -0
- metadata +45 -45
- data/README +0 -214
- data/Rakefile +0 -90
- data/TODO +0 -2
- data/setup.rb +0 -1360
data/lib/daemons/controller.rb
CHANGED
@@ -1,70 +1,57 @@
|
|
1
1
|
|
2
2
|
module Daemons
|
3
3
|
class Controller
|
4
|
-
|
5
4
|
attr_reader :app_name
|
6
|
-
|
5
|
+
|
7
6
|
attr_reader :group
|
8
|
-
|
7
|
+
|
9
8
|
attr_reader :options
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
'start',
|
14
|
-
'stop',
|
15
|
-
'restart',
|
16
|
-
'run',
|
17
|
-
'zap',
|
18
|
-
'reload',
|
19
|
-
'status'
|
20
|
-
]
|
21
|
-
|
9
|
+
|
10
|
+
COMMANDS = %w(start stop restart run zap reload status)
|
11
|
+
|
22
12
|
def initialize(options = {}, argv = [])
|
23
13
|
@options = options
|
24
14
|
@argv = argv
|
25
|
-
|
15
|
+
|
26
16
|
# Allow an app_name to be specified. If not specified use the
|
27
17
|
# basename of the script.
|
28
18
|
@app_name = options[:app_name]
|
29
|
-
|
19
|
+
|
30
20
|
if options[:script]
|
31
21
|
@script = File.expand_path(options[:script])
|
32
|
-
|
22
|
+
|
33
23
|
@app_name ||= File.split(@script)[1]
|
34
24
|
end
|
35
|
-
|
25
|
+
|
36
26
|
@app_name ||= 'unknown_application'
|
37
|
-
|
27
|
+
|
38
28
|
@command, @controller_part, @app_part = Controller.split_argv(argv)
|
39
|
-
|
40
|
-
|
41
|
-
|
29
|
+
|
30
|
+
# @options[:dir_mode] ||= :script
|
31
|
+
|
42
32
|
@optparse = Optparse.new(self)
|
43
33
|
end
|
44
|
-
|
45
|
-
|
34
|
+
|
46
35
|
# This function is used to do a final update of the options passed to the application
|
47
36
|
# before they are really used.
|
48
37
|
#
|
49
38
|
# Note that this function should only update <tt>@options</tt> and no other variables.
|
50
39
|
#
|
51
40
|
def setup_options
|
52
|
-
|
41
|
+
# @options[:ontop] ||= true
|
53
42
|
end
|
54
|
-
|
43
|
+
|
55
44
|
def run
|
56
|
-
@options.update @optparse.parse(@controller_part).delete_if {|k,v| !v}
|
57
|
-
|
58
|
-
setup_options
|
59
|
-
|
60
|
-
#pp @options
|
45
|
+
@options.update @optparse.parse(@controller_part).delete_if { |k, v| !v }
|
46
|
+
|
47
|
+
setup_options
|
61
48
|
|
62
49
|
@group = ApplicationGroup.new(@app_name, @options)
|
63
50
|
@group.controller_argv = @controller_part
|
64
51
|
@group.app_argv = @app_part
|
65
|
-
|
52
|
+
|
66
53
|
@group.setup
|
67
|
-
|
54
|
+
|
68
55
|
case @command
|
69
56
|
when 'start'
|
70
57
|
@group.new_application.start
|
@@ -79,7 +66,7 @@ module Daemons
|
|
79
66
|
sleep(1)
|
80
67
|
@group.start_all
|
81
68
|
else
|
82
|
-
puts "
|
69
|
+
$stderr.puts "#{@group.app_name}: warning: no instances running. Starting..."
|
83
70
|
@group.new_application.start
|
84
71
|
end
|
85
72
|
when 'reload'
|
@@ -89,21 +76,18 @@ module Daemons
|
|
89
76
|
when 'status'
|
90
77
|
unless @group.applications.empty?
|
91
78
|
@group.show_status
|
79
|
+
exit 3 if not @group.running? # exit with status 3 to indicate that no apps are running
|
92
80
|
else
|
93
|
-
puts "#{@group.app_name}: no instances running"
|
81
|
+
$stderr.puts "#{@group.app_name}: no instances running"
|
82
|
+
exit 3 # exit with status 3 to indicate that no apps are running
|
94
83
|
end
|
95
84
|
when nil
|
96
|
-
|
97
|
-
#puts "ERROR: No command given"; puts
|
98
|
-
|
99
|
-
#print_usage()
|
100
|
-
#raise('usage function not implemented')
|
85
|
+
fail CmdException.new('no command given')
|
101
86
|
else
|
102
|
-
|
87
|
+
fail Error.new("command '#{@command}' not implemented")
|
103
88
|
end
|
104
89
|
end
|
105
|
-
|
106
|
-
|
90
|
+
|
107
91
|
# Split an _argv_ array.
|
108
92
|
# +argv+ is assumed to be in the following format:
|
109
93
|
# ['command', 'controller option 1', 'controller option 2', ..., '--', 'app option 1', ...]
|
@@ -113,28 +97,27 @@ module Daemons
|
|
113
97
|
# *Returns*: the command as a string, the controller options as an array, the appliation options
|
114
98
|
# as an array
|
115
99
|
#
|
116
|
-
def
|
100
|
+
def self.split_argv(argv)
|
117
101
|
argv = argv.dup
|
118
|
-
|
102
|
+
|
119
103
|
command = nil
|
120
104
|
controller_part = []
|
121
105
|
app_part = []
|
122
|
-
|
106
|
+
|
123
107
|
if COMMANDS.include? argv[0]
|
124
108
|
command = argv.shift
|
125
109
|
end
|
126
|
-
|
110
|
+
|
127
111
|
if i = argv.index('--')
|
128
112
|
# Handle the case where no controller options are given, just
|
129
113
|
# options after "--" as well (i == 0)
|
130
|
-
controller_part = (i == 0 ? [] : argv[0..i-1])
|
131
|
-
app_part = argv[i+1..-1]
|
114
|
+
controller_part = (i == 0 ? [] : argv[0..i - 1])
|
115
|
+
app_part = argv[i + 1..-1]
|
132
116
|
else
|
133
117
|
controller_part = argv[0..-1]
|
134
118
|
end
|
135
|
-
|
136
|
-
|
119
|
+
|
120
|
+
[command, controller_part, app_part]
|
137
121
|
end
|
138
122
|
end
|
139
|
-
|
140
123
|
end
|
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,143 @@ 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: STDOUT and STDERR will not be redirected to the logfile,
|
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
61
|
unless sess_id = Process.setsid
|
60
|
-
|
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
103
|
exit if pid = safefork
|
103
|
-
|
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
123
|
# Part I: close all IO objects (except for STDIN/STDOUT/STDERR)
|
124
124
|
ObjectSpace.each_object(IO) do |io|
|
125
125
|
unless [STDIN, STDOUT, STDERR].include?(io)
|
126
|
-
|
127
|
-
unless io.closed?
|
128
|
-
io.close
|
129
|
-
end
|
130
|
-
rescue ::Exception
|
131
|
-
end
|
126
|
+
io.close rescue nil
|
132
127
|
end
|
133
128
|
end
|
134
|
-
|
129
|
+
|
135
130
|
# Make sure all input/output streams are closed
|
136
131
|
# Part II: close all file decriptors (except for STDIN/STDOUT/STDERR)
|
137
|
-
|
138
|
-
|
139
|
-
next if io.fileno < 3
|
140
|
-
io.close
|
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
|
-
|
137
|
+
|
146
138
|
# Free STDIN/STDOUT/STDERR file descriptors and
|
147
139
|
# point them somewhere sensible
|
148
140
|
def redirect_io(logfile_name)
|
149
|
-
begin; STDIN.reopen
|
150
|
-
|
141
|
+
begin; STDIN.reopen '/dev/null'; rescue ::Exception; end
|
142
|
+
|
151
143
|
if logfile_name
|
152
144
|
begin
|
153
|
-
STDOUT.reopen logfile_name,
|
145
|
+
STDOUT.reopen logfile_name, 'a'
|
154
146
|
File.chmod(0644, logfile_name)
|
155
147
|
STDOUT.sync = true
|
156
148
|
rescue ::Exception
|
157
|
-
begin; STDOUT.reopen
|
149
|
+
begin; STDOUT.reopen '/dev/null'; rescue ::Exception; end
|
158
150
|
end
|
159
151
|
else
|
160
|
-
begin; STDOUT.reopen
|
152
|
+
begin; STDOUT.reopen '/dev/null'; rescue ::Exception; end
|
161
153
|
end
|
162
|
-
|
154
|
+
|
163
155
|
begin; STDERR.reopen STDOUT; rescue ::Exception; end
|
164
156
|
STDERR.sync = true
|
165
157
|
end
|
166
158
|
module_function :redirect_io
|
167
|
-
|
168
|
-
|
169
159
|
end
|
@@ -2,11 +2,12 @@ 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 }
|
5
|
+
Etc.group { |e| return e.name if gid == e.gid }
|
6
6
|
nil
|
7
7
|
end
|
8
|
+
|
8
9
|
def username(uid)
|
9
|
-
Etc.passwd {|e| return e.name if uid == e.uid }
|
10
|
+
Etc.passwd { |e| return e.name if uid == e.uid }
|
10
11
|
nil
|
11
12
|
end
|
12
13
|
end
|
data/lib/daemons/exceptions.rb
CHANGED
@@ -1,28 +1,27 @@
|
|
1
1
|
|
2
2
|
module Daemons
|
3
|
-
|
4
3
|
class Exception < ::RuntimeError
|
5
4
|
end
|
6
|
-
|
5
|
+
|
7
6
|
class RuntimeException < Exception
|
8
7
|
end
|
9
|
-
|
8
|
+
|
10
9
|
class CmdException < Exception
|
11
10
|
end
|
12
|
-
|
11
|
+
|
13
12
|
class Error < Exception
|
14
13
|
end
|
15
|
-
|
14
|
+
|
16
15
|
class SystemError < Error
|
17
|
-
|
18
16
|
attr_reader :system_error
|
19
|
-
|
17
|
+
|
20
18
|
def initialize(msg, system_error)
|
21
19
|
super(msg)
|
22
|
-
|
20
|
+
|
23
21
|
@system_error = system_error
|
24
22
|
end
|
25
|
-
|
26
23
|
end
|
27
|
-
|
28
|
-
|
24
|
+
|
25
|
+
class TimeoutError < Error
|
26
|
+
end
|
27
|
+
end
|
data/lib/daemons/monitor.rb
CHANGED
@@ -1,77 +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
|
-
|
27
|
+
|
30
28
|
def initialize(an_app)
|
31
29
|
@app = an_app
|
32
30
|
@app_name = an_app.group.app_name + '_monitor'
|
33
|
-
|
31
|
+
|
34
32
|
if an_app.pidfile_dir
|
35
33
|
@pid = PidFile.new(an_app.pidfile_dir, @app_name, false)
|
36
34
|
else
|
37
35
|
@pid = PidMem.new
|
38
36
|
end
|
39
37
|
end
|
40
|
-
|
41
|
-
def watch(
|
42
|
-
sleep(
|
43
|
-
|
38
|
+
|
39
|
+
def watch(application_group)
|
40
|
+
sleep(5)
|
41
|
+
|
44
42
|
loop do
|
45
|
-
applications.each
|
46
|
-
sleep(10)
|
47
|
-
|
43
|
+
application_group.applications.each do |a|
|
48
44
|
unless a.running?
|
49
45
|
a.zap!
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
46
|
+
|
47
|
+
sleep(1)
|
48
|
+
|
49
|
+
Process.detach(fork { a.start(restart = true) })
|
50
|
+
|
51
|
+
sleep(5)
|
52
|
+
|
53
|
+
# application_group.setup
|
54
54
|
end
|
55
|
-
|
56
|
-
|
57
|
-
sleep(
|
55
|
+
end
|
56
|
+
|
57
|
+
# sleep(5)
|
58
|
+
# application_group.setup
|
59
|
+
# sleep(30)
|
58
60
|
end
|
59
61
|
end
|
60
62
|
private :watch
|
61
|
-
|
62
|
-
|
63
|
-
def start_with_pidfile(applications)
|
63
|
+
|
64
|
+
def start_with_pidfile(application_group)
|
64
65
|
fork do
|
65
66
|
Daemonize.daemonize(nil, @app_name)
|
66
|
-
|
67
|
-
begin
|
67
|
+
|
68
|
+
begin
|
68
69
|
@pid.pid = Process.pid
|
69
|
-
|
70
|
+
|
70
71
|
# at_exit {
|
71
72
|
# begin; @pid.cleanup; rescue ::Exception; end
|
72
73
|
# }
|
73
|
-
|
74
|
-
# This part is needed to remove the pid-file if the application is killed by
|
74
|
+
|
75
|
+
# This part is needed to remove the pid-file if the application is killed by
|
75
76
|
# daemons or manually by the user.
|
76
77
|
# Note that the applications is not supposed to overwrite the signal handler for
|
77
78
|
# 'TERM'.
|
@@ -80,16 +81,16 @@ module Daemons
|
|
80
81
|
# begin; @pid.cleanup; rescue ::Exception; end
|
81
82
|
# exit
|
82
83
|
# }
|
83
|
-
|
84
|
-
watch(
|
84
|
+
|
85
|
+
watch(application_group)
|
85
86
|
rescue ::Exception => e
|
86
87
|
begin
|
87
|
-
File.open(@app.logfile, 'a')
|
88
|
+
File.open(@app.logfile, 'a') do |f|
|
88
89
|
f.puts Time.now
|
89
90
|
f.puts e
|
90
91
|
f.puts e.backtrace.inspect
|
91
|
-
|
92
|
-
ensure
|
92
|
+
end
|
93
|
+
ensure
|
93
94
|
begin; @pid.cleanup; rescue ::Exception; end
|
94
95
|
exit!
|
95
96
|
end
|
@@ -97,42 +98,39 @@ module Daemons
|
|
97
98
|
end
|
98
99
|
end
|
99
100
|
private :start_with_pidfile
|
100
|
-
|
101
|
-
def start_without_pidfile(
|
102
|
-
Thread.new { watch(
|
101
|
+
|
102
|
+
def start_without_pidfile(application_group)
|
103
|
+
Thread.new { watch(application_group) }
|
103
104
|
end
|
104
105
|
private :start_without_pidfile
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
106
|
+
|
107
|
+
def start(application_group)
|
108
|
+
return if application_group.applications.empty?
|
109
|
+
|
110
110
|
if @pid.kind_of?(PidFile)
|
111
|
-
start_with_pidfile(
|
111
|
+
start_with_pidfile(application_group)
|
112
112
|
else
|
113
|
-
start_without_pidfile(
|
113
|
+
start_without_pidfile(application_group)
|
114
114
|
end
|
115
115
|
end
|
116
|
-
|
117
|
-
|
116
|
+
|
118
117
|
def stop
|
119
118
|
begin
|
120
119
|
pid = @pid.pid
|
121
120
|
Process.kill(Application::SIGNAL, pid)
|
122
|
-
|
123
|
-
|
124
|
-
|
121
|
+
Timeout.timeout(5, TimeoutError) do
|
122
|
+
while Pid.running?(pid)
|
123
|
+
sleep(0.1)
|
124
|
+
end
|
125
125
|
end
|
126
|
-
}
|
127
126
|
rescue ::Exception => e
|
128
127
|
puts "#{e} #{pid}"
|
129
|
-
puts
|
128
|
+
puts 'deleting pid-file.'
|
130
129
|
end
|
131
|
-
|
130
|
+
|
132
131
|
# We try to remove the pid-files by ourselves, in case the application
|
133
132
|
# didn't clean it up.
|
134
133
|
begin; @pid.cleanup; rescue ::Exception; end
|
135
134
|
end
|
136
|
-
|
137
|
-
|
138
|
-
end
|
135
|
+
end
|
136
|
+
end
|