process-daemon 0.6.1 → 1.0.0
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/.travis.yml +5 -6
- data/README.md +3 -3
- data/lib/process/daemon.rb +31 -31
- data/lib/process/daemon/controller.rb +12 -12
- data/lib/process/daemon/log_file.rb +8 -3
- data/lib/process/daemon/version.rb +1 -1
- data/process-daemon.gemspec +1 -1
- data/spec/process/daemon/crashed_daemon_spec.rb +57 -0
- data/spec/process/daemon/daemon_spec.rb +4 -6
- data/spec/process/daemon/daemonize_spec.rb +57 -0
- data/spec/process/daemon/log_file_spec.rb +36 -0
- data/spec/process/daemon/notification_spec.rb +5 -0
- metadata +11 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f2719836b2dfefcb18754e6157764c3f964d667
|
4
|
+
data.tar.gz: 696fd41006946dd13a6a04eaabef60e5f35c8925
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a2c171b1f7007a6c69e198ee47b56409c870a6c6fe525b6d0b75f75529ea8a4cc802bf22aaad27751f0ec7e631c6ea2221be4ad83e64b4ffe4fe84b1554aeb5
|
7
|
+
data.tar.gz: 37b32a1adec863f0b34451b11e1dec6ddaed83e0c568be6f72d4171e5b878a7c873814353f19273ad901e63933381ee2a4699c340b18735742da40432bec4d2c
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
`Process::Daemon` is a stable and helpful base class for long running tasks and daemons. Provides standard `start`, `stop`, `restart`, `status` operations.
|
4
4
|
|
5
|
-
[](https://travis-ci.org/ioquatix/process-daemon)
|
6
|
+
[](https://codeclimate.com/github/ioquatix/process-daemon)
|
7
|
+
[](https://coveralls.io/r/ioquatix/process-daemon)
|
8
8
|
[](http://www.rubydoc.info/gems/process-daemon)
|
9
9
|
[](https://github.com/ioquatix/process-daemon)
|
10
10
|
|
data/lib/process/daemon.rb
CHANGED
@@ -162,38 +162,38 @@ module Process
|
|
162
162
|
self.shutdown
|
163
163
|
end
|
164
164
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
# The process controller, responsible for managing the daemon process start, stop, restart, etc.
|
171
|
-
def self.controller(options = {})
|
172
|
-
@controller ||= Controller.new(instance, options)
|
173
|
-
end
|
174
|
-
|
175
|
-
# The main entry point for daemonized scripts.
|
176
|
-
def self.daemonize(*args)
|
177
|
-
# Wish Ruby 2.0 kwargs were backported to 1.9.3... oh well:
|
178
|
-
options = (args.last === Hash) ? args.pop : {}
|
179
|
-
argv = (args.last === Array) ? args.pop : ARGV
|
165
|
+
class << self
|
166
|
+
# A shared instance of the daemon.
|
167
|
+
def instance
|
168
|
+
@instance ||= self.new
|
169
|
+
end
|
180
170
|
|
181
|
-
controller
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
171
|
+
# The process controller, responsible for managing the daemon process start, stop, restart, etc.
|
172
|
+
def controller(options = {})
|
173
|
+
@controller ||= Controller.new(instance, options)
|
174
|
+
end
|
175
|
+
|
176
|
+
# The main entry point for daemonized scripts.
|
177
|
+
def daemonize(*args, **options)
|
178
|
+
args = ARGV if args.empty?
|
179
|
+
|
180
|
+
controller(options).daemonize(args)
|
181
|
+
end
|
182
|
+
|
183
|
+
# Start the shared daemon instance.
|
184
|
+
def start
|
185
|
+
controller.start
|
186
|
+
end
|
187
|
+
|
188
|
+
# Stop the shared daemon instance.
|
189
|
+
def stop
|
190
|
+
controller.stop
|
191
|
+
end
|
192
|
+
|
193
|
+
# Check if the shared daemon instance is runnning or not.
|
194
|
+
def status
|
195
|
+
controller.status
|
196
|
+
end
|
197
197
|
end
|
198
198
|
end
|
199
199
|
end
|
@@ -42,18 +42,18 @@ module Process
|
|
42
42
|
case (argv.shift || :default).to_sym
|
43
43
|
when :start
|
44
44
|
start
|
45
|
-
|
45
|
+
show_status
|
46
46
|
when :stop
|
47
47
|
stop
|
48
|
-
|
48
|
+
show_status
|
49
49
|
ProcessFile.cleanup(@daemon)
|
50
50
|
when :restart
|
51
51
|
stop
|
52
52
|
ProcessFile.cleanup(@daemon)
|
53
53
|
start
|
54
|
-
|
54
|
+
show_status
|
55
55
|
when :status
|
56
|
-
|
56
|
+
show_status
|
57
57
|
else
|
58
58
|
@output.puts Rainbow("Invalid command. Please specify start, restart, stop or status.").red
|
59
59
|
end
|
@@ -73,8 +73,8 @@ module Process
|
|
73
73
|
File.umask 0000
|
74
74
|
Dir.chdir @daemon.working_directory
|
75
75
|
|
76
|
-
$stdin.reopen
|
77
|
-
$stdout.reopen @daemon.log_file_path,
|
76
|
+
$stdin.reopen '/dev/null'
|
77
|
+
$stdout.reopen @daemon.log_file_path, 'a'
|
78
78
|
$stdout.sync = true
|
79
79
|
|
80
80
|
$stderr.reopen $stdout
|
@@ -99,7 +99,7 @@ module Process
|
|
99
99
|
def start
|
100
100
|
@output.puts Rainbow("Starting #{@daemon.name} daemon...").blue
|
101
101
|
|
102
|
-
case
|
102
|
+
case self.status
|
103
103
|
when :running
|
104
104
|
@output.puts Rainbow("Daemon already running!").blue
|
105
105
|
return
|
@@ -132,9 +132,11 @@ module Process
|
|
132
132
|
|
133
133
|
# Prints out the status of the daemon
|
134
134
|
def status
|
135
|
-
|
136
|
-
|
137
|
-
|
135
|
+
ProcessFile.status(@daemon)
|
136
|
+
end
|
137
|
+
|
138
|
+
def show_status
|
139
|
+
case self.status
|
138
140
|
when :running
|
139
141
|
@output.puts Rainbow("Daemon status: running pid=#{ProcessFile.recall(@daemon)}").green
|
140
142
|
when :unknown
|
@@ -150,8 +152,6 @@ module Process
|
|
150
152
|
when :stopped
|
151
153
|
@output.puts Rainbow("Daemon status: stopped").blue
|
152
154
|
end
|
153
|
-
|
154
|
-
return daemon_state
|
155
155
|
end
|
156
156
|
|
157
157
|
# The pid of the daemon if it is available. The pid may be invalid if the daemon has crashed.
|
@@ -31,7 +31,7 @@ module Process
|
|
31
31
|
reverse_each_line do |line|
|
32
32
|
lines << line
|
33
33
|
|
34
|
-
break if yield line
|
34
|
+
break if block_given? and yield line
|
35
35
|
end
|
36
36
|
|
37
37
|
return lines.reverse
|
@@ -81,14 +81,19 @@ module Process
|
|
81
81
|
|
82
82
|
while offset == nil
|
83
83
|
chunk = read_reverse(REVERSE_BUFFER_SIZE)
|
84
|
+
|
84
85
|
return (buf == "" ? nil : buf) if chunk == nil
|
85
86
|
|
86
87
|
buf = chunk + buf
|
87
88
|
|
88
|
-
|
89
|
+
# Don't consider the last newline.
|
90
|
+
offset = buf.rindex(sep_string, -(sep_string.length + 1))
|
89
91
|
end
|
90
92
|
|
91
|
-
|
93
|
+
# Don't include newline:
|
94
|
+
offset += 1
|
95
|
+
|
96
|
+
line = buf[offset...buf.size]
|
92
97
|
|
93
98
|
seek((end_pos - buf.size) + offset, IO::SEEK_SET)
|
94
99
|
|
data/process-daemon.gemspec
CHANGED
@@ -23,6 +23,6 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.add_dependency "rainbow", "~> 2.0"
|
24
24
|
|
25
25
|
spec.add_development_dependency "bundler", "~> 1.3"
|
26
|
-
spec.add_development_dependency "rspec", "~> 3.
|
26
|
+
spec.add_development_dependency "rspec", "~> 3.4.0"
|
27
27
|
spec.add_development_dependency "rake"
|
28
28
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# Copyright, 2007, 2014, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
require 'process/daemon'
|
22
|
+
|
23
|
+
require 'webrick'
|
24
|
+
require 'webrick/https'
|
25
|
+
|
26
|
+
require 'xmlrpc/server'
|
27
|
+
require 'xmlrpc/client'
|
28
|
+
|
29
|
+
module Process::Daemon::DaemonizeSpec
|
30
|
+
class CrashDaemon < Process::Daemon
|
31
|
+
def working_directory
|
32
|
+
File.expand_path("../tmp", __FILE__)
|
33
|
+
end
|
34
|
+
|
35
|
+
def run
|
36
|
+
and_bobs_your_uncle
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe Process::Daemon do
|
41
|
+
it "should crash daemon and print exception" do
|
42
|
+
output = StringIO.new
|
43
|
+
|
44
|
+
controller = Process::Daemon::Controller.new(CrashDaemon.instance, :output => output)
|
45
|
+
|
46
|
+
controller.start
|
47
|
+
|
48
|
+
sleep 1
|
49
|
+
|
50
|
+
controller.show_status
|
51
|
+
|
52
|
+
expect(CrashDaemon.status).to be == :unknown
|
53
|
+
expect(output.string).to include("=== Daemon Exception Backtrace", "=== Daemon Crashed")
|
54
|
+
expect(output.string).to include("NameError", "and_bobs_your_uncle")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -69,14 +69,10 @@ module Process::Daemon::DaemonSpec
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
-
class
|
72
|
+
class DefaultDaemon < Process::Daemon
|
73
73
|
def working_directory
|
74
74
|
File.expand_path("../tmp", __FILE__)
|
75
75
|
end
|
76
|
-
|
77
|
-
def run
|
78
|
-
sleep 1 while true
|
79
|
-
end
|
80
76
|
end
|
81
77
|
|
82
78
|
describe Process::Daemon do
|
@@ -90,6 +86,7 @@ module Process::Daemon::DaemonSpec
|
|
90
86
|
|
91
87
|
it "should be running" do
|
92
88
|
expect(XMLRPCDaemon.status).to be == :running
|
89
|
+
expect(XMLRPCDaemon.instance.crashed?).to be_falsey
|
93
90
|
end
|
94
91
|
|
95
92
|
it "should respond to connections" do
|
@@ -102,7 +99,7 @@ module Process::Daemon::DaemonSpec
|
|
102
99
|
end
|
103
100
|
|
104
101
|
it "should be a unique instance" do
|
105
|
-
expect(XMLRPCDaemon.instance).to_not be ==
|
102
|
+
expect(XMLRPCDaemon.instance).to_not be == DefaultDaemon.instance
|
106
103
|
end
|
107
104
|
|
108
105
|
it "should produce useful output" do
|
@@ -112,6 +109,7 @@ module Process::Daemon::DaemonSpec
|
|
112
109
|
|
113
110
|
expect(controller.status).to be == :running
|
114
111
|
|
112
|
+
controller.show_status
|
115
113
|
expect(output.string).to match /Daemon status: running pid=\d+/
|
116
114
|
|
117
115
|
output.rewind
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# Copyright, 2007, 2014, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
require 'process/daemon'
|
22
|
+
|
23
|
+
require 'webrick'
|
24
|
+
require 'webrick/https'
|
25
|
+
|
26
|
+
require 'xmlrpc/server'
|
27
|
+
require 'xmlrpc/client'
|
28
|
+
|
29
|
+
module Process::Daemon::DaemonizeSpec
|
30
|
+
class SleepDaemon < Process::Daemon
|
31
|
+
def working_directory
|
32
|
+
File.expand_path("../tmp", __FILE__)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe Process::Daemon do
|
37
|
+
it "should start daemon" do
|
38
|
+
SleepDaemon.daemonize(:start)
|
39
|
+
|
40
|
+
expect(SleepDaemon.status).to be == :running
|
41
|
+
|
42
|
+
SleepDaemon.daemonize(:stop)
|
43
|
+
|
44
|
+
expect(SleepDaemon.status).to be == :stopped
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should restart daemon" do
|
48
|
+
SleepDaemon.daemonize(:restart)
|
49
|
+
|
50
|
+
expect(SleepDaemon.status).to be == :running
|
51
|
+
|
52
|
+
SleepDaemon.daemonize(:stop)
|
53
|
+
|
54
|
+
expect(SleepDaemon.status).to be == :stopped
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Copyright, 2014, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
require 'process/daemon'
|
22
|
+
require 'process/daemon/log_file'
|
23
|
+
|
24
|
+
module Process::Daemon::LogFileSpec
|
25
|
+
describe Process::Daemon::LogFile do
|
26
|
+
let(:daemon) {SleepDaemon.instance}
|
27
|
+
|
28
|
+
it "should give the several last lines" do
|
29
|
+
lines = File.readlines(__FILE__)
|
30
|
+
|
31
|
+
log_file = Process::Daemon::LogFile.open(__FILE__)
|
32
|
+
|
33
|
+
expect(log_file.tail_log).to be == lines
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -38,6 +38,7 @@ module Process::Daemon::NotificationSpec
|
|
38
38
|
end
|
39
39
|
|
40
40
|
it "can be signalled within trap context and across processes" do
|
41
|
+
ready = Process::Daemon::Notification.new
|
41
42
|
notification = Process::Daemon::Notification.new
|
42
43
|
|
43
44
|
pid = fork do
|
@@ -46,9 +47,13 @@ module Process::Daemon::NotificationSpec
|
|
46
47
|
exit(0)
|
47
48
|
end
|
48
49
|
|
50
|
+
ready.signal
|
51
|
+
|
49
52
|
sleep
|
50
53
|
end
|
51
54
|
|
55
|
+
ready.wait(timeout: 5.0)
|
56
|
+
|
52
57
|
Process.kill(:INT, pid)
|
53
58
|
|
54
59
|
notification.wait(timeout: 1.0)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: process-daemon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rainbow
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 3.
|
47
|
+
version: 3.4.0
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 3.
|
54
|
+
version: 3.4.0
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -88,8 +88,11 @@ files:
|
|
88
88
|
- lib/process/daemon/process_file.rb
|
89
89
|
- lib/process/daemon/version.rb
|
90
90
|
- process-daemon.gemspec
|
91
|
+
- spec/process/daemon/crashed_daemon_spec.rb
|
91
92
|
- spec/process/daemon/daemon.rb
|
92
93
|
- spec/process/daemon/daemon_spec.rb
|
94
|
+
- spec/process/daemon/daemonize_spec.rb
|
95
|
+
- spec/process/daemon/log_file_spec.rb
|
93
96
|
- spec/process/daemon/notification_spec.rb
|
94
97
|
- spec/process/daemon/privileges_spec.rb
|
95
98
|
- spec/process/daemon/process_file_spec.rb
|
@@ -113,15 +116,17 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
113
116
|
version: '0'
|
114
117
|
requirements: []
|
115
118
|
rubyforge_project:
|
116
|
-
rubygems_version: 2.
|
119
|
+
rubygems_version: 2.4.6
|
117
120
|
signing_key:
|
118
121
|
specification_version: 4
|
119
122
|
summary: "`Process::Daemon` is a stable and helpful base class for long running tasks
|
120
123
|
and daemons. Provides standard `start`, `stop`, `restart`, `status` operations."
|
121
124
|
test_files:
|
125
|
+
- spec/process/daemon/crashed_daemon_spec.rb
|
122
126
|
- spec/process/daemon/daemon.rb
|
123
127
|
- spec/process/daemon/daemon_spec.rb
|
128
|
+
- spec/process/daemon/daemonize_spec.rb
|
129
|
+
- spec/process/daemon/log_file_spec.rb
|
124
130
|
- spec/process/daemon/notification_spec.rb
|
125
131
|
- spec/process/daemon/privileges_spec.rb
|
126
132
|
- spec/process/daemon/process_file_spec.rb
|
127
|
-
has_rdoc: yard
|