mlanett-daemons 1.0.13 → 1.1.10.2
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/Gemfile.lock +12 -2
- data/LICENSE +1 -8
- data/README-mlanett.rdoc +8 -0
- data/{README → README.rdoc} +6 -15
- data/Releases +84 -9
- data/TODO +1 -5
- data/daemons.gemspec +1 -0
- data/examples/call/call.rb +1 -0
- data/examples/daemonize/daemonize.rb +10 -3
- data/examples/run/ctrl_hanging.rb +19 -0
- data/examples/run/ctrl_monitor_multiple.rb +18 -0
- data/examples/run/ctrl_normal.rb +0 -1
- data/examples/run/ctrl_proc.rb.output +20 -0
- data/examples/run/ctrl_proc_rand.rb +23 -0
- data/examples/run/ctrl_slowstop.rb +16 -0
- data/examples/run/myserver_crashing.rb +2 -2
- data/examples/run/myserver_hanging.rb +21 -0
- data/examples/run/myserver_slowstop.rb +21 -0
- data/lib/daemons.rb +38 -10
- data/lib/daemons/application.rb +131 -26
- data/lib/daemons/application_group.rb +58 -10
- data/lib/daemons/change_privilege.rb +19 -0
- data/lib/daemons/cmdline.rb +10 -6
- data/lib/daemons/controller.rb +5 -2
- data/lib/daemons/daemonize.rb +64 -150
- data/lib/daemons/etc_extension.rb +12 -0
- data/lib/daemons/exceptions.rb +3 -0
- data/lib/daemons/monitor.rb +27 -19
- data/lib/daemons/pid.rb +13 -14
- data/lib/daemons/pidfile.rb +14 -7
- data/lib/daemons/pidmem.rb +9 -0
- data/lib/daemons/version.rb +1 -1
- data/spec/pidfile_spec.rb +12 -0
- data/spec/spec_helper.rb +1 -0
- metadata +31 -47
- data/daemons.tmproj +0 -56
- data/examples/run/myserver_crashing.rb.output +0 -30
- data/html/classes/Daemonize.html +0 -497
- data/html/classes/Daemons.html +0 -683
- data/html/classes/Daemons/Application.html +0 -836
- data/html/classes/Daemons/ApplicationGroup.html +0 -508
- data/html/classes/Daemons/CmdException.html +0 -113
- data/html/classes/Daemons/Controller.html +0 -429
- data/html/classes/Daemons/Error.html +0 -113
- data/html/classes/Daemons/Exception.html +0 -111
- data/html/classes/Daemons/Monitor.html +0 -263
- data/html/classes/Daemons/Optparse.html +0 -244
- data/html/classes/Daemons/Pid.html +0 -339
- data/html/classes/Daemons/PidFile.html +0 -441
- data/html/classes/Daemons/PidMem.html +0 -126
- data/html/classes/Daemons/RuntimeException.html +0 -113
- data/html/classes/Daemons/SystemError.html +0 -163
- data/html/created.rid +0 -1
- data/html/files/README.html +0 -377
- data/html/files/Releases.html +0 -342
- data/html/files/TODO.html +0 -121
- data/html/files/lib/daemons/application_group_rb.html +0 -101
- data/html/files/lib/daemons/application_rb.html +0 -110
- data/html/files/lib/daemons/cmdline_rb.html +0 -101
- data/html/files/lib/daemons/controller_rb.html +0 -101
- data/html/files/lib/daemons/daemonize_rb.html +0 -207
- data/html/files/lib/daemons/exceptions_rb.html +0 -101
- data/html/files/lib/daemons/monitor_rb.html +0 -108
- data/html/files/lib/daemons/pid_rb.html +0 -108
- data/html/files/lib/daemons/pidfile_rb.html +0 -108
- data/html/files/lib/daemons/pidmem_rb.html +0 -108
- data/html/files/lib/daemons_rb.html +0 -117
- data/html/fr_class_index.html +0 -41
- data/html/fr_file_index.html +0 -40
- data/html/fr_method_index.html +0 -91
- data/html/index.html +0 -24
- data/html/rdoc-style.css +0 -208
- data/test/call_as_daemon.rb +0 -12
- data/test/tc_main.rb +0 -24
- data/test/test1.rb +0 -19
- data/test/testapp.rb +0 -11
@@ -42,6 +42,7 @@ module Daemons
|
|
42
42
|
@dir = options[:dir] || ''
|
43
43
|
|
44
44
|
@keep_pid_files = options[:keep_pid_files] || false
|
45
|
+
@no_pidfiles = options[:no_pidfiles] || false
|
45
46
|
|
46
47
|
#@applications = find_applications(pidfile_dir())
|
47
48
|
@applications = []
|
@@ -60,6 +61,41 @@ module Daemons
|
|
60
61
|
end
|
61
62
|
|
62
63
|
def find_applications(dir)
|
64
|
+
if @no_pidfiles
|
65
|
+
return find_applications_by_app_name(app_name)
|
66
|
+
else
|
67
|
+
return find_applications_by_pidfiles(dir)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# TODO: identifiy the monitor process
|
72
|
+
def find_applications_by_app_name(app_name)
|
73
|
+
pids = []
|
74
|
+
|
75
|
+
begin
|
76
|
+
x = `ps auxw | grep -v grep | awk '{print $2, $11, $12}' | grep #{app_name}`
|
77
|
+
if x && x.chomp!
|
78
|
+
processes = x.split(/\n/).compact
|
79
|
+
processes = processes.delete_if do |p|
|
80
|
+
pid, name, add = p.split(/\s/)
|
81
|
+
# We want to make sure that the first part of the process name matches
|
82
|
+
# so that app_name matches app_name_22
|
83
|
+
|
84
|
+
app_name != name[0..(app_name.length - 1)] and not add.include?(app_name)
|
85
|
+
end
|
86
|
+
pids = processes.map {|p| p.split(/\s/)[0].to_i}
|
87
|
+
end
|
88
|
+
rescue ::Exception
|
89
|
+
end
|
90
|
+
|
91
|
+
return pids.map {|f|
|
92
|
+
app = Application.new(self, {}, PidMem.existing(f))
|
93
|
+
setup_app(app)
|
94
|
+
app
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
def find_applications_by_pidfiles(dir)
|
63
99
|
pid_files = PidFile.find_files(dir, app_name, ! @keep_pid_files)
|
64
100
|
|
65
101
|
#pp pid_files
|
@@ -105,12 +141,14 @@ module Daemons
|
|
105
141
|
private :setup_app
|
106
142
|
|
107
143
|
def create_monitor(an_app)
|
108
|
-
|
144
|
+
if @monitor and options[:monitor]
|
145
|
+
@monitor.stop
|
146
|
+
@monitor = nil
|
147
|
+
end
|
109
148
|
|
110
149
|
if options[:monitor]
|
111
150
|
@monitor = Monitor.new(an_app)
|
112
|
-
|
113
|
-
@monitor.start(@applications)
|
151
|
+
@monitor.start(self)
|
114
152
|
end
|
115
153
|
end
|
116
154
|
|
@@ -125,18 +163,28 @@ module Daemons
|
|
125
163
|
}
|
126
164
|
end
|
127
165
|
|
128
|
-
def stop_all(
|
129
|
-
|
166
|
+
def stop_all(no_wait = false)
|
167
|
+
if @monitor
|
168
|
+
@monitor.stop
|
169
|
+
@monitor = nil
|
170
|
+
setup
|
171
|
+
end
|
172
|
+
|
173
|
+
threads = []
|
130
174
|
|
131
175
|
@applications.each {|a|
|
132
|
-
|
133
|
-
|
134
|
-
else
|
135
|
-
a.stop
|
176
|
+
threads << Thread.new do
|
177
|
+
a.stop(no_wait)
|
136
178
|
end
|
137
179
|
}
|
180
|
+
|
181
|
+
threads.each {|t| t.join}
|
138
182
|
end
|
139
183
|
|
184
|
+
def reload_all
|
185
|
+
@applications.each {|a| a.reload}
|
186
|
+
end
|
187
|
+
|
140
188
|
def zap_all
|
141
189
|
@monitor.stop if @monitor
|
142
190
|
|
@@ -149,4 +197,4 @@ module Daemons
|
|
149
197
|
|
150
198
|
end
|
151
199
|
|
152
|
-
end
|
200
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'daemons/etc_extension'
|
2
|
+
|
3
|
+
class CurrentProcess
|
4
|
+
def self.change_privilege(user, group=user)
|
5
|
+
puts "Changing process privilege to #{user}:#{group}"
|
6
|
+
|
7
|
+
uid, gid = Process.euid, Process.egid
|
8
|
+
target_uid = Etc.getpwnam(user).uid
|
9
|
+
target_gid = Etc.getgrnam(group).gid
|
10
|
+
|
11
|
+
if uid != target_uid || gid != target_gid
|
12
|
+
Process.initgroups(user, target_gid)
|
13
|
+
Process::GID.change_privilege(target_gid)
|
14
|
+
Process::UID.change_privilege(target_uid)
|
15
|
+
end
|
16
|
+
rescue Errno::EPERM => e
|
17
|
+
raise "Couldn't change user and group to #{user}:#{group}: #{e}"
|
18
|
+
end
|
19
|
+
end
|
data/lib/daemons/cmdline.rb
CHANGED
@@ -10,10 +10,8 @@ module Daemons
|
|
10
10
|
@options = {}
|
11
11
|
|
12
12
|
@opts = OptionParser.new do |opts|
|
13
|
-
#opts.banner = "Usage: example.rb [options]"
|
14
13
|
opts.banner = ""
|
15
14
|
|
16
|
-
# Boolean switch.
|
17
15
|
# opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
|
18
16
|
# @options[:verbose] = v
|
19
17
|
# end
|
@@ -26,6 +24,10 @@ module Daemons
|
|
26
24
|
@options[:force] = t
|
27
25
|
end
|
28
26
|
|
27
|
+
opts.on("-n", "--no_wait", "Do not wait for processes to stop") do |t|
|
28
|
+
@options[:no_wait] = t
|
29
|
+
end
|
30
|
+
|
29
31
|
#opts.separator ""
|
30
32
|
#opts.separator "Specific options:"
|
31
33
|
|
@@ -33,8 +35,7 @@ module Daemons
|
|
33
35
|
opts.separator ""
|
34
36
|
opts.separator "Common options:"
|
35
37
|
|
36
|
-
# No argument, shows at tail. This will print an options summary
|
37
|
-
# Try it and see!
|
38
|
+
# No argument, shows at tail. This will print an options summary
|
38
39
|
opts.on_tail("-h", "--help", "Show this message") do
|
39
40
|
#puts opts
|
40
41
|
#@usage =
|
@@ -43,7 +44,7 @@ module Daemons
|
|
43
44
|
exit
|
44
45
|
end
|
45
46
|
|
46
|
-
#
|
47
|
+
# Switch to print the version.
|
47
48
|
opts.on_tail("--version", "Show version") do
|
48
49
|
puts "daemons version #{Daemons::VERSION}"
|
49
50
|
exit
|
@@ -56,6 +57,7 @@ module Daemons
|
|
56
57
|
@usage = <<END
|
57
58
|
-t, --ontop Stay on top (does not daemonize)
|
58
59
|
-f, --force Force operation
|
60
|
+
-n, --no_wait Do not wait for processes to stop
|
59
61
|
|
60
62
|
Common options:
|
61
63
|
-h, --help Show this message
|
@@ -92,8 +94,10 @@ END
|
|
92
94
|
puts " start start an instance of the application"
|
93
95
|
puts " stop stop all instances of the application"
|
94
96
|
puts " restart stop all instances and restart them afterwards"
|
97
|
+
puts " reload send a SIGHUP to all instances of the application"
|
95
98
|
puts " run start the application and stay on top"
|
96
99
|
puts " zap set the application to a stopped state"
|
100
|
+
puts " status show status (PID) of application instances"
|
97
101
|
puts
|
98
102
|
puts "* and where <options> may contain several of the following:"
|
99
103
|
|
@@ -114,4 +118,4 @@ END
|
|
114
118
|
|
115
119
|
end
|
116
120
|
|
117
|
-
end
|
121
|
+
end
|
data/lib/daemons/controller.rb
CHANGED
@@ -15,6 +15,7 @@ module Daemons
|
|
15
15
|
'restart',
|
16
16
|
'run',
|
17
17
|
'zap',
|
18
|
+
'reload',
|
18
19
|
'status'
|
19
20
|
]
|
20
21
|
|
@@ -71,16 +72,18 @@ module Daemons
|
|
71
72
|
@options[:ontop] ||= true
|
72
73
|
@group.new_application.start
|
73
74
|
when 'stop'
|
74
|
-
@group.stop_all
|
75
|
+
@group.stop_all(@options[:no_wait])
|
75
76
|
when 'restart'
|
76
77
|
unless @group.applications.empty?
|
77
78
|
@group.stop_all
|
78
|
-
sleep
|
79
|
+
sleep(1)
|
79
80
|
@group.start_all
|
80
81
|
else
|
81
82
|
puts "Warning: no instances running. Starting..."
|
82
83
|
@group.new_application.start
|
83
84
|
end
|
85
|
+
when 'reload'
|
86
|
+
@group.reload_all
|
84
87
|
when 'zap'
|
85
88
|
@group.zap_all
|
86
89
|
when 'status'
|
data/lib/daemons/daemonize.rb
CHANGED
@@ -1,97 +1,5 @@
|
|
1
|
-
#--
|
2
|
-
###############################################################################
|
3
|
-
# daemonize.rb is a slightly modified version of daemonize.rb was #
|
4
|
-
# from the Daemonize Library written by Travis Whitton #
|
5
|
-
# for details, read the notice below #
|
6
|
-
###############################################################################
|
7
|
-
#++
|
8
|
-
#
|
9
|
-
#
|
10
|
-
# =Daemonize Library
|
11
|
-
#
|
12
|
-
# February. 4, 2005 Travis Whitton <whitton@atlantic.net>
|
13
|
-
#
|
14
|
-
# Daemonize allows you to easily modify any existing Ruby program to run
|
15
|
-
# as a daemon. See README.rdoc for more details.
|
16
|
-
#
|
17
|
-
# == How to install
|
18
|
-
# 1. su to root
|
19
|
-
# 2. ruby install.rb
|
20
|
-
# build the docs if you want to
|
21
|
-
# 3. rdoc --main README.rdoc daemonize.rb README.rdoc
|
22
|
-
#
|
23
|
-
# == Copying
|
24
|
-
# The Daemonize extension module is copywrited free software by Travis Whitton
|
25
|
-
# <whitton@atlantic.net>. You can redistribute it under the terms specified in
|
26
|
-
# the COPYING file of the Ruby distribution.
|
27
|
-
#
|
28
|
-
# == WARRANTY
|
29
|
-
# THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
30
|
-
# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
31
|
-
# WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
32
|
-
# PURPOSE.
|
33
|
-
#
|
34
|
-
#
|
35
|
-
# ----
|
36
|
-
#
|
37
|
-
# == Purpose
|
38
|
-
#
|
39
|
-
# Daemonize is a module derived from Perl's Proc::Daemon module. This module
|
40
|
-
# allows you to easily modify any existing Ruby program to run as a daemon.
|
41
|
-
# A daemon is a process that runs in the background with no controlling terminal.
|
42
|
-
# Generally servers (like FTP and HTTP servers) run as daemon processes.
|
43
|
-
# Note, do not make the mistake that a daemon == server. Converting a program
|
44
|
-
# to a daemon by hand is a relatively simple process; however, this module will
|
45
|
-
# save you the effort of repeatedly looking up the procedure, and it will also
|
46
|
-
# insure that your programs are daemonized in the safest and most corrects
|
47
|
-
# fashion possible.
|
48
|
-
#
|
49
|
-
# == Procedure
|
50
|
-
#
|
51
|
-
# The Daemonize module does the following:
|
52
|
-
#
|
53
|
-
# Forks a child and exits the parent process.
|
54
|
-
#
|
55
|
-
# Becomes a session leader (which detaches the program from
|
56
|
-
# the controlling terminal).
|
57
|
-
#
|
58
|
-
# Forks another child process and exits first child. This prevents
|
59
|
-
# the potential of acquiring a controlling terminal.
|
60
|
-
#
|
61
|
-
# Changes the current working directory to "/".
|
62
|
-
#
|
63
|
-
# Clears the file creation mask.
|
64
|
-
#
|
65
|
-
# Closes file descriptors.
|
66
|
-
#
|
67
|
-
# == Example usage
|
68
|
-
#
|
69
|
-
# Using the Daemonize module is extremely simple:
|
70
|
-
#
|
71
|
-
# require 'daemonize'
|
72
|
-
#
|
73
|
-
# class TestDaemon
|
74
|
-
# include Daemonize
|
75
|
-
#
|
76
|
-
# def initialize
|
77
|
-
# daemonize()
|
78
|
-
# loop do
|
79
|
-
# # do some work here
|
80
|
-
# end
|
81
|
-
# end
|
82
|
-
# end
|
83
|
-
#
|
84
|
-
# == Credits
|
85
|
-
#
|
86
|
-
# Daemonize was written by Travis Whitton and is based on Perl's
|
87
|
-
# Proc::Daemonize, which was written by Earl Hood. The above documentation
|
88
|
-
# is also partially borrowed from the Proc::Daemonize POD documentation.
|
89
|
-
|
90
|
-
|
91
|
-
|
92
1
|
module Daemonize
|
93
|
-
|
94
|
-
|
2
|
+
|
95
3
|
# Try to fork if at all possible retrying every 5 sec if the
|
96
4
|
# maximum process limit for the system has been reached
|
97
5
|
def safefork
|
@@ -112,38 +20,37 @@ module Daemonize
|
|
112
20
|
module_function :safefork
|
113
21
|
|
114
22
|
|
115
|
-
|
116
|
-
|
23
|
+
# Simulate the daemonization process (:ontop mode)
|
24
|
+
# NOTE: STDOUT and STDERR will not be redirected to the logfile,
|
25
|
+
# because in :ontop mode, we normally want to see the output
|
26
|
+
def simulate(logfile_name = nil, app_name = nil)
|
27
|
+
$0 = app_name if app_name
|
117
28
|
|
118
|
-
|
119
|
-
|
29
|
+
# Release old working directory
|
30
|
+
Dir.chdir "/"
|
31
|
+
|
32
|
+
# Release old working directory
|
33
|
+
Dir.chdir "/"
|
120
34
|
|
121
|
-
|
122
|
-
ObjectSpace.each_object(IO) do |io|
|
123
|
-
unless [STDIN, STDOUT, STDERR].include?(io)
|
124
|
-
begin
|
125
|
-
unless io.closed?
|
126
|
-
io.close
|
127
|
-
end
|
128
|
-
rescue ::Exception
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
35
|
+
close_io()
|
132
36
|
|
133
|
-
# Free
|
134
|
-
|
135
|
-
# STDOUT/STDERR should go to a logfile
|
37
|
+
# Free STDIN and point it to somewhere sensible
|
38
|
+
begin; STDIN.reopen "/dev/null"; rescue ::Exception; end
|
136
39
|
|
137
|
-
|
40
|
+
# Split rand streams between spawning and daemonized process
|
41
|
+
srand
|
138
42
|
end
|
139
43
|
module_function :simulate
|
140
44
|
|
141
45
|
|
46
|
+
# Call a given block as a daemon
|
142
47
|
def call_as_daemon(block, logfile_name = nil, app_name = nil)
|
48
|
+
# we use a pipe to return the PID of the daemon
|
143
49
|
rd, wr = IO.pipe
|
144
50
|
|
145
51
|
if tmppid = safefork
|
146
|
-
# parent
|
52
|
+
# in the parent
|
53
|
+
|
147
54
|
wr.close
|
148
55
|
pid = rd.read.to_i
|
149
56
|
rd.close
|
@@ -152,7 +59,7 @@ module Daemonize
|
|
152
59
|
|
153
60
|
return pid
|
154
61
|
else
|
155
|
-
# child
|
62
|
+
# in the child
|
156
63
|
|
157
64
|
rd.close
|
158
65
|
|
@@ -162,33 +69,24 @@ module Daemonize
|
|
162
69
|
end
|
163
70
|
|
164
71
|
# Prevent the possibility of acquiring a controlling terminal
|
165
|
-
|
166
|
-
|
167
|
-
exit if pid = safefork
|
168
|
-
#end
|
72
|
+
trap 'SIGHUP', 'IGNORE'
|
73
|
+
exit if pid = safefork
|
169
74
|
|
170
75
|
wr.write Process.pid
|
171
76
|
wr.close
|
172
77
|
|
173
78
|
$0 = app_name if app_name
|
174
79
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
# Make sure all file descriptors are closed
|
179
|
-
ObjectSpace.each_object(IO) do |io|
|
180
|
-
unless [STDIN, STDOUT, STDERR].include?(io)
|
181
|
-
begin
|
182
|
-
unless io.closed?
|
183
|
-
io.close
|
184
|
-
end
|
185
|
-
rescue ::Exception
|
186
|
-
end
|
187
|
-
end
|
188
|
-
end
|
80
|
+
# Release old working directory
|
81
|
+
Dir.chdir "/"
|
189
82
|
|
83
|
+
close_io()
|
84
|
+
|
190
85
|
redirect_io(logfile_name)
|
191
86
|
|
87
|
+
# Split rand streams between spawning and daemonized process
|
88
|
+
srand
|
89
|
+
|
192
90
|
block.call
|
193
91
|
|
194
92
|
exit
|
@@ -197,10 +95,10 @@ module Daemonize
|
|
197
95
|
module_function :call_as_daemon
|
198
96
|
|
199
97
|
|
200
|
-
#
|
98
|
+
# Transform the current process into a daemon
|
201
99
|
def daemonize(logfile_name = nil, app_name = nil)
|
202
|
-
|
203
|
-
safefork and exit
|
100
|
+
# Fork and exit from the parent
|
101
|
+
safefork and exit
|
204
102
|
|
205
103
|
# Detach from the controlling terminal
|
206
104
|
unless sess_id = Process.setsid
|
@@ -208,17 +106,29 @@ module Daemonize
|
|
208
106
|
end
|
209
107
|
|
210
108
|
# Prevent the possibility of acquiring a controlling terminal
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
#end
|
215
|
-
|
109
|
+
trap 'SIGHUP', 'IGNORE'
|
110
|
+
exit if pid = safefork
|
111
|
+
|
216
112
|
$0 = app_name if app_name
|
217
113
|
|
218
|
-
|
219
|
-
|
114
|
+
# Release old working directory
|
115
|
+
Dir.chdir "/"
|
116
|
+
|
117
|
+
close_io()
|
220
118
|
|
221
|
-
|
119
|
+
redirect_io(logfile_name)
|
120
|
+
|
121
|
+
# Split rand streams between spawning and daemonized process
|
122
|
+
srand
|
123
|
+
|
124
|
+
return sess_id
|
125
|
+
end
|
126
|
+
module_function :daemonize
|
127
|
+
|
128
|
+
|
129
|
+
def close_io()
|
130
|
+
# Make sure all input/output streams are closed
|
131
|
+
# Part I: close all IO objects (except for STDIN/STDOUT/STDERR)
|
222
132
|
ObjectSpace.each_object(IO) do |io|
|
223
133
|
unless [STDIN, STDOUT, STDERR].include?(io)
|
224
134
|
begin
|
@@ -229,24 +139,27 @@ module Daemonize
|
|
229
139
|
end
|
230
140
|
end
|
231
141
|
end
|
232
|
-
|
233
|
-
redirect_io(logfile_name)
|
234
142
|
|
235
|
-
#
|
236
|
-
|
143
|
+
# Make sure all input/output streams are closed
|
144
|
+
# Part II: close all file decriptors (except for STDIN/STDOUT/STDERR)
|
145
|
+
ios = Array.new(8192) {|i| IO.for_fd(i) rescue nil}.compact
|
146
|
+
ios.each do |io|
|
147
|
+
next if io.fileno < 3
|
148
|
+
io.close
|
149
|
+
end
|
237
150
|
end
|
238
|
-
module_function :
|
151
|
+
module_function :close_io
|
239
152
|
|
240
153
|
|
241
|
-
# Free file descriptors and
|
154
|
+
# Free STDIN/STDOUT/STDERR file descriptors and
|
242
155
|
# point them somewhere sensible
|
243
|
-
# STDOUT/STDERR should go to a logfile
|
244
156
|
def redirect_io(logfile_name)
|
245
157
|
begin; STDIN.reopen "/dev/null"; rescue ::Exception; end
|
246
158
|
|
247
159
|
if logfile_name
|
248
160
|
begin
|
249
161
|
STDOUT.reopen logfile_name, "a"
|
162
|
+
File.chmod(0644, logfile_name)
|
250
163
|
STDOUT.sync = true
|
251
164
|
rescue ::Exception
|
252
165
|
begin; STDOUT.reopen "/dev/null"; rescue ::Exception; end
|
@@ -260,4 +173,5 @@ module Daemonize
|
|
260
173
|
end
|
261
174
|
module_function :redirect_io
|
262
175
|
|
176
|
+
|
263
177
|
end
|