boreman 0.1.27 → 0.1.28
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 +4 -4
- data/lib/boreman.rb +7 -25
- data/lib/boreman/daemonize.rb +141 -0
- data/lib/boreman/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b43032f6ccbd8241a33a650f841b0918cb1d33d4
|
4
|
+
data.tar.gz: 8b7fde40f727ed9f62e6fc1eec3edc9ba99f75cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a92f68270e25b7f0449c95aac5089b7f75d2298ce094385736d4253fe7547e7aaf962f41002e1e0bc98cb398294dcaf9017d820bfa6ddcfdcf9f73ad9d2cdda3
|
7
|
+
data.tar.gz: 61f18ed3c883abd891780d6bd2dbaf6c2b83ac7a17ad2c22066dd130fba7fe0cf399e976e66043bfc0a67804780bc087cd9281c7c4bdae038824d50cebbeed35
|
data/lib/boreman.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "boreman/version"
|
2
|
+
require "boreman/daemonize"
|
2
3
|
|
3
4
|
module Boreman
|
4
5
|
def self.run(action, selector, opts = {})
|
@@ -93,32 +94,13 @@ module Boreman
|
|
93
94
|
if cmd = procs[selector]
|
94
95
|
cmd = prepare_command(cmd)
|
95
96
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
fpid = fork do
|
100
|
-
STDOUT.reopen(w)
|
101
|
-
|
102
|
-
r.close
|
103
|
-
|
104
|
-
pid = Process.spawn cmd, pgroup: true
|
105
|
-
|
106
|
-
puts pid.to_s
|
107
|
-
|
108
|
-
exit! 0
|
109
|
-
end
|
110
|
-
|
111
|
-
pid = r.gets.chomp.to_i
|
112
|
-
|
113
|
-
Process.detach(fpid)
|
114
|
-
Process.detach(pid)
|
115
|
-
|
116
|
-
write_pid selector, pid
|
117
|
-
puts "Started #{selector}, pid = #{pid}"
|
118
|
-
ensure
|
119
|
-
r.close rescue nil
|
120
|
-
w.close rescue nil
|
97
|
+
run = Proc.new do
|
98
|
+
Kernel.exec cmd
|
121
99
|
end
|
100
|
+
|
101
|
+
pid = Daemonize.call_as_daemon run
|
102
|
+
write_pid selector, pid
|
103
|
+
puts "Started #{selector}, pid = #{pid}"
|
122
104
|
else
|
123
105
|
puts "Entry #{selector} not found in Procfile"
|
124
106
|
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
module Daemonize
|
2
|
+
# Try to fork if at all possible retrying every 5 sec if the
|
3
|
+
# maximum process limit for the system has been reached
|
4
|
+
def self.safefork
|
5
|
+
tryagain = true
|
6
|
+
|
7
|
+
while tryagain
|
8
|
+
tryagain = false
|
9
|
+
begin
|
10
|
+
if pid = fork
|
11
|
+
return pid
|
12
|
+
end
|
13
|
+
rescue Errno::EWOULDBLOCK
|
14
|
+
sleep 5
|
15
|
+
tryagain = true
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Call a given block as a daemon
|
21
|
+
def self.call_as_daemon(block, logfile_name = nil, app_name = nil)
|
22
|
+
# we use a pipe to return the PID of the daemon
|
23
|
+
rd, wr = IO.pipe
|
24
|
+
|
25
|
+
if tmppid = safefork
|
26
|
+
# in the parent
|
27
|
+
|
28
|
+
wr.close
|
29
|
+
pid = rd.read.to_i
|
30
|
+
rd.close
|
31
|
+
|
32
|
+
Process.waitpid(tmppid)
|
33
|
+
|
34
|
+
return pid
|
35
|
+
else
|
36
|
+
# in the child
|
37
|
+
|
38
|
+
rd.close
|
39
|
+
|
40
|
+
# Detach from the controlling terminal
|
41
|
+
unless Process.setsid
|
42
|
+
fail Daemons.RuntimeException.new('cannot detach from controlling terminal')
|
43
|
+
end
|
44
|
+
|
45
|
+
# Prevent the possibility of acquiring a controlling terminal
|
46
|
+
trap 'SIGHUP', 'IGNORE'
|
47
|
+
exit if pid = safefork
|
48
|
+
|
49
|
+
wr.write Process.pid
|
50
|
+
wr.close
|
51
|
+
|
52
|
+
$0 = app_name if app_name
|
53
|
+
|
54
|
+
close_io
|
55
|
+
|
56
|
+
redirect_io(logfile_name)
|
57
|
+
|
58
|
+
# Split rand streams between spawning and daemonized process
|
59
|
+
srand
|
60
|
+
|
61
|
+
block.call
|
62
|
+
|
63
|
+
exit
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Transform the current process into a daemon
|
68
|
+
def self.daemonize(logfile_name = nil, app_name = nil)
|
69
|
+
# Fork and exit from the parent
|
70
|
+
safefork && exit
|
71
|
+
|
72
|
+
# Detach from the controlling terminal
|
73
|
+
unless sess_id = Process.setsid
|
74
|
+
fail Daemons.RuntimeException.new('cannot detach from controlling terminal')
|
75
|
+
end
|
76
|
+
|
77
|
+
# Prevent the possibility of acquiring a controlling terminal
|
78
|
+
trap 'SIGHUP', 'IGNORE'
|
79
|
+
exit if safefork
|
80
|
+
|
81
|
+
$0 = app_name if app_name
|
82
|
+
|
83
|
+
# Release old working directory
|
84
|
+
Dir.chdir '/'
|
85
|
+
|
86
|
+
close_io
|
87
|
+
|
88
|
+
redirect_io(logfile_name)
|
89
|
+
|
90
|
+
# Split rand streams between spawning and daemonized process
|
91
|
+
srand
|
92
|
+
|
93
|
+
sess_id
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.close_io
|
97
|
+
# Make sure all input/output streams are closed
|
98
|
+
# Part I: close all IO objects (except for $stdin/$stdout/$stderr)
|
99
|
+
ObjectSpace.each_object(IO) do |io|
|
100
|
+
unless [$stdin, $stdout, $stderr].include?(io)
|
101
|
+
io.close rescue nil
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Make sure all input/output streams are closed
|
106
|
+
# Part II: close all file decriptors (except for $stdin/$stdout/$stderr)
|
107
|
+
3.upto(8192) do |i|
|
108
|
+
IO.for_fd(i).close rescue nil
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Free $stdin/$stdout/$stderr file descriptors and
|
113
|
+
# point them somewhere sensible
|
114
|
+
def self.redirect_io(logfile_name)
|
115
|
+
begin; $stdin.reopen '/dev/null'; rescue ::Exception; end
|
116
|
+
|
117
|
+
if logfile_name == 'SYSLOG'
|
118
|
+
# attempt to use syslog via syslogio
|
119
|
+
begin
|
120
|
+
require 'syslogio'
|
121
|
+
$stdout = ::Daemons::SyslogIO.new($0, :local0, :info, $stdout)
|
122
|
+
$stderr = ::Daemons::SyslogIO.new($0, :local0, :err, $stderr)
|
123
|
+
# error out early so we can fallback to null
|
124
|
+
$stdout.puts "no logfile provided, output redirected to syslog"
|
125
|
+
rescue ::Exception
|
126
|
+
# on unsupported platforms simply reopen /dev/null
|
127
|
+
begin; $stdout.reopen '/dev/null'; rescue ::Exception; end
|
128
|
+
begin; $stderr.reopen '/dev/null'; rescue ::Exception; end
|
129
|
+
end
|
130
|
+
elsif logfile_name
|
131
|
+
$stdout.reopen logfile_name, 'a'
|
132
|
+
File.chmod(0644, logfile_name)
|
133
|
+
$stdout.sync = true
|
134
|
+
begin; $stderr.reopen $stdout; rescue ::Exception; end
|
135
|
+
$stderr.sync = true
|
136
|
+
else
|
137
|
+
begin; $stdout.reopen '/dev/null'; rescue ::Exception; end
|
138
|
+
begin; $stderr.reopen '/dev/null'; rescue ::Exception; end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
data/lib/boreman/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: boreman
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.28
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kyle Brett
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-03-
|
11
|
+
date: 2017-03-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -58,6 +58,7 @@ files:
|
|
58
58
|
- boreman.gemspec
|
59
59
|
- exe/boreman
|
60
60
|
- lib/boreman.rb
|
61
|
+
- lib/boreman/daemonize.rb
|
61
62
|
- lib/boreman/version.rb
|
62
63
|
homepage:
|
63
64
|
licenses: []
|