daemon 1.1.0 → 1.2.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.
data/Gemfile CHANGED
@@ -1,15 +1,10 @@
1
- source "http://rubygems.org"
2
- # Add dependencies required to use your gem here.
3
- # Example:
4
- # gem "activesupport", ">= 2.3.5"
1
+ source 'http://rubygems.org'
5
2
 
6
3
  # Add dependencies to develop your gem here.
7
4
  # Include everything needed to run rake, tests, features, etc.
8
5
  group :development do
9
- gem "rspec", "~> 2.3.0"
10
- gem "shoulda", ">= 0"
11
- gem "bundler", "~> 1.0.0"
12
- gem "jeweler", "~> 1.6.4"
13
- gem "rcov", ">= 0"
6
+ gem 'rspec', '~> 2.13'
7
+ gem 'jeweler', '~> 1.8.4'
8
+ gem 'rdoc', '~> 3.9'
14
9
  end
15
10
 
@@ -1,30 +1,30 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- diff-lcs (1.1.3)
4
+ diff-lcs (1.2.4)
5
5
  git (1.2.5)
6
- jeweler (1.6.4)
6
+ jeweler (1.8.4)
7
7
  bundler (~> 1.0)
8
8
  git (>= 1.2.5)
9
9
  rake
10
- rake (0.9.2)
11
- rcov (0.9.10)
12
- rspec (2.3.0)
13
- rspec-core (~> 2.3.0)
14
- rspec-expectations (~> 2.3.0)
15
- rspec-mocks (~> 2.3.0)
16
- rspec-core (2.3.1)
17
- rspec-expectations (2.3.0)
18
- diff-lcs (~> 1.1.2)
19
- rspec-mocks (2.3.0)
20
- shoulda (2.11.3)
10
+ rdoc
11
+ json (1.7.7)
12
+ rake (10.0.4)
13
+ rdoc (3.12.2)
14
+ json (~> 1.4)
15
+ rspec (2.13.0)
16
+ rspec-core (~> 2.13.0)
17
+ rspec-expectations (~> 2.13.0)
18
+ rspec-mocks (~> 2.13.0)
19
+ rspec-core (2.13.1)
20
+ rspec-expectations (2.13.0)
21
+ diff-lcs (>= 1.1.3, < 2.0)
22
+ rspec-mocks (2.13.1)
21
23
 
22
24
  PLATFORMS
23
25
  ruby
24
26
 
25
27
  DEPENDENCIES
26
- bundler (~> 1.0.0)
27
- jeweler (~> 1.6.4)
28
- rcov
29
- rspec (~> 2.3.0)
30
- shoulda
28
+ jeweler (~> 1.8.4)
29
+ rdoc (~> 3.9)
30
+ rspec (~> 2.13)
@@ -24,8 +24,16 @@ So full usage may look like this:
24
24
  Daemon.daemonize('myscript.pid', 'out.log')
25
25
  end
26
26
 
27
+ To spawn a daemon process and keep current process runing:
28
+
29
+ pid, wait = Daemon.daemonize('myscript.pid', 'out.log') do |log|
30
+ # daemon code
31
+ end
32
+
33
+ wait.value # wait for daemon to finish; returns Process::Status
34
+
27
35
  == Contributing to daemon
28
-
36
+
29
37
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
30
38
  * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
31
39
  * Fork the project
data/Rakefile CHANGED
@@ -31,22 +31,9 @@ RSpec::Core::RakeTask.new(:spec) do |spec|
31
31
  spec.pattern = FileList['spec/**/*_spec.rb']
32
32
  end
33
33
 
34
- RSpec::Core::RakeTask.new(:rcov) do |spec|
35
- spec.pattern = 'spec/**/*_spec.rb'
36
- spec.rcov = true
37
- end
38
-
39
- require 'rcov/rcovtask'
40
- Rcov::RcovTask.new do |test|
41
- test.libs << 'test'
42
- test.pattern = 'test/**/test_*.rb'
43
- test.verbose = true
44
- test.rcov_opts << '--exclude "gems/*"'
45
- end
46
-
47
34
  task :default => :spec
48
35
 
49
- require 'rake/rdoctask'
36
+ require 'rdoc/task'
50
37
  Rake::RDocTask.new do |rdoc|
51
38
  version = File.exist?('VERSION') ? File.read('VERSION') : ""
52
39
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.0
1
+ 1.2.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "daemon"
8
- s.version = "1.1.0"
8
+ s.version = "1.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Jakub Pastuszek"]
12
- s.date = "2011-09-28"
12
+ s.date = "2014-09-01"
13
13
  s.description = "Make calling script to become a daemon with pid file locking support and stdout/stderr redirection"
14
14
  s.email = "jpastuszek@gmail.com"
15
15
  s.extra_rdoc_files = [
@@ -32,31 +32,25 @@ Gem::Specification.new do |s|
32
32
  s.homepage = "http://github.com/jpastuszek/daemon"
33
33
  s.licenses = ["MIT"]
34
34
  s.require_paths = ["lib"]
35
- s.rubygems_version = "1.8.10"
35
+ s.rubygems_version = "1.8.23"
36
36
  s.summary = "Daemonize your script with a single line of code"
37
37
 
38
38
  if s.respond_to? :specification_version then
39
39
  s.specification_version = 3
40
40
 
41
41
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
42
- s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
43
- s.add_development_dependency(%q<shoulda>, [">= 0"])
44
- s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
45
- s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
46
- s.add_development_dependency(%q<rcov>, [">= 0"])
42
+ s.add_development_dependency(%q<rspec>, ["~> 2.13"])
43
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
44
+ s.add_development_dependency(%q<rdoc>, ["~> 3.9"])
47
45
  else
48
- s.add_dependency(%q<rspec>, ["~> 2.3.0"])
49
- s.add_dependency(%q<shoulda>, [">= 0"])
50
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
51
- s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
52
- s.add_dependency(%q<rcov>, [">= 0"])
46
+ s.add_dependency(%q<rspec>, ["~> 2.13"])
47
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
48
+ s.add_dependency(%q<rdoc>, ["~> 3.9"])
53
49
  end
54
50
  else
55
- s.add_dependency(%q<rspec>, ["~> 2.3.0"])
56
- s.add_dependency(%q<shoulda>, [">= 0"])
57
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
58
- s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
59
- s.add_dependency(%q<rcov>, [">= 0"])
51
+ s.add_dependency(%q<rspec>, ["~> 2.13"])
52
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
53
+ s.add_dependency(%q<rdoc>, ["~> 3.9"])
60
54
  end
61
55
  end
62
56
 
@@ -6,35 +6,108 @@ class Daemon
6
6
  end
7
7
 
8
8
  def self.daemonize(pid_file, log_file = nil, sync = true)
9
- exit if fork
10
- Process.setsid # become session leader
11
- exit if fork # and exits
12
- # now in child
9
+ if block_given?
10
+ spawn do |send_ok, send_error|
11
+ log = begin
12
+ # try to lock before we kill stdin/out
13
+ lock(pid_file)
13
14
 
14
- # try to lock before we kill stdin/out
15
- lock(pid_file)
15
+ # close I/O
16
+ disconnect(log_file, sync)
17
+ rescue => error
18
+ send_error.call(error)
19
+ end
16
20
 
17
- if log_file
18
- log = File.open(log_file, 'a')
19
- log.sync = sync
21
+ send_ok.call
22
+
23
+ yield log
24
+ end # => pid, wait
20
25
  else
21
- log = '/dev/null'
26
+ # become new process group leader
27
+ fence
28
+
29
+ # try to lock before we kill stdin/out
30
+ lock(pid_file)
31
+
32
+ # close I/O
33
+ disconnect(log_file, sync) # => log
22
34
  end
35
+ end
23
36
 
24
- # disconnect
25
- STDIN.reopen '/dev/null'
26
- STDOUT.reopen log
27
- STDERR.reopen log
37
+ def self.spawn
38
+ r, w = IO.pipe
39
+
40
+ pid = fence do
41
+ r.close
42
+
43
+ yield(
44
+ ->{
45
+ w.write Marshal.dump(nil) # send OK to parent
46
+ w.close
47
+ },
48
+ ->(error){
49
+ w.write Marshal.dump(error) # send error to parent
50
+ w.close
51
+ exit 42
52
+ }
53
+ )
54
+ end
55
+ thr = Process.detach(pid)
56
+
57
+ w.close
58
+ data = r.read
59
+ data.empty? and fail 'ok/error handler not called!'
60
+
61
+ if error = Marshal.load(data)
62
+ thr.join # wait for child to die
63
+ raise error
64
+ end
65
+
66
+ return pid, thr
67
+ ensure
68
+ w.close unless w.closed?
69
+ r.close
70
+ end
71
+
72
+ def self.fence
73
+ if block_given?
74
+ fork do
75
+ Process.setsid # become new session leader
76
+ # now in child
77
+ yield
78
+ end # => pid
79
+ else
80
+ exit! 0 if fork
81
+ Process.setsid # become new session leader
82
+ # now in child
83
+ end
28
84
  end
29
85
 
30
86
  def self.lock(pid_file)
31
87
  pf = File.open(pid_file, File::RDWR | File::CREAT)
32
- raise LockError, pf unless pf.flock(File::LOCK_EX|File::LOCK_NB)
88
+ raise LockError, pf unless pf.flock(File::LOCK_EX | File::LOCK_NB)
33
89
  pf.truncate(0)
34
90
  pf.write(Process.pid.to_s + "\n")
35
91
  pf.flush
36
92
 
37
93
  @pf = pf # keep it open and locked until process exits
38
94
  end
39
- end
40
95
 
96
+ def self.disconnect(log_file = nil, sync = true)
97
+ if log_file
98
+ log = File.open(log_file, File::WRONLY | File::CREAT | File::APPEND | File::BINARY)
99
+ log.sync = sync
100
+ else
101
+ # don't raise on STDOUT/STDERR write
102
+ log = File.new('/dev/null', File::WRONLY | File::BINARY)
103
+ end
104
+
105
+ # disconnect
106
+ STDIN.close # raise IOError on STDIN.read
107
+ STDOUT.reopen log
108
+ STDERR.reopen log
109
+
110
+ # provide log IO
111
+ return log
112
+ end
113
+ end
@@ -1,23 +1,282 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
  require 'daemon'
3
-
4
- $pf = 'test.pid'
3
+ require 'timeout'
4
+ require 'tempfile'
5
5
 
6
6
  describe Daemon do
7
- it '#lock should create a pid file with current process pid' do
8
- Daemon.lock($pf)
9
- File.open($pf).read.should == "#{Process.pid}\n"
7
+ let! :pid_file do
8
+ Tempfile.new('daemon-pid')
9
+ end
10
+
11
+ let! :log_file do
12
+ Tempfile.new('daemon-log')
10
13
  end
11
14
 
12
- it '#lock should raise error if called twice on same pid file' do
13
- Daemon.lock($pf)
14
- lambda {
15
- Daemon.lock($pf)
16
- }.should raise_error Daemon::LockError
15
+ describe 'locking' do
16
+ it '#lock should create a pid file with current process pid' do
17
+ Daemon.lock(pid_file)
18
+ File.open(pid_file).read.should == "#{Process.pid}\n"
19
+ end
20
+
21
+ it '#lock should raise error if called twice on same pid file' do
22
+ Daemon.lock(pid_file)
23
+ lambda {
24
+ Daemon.lock(pid_file)
25
+ }.should raise_error Daemon::LockError
26
+ end
17
27
  end
18
28
 
19
- after :each do
20
- File.unlink($pf) if File.exist?($pf)
29
+ describe 'forking' do
30
+ it 'forked sub process can be terminated with SIGHUP to whole process group' do
31
+ cr, cw = *IO.pipe
32
+ mr, mw = *IO.pipe
33
+
34
+ pid = fork do # parent
35
+ Process.setsid # start new process group
36
+
37
+ pid = fork do # child
38
+ loop{cr.readline and mw.puts 'pong'}
39
+ end
40
+ Process.wait(pid)
41
+ end
42
+
43
+ # close our end
44
+ mw.close
45
+ cr.close
46
+
47
+ # wait for the child to start
48
+ cw.puts 'ping'
49
+ mr.readline.strip.should == 'pong'
50
+
51
+ Process.kill('HUP', -pid) # kill the group; this should kill the child
52
+ Process.wait(pid) # parent exit
53
+
54
+ expect {
55
+ Timeout.timeout(2) do
56
+ # child is dead
57
+ cw.puts 'ping'
58
+ end
59
+ }.to raise_error Errno::EPIPE
60
+ end
61
+
62
+ it '#fence should start new process group to protect the process from HUP signal' do
63
+ cr, cw = *IO.pipe
64
+ mr, mw = *IO.pipe
65
+
66
+ pid = fork do # parent
67
+ Process.setsid # start new process group
68
+
69
+ Daemon.fence
70
+
71
+ # now in protected child
72
+ loop{cr.readline and mw.puts 'pong'}
73
+ end
74
+ Process.wait(pid) # parent exits
75
+
76
+ # close our end
77
+ mw.close
78
+ cr.close
79
+
80
+ # wait for the child to start
81
+ cw.puts 'ping'
82
+ mr.readline.strip.should == 'pong'
83
+
84
+ expect {
85
+ Process.kill('HUP', -pid)
86
+ # the group is gone with the parent process
87
+ }.to raise_error Errno::ESRCH
88
+
89
+ Timeout.timeout(2) do
90
+ # child still there
91
+ cw.puts 'ping'
92
+ mr.readline.strip.should == 'pong'
93
+ end
94
+ end
95
+
96
+ it '#fence with block should start new process group to protect the process from HUP signal calling provided block within it' do
97
+ cr, cw = *IO.pipe
98
+ mr, mw = *IO.pipe
99
+
100
+ pid = fork do # parent
101
+ Process.setsid # start new process group
102
+
103
+ pid = Daemon.fence do
104
+ # now in protected child
105
+ loop{cr.readline and mw.puts 'pong'}
106
+ end
107
+
108
+ Process.wait(pid)
109
+ end
110
+
111
+ # close our end
112
+ mw.close
113
+ cr.close
114
+
115
+ # wait for the child to start
116
+ cw.puts 'ping'
117
+ mr.readline.strip.should == 'pong'
118
+
119
+ Process.kill('HUP', -pid) # kill the group; this would kill the child
120
+ Process.wait(pid) # parent exit
121
+
122
+ Timeout.timeout(2) do
123
+ # child still there
124
+ cw.puts 'ping'
125
+ mr.readline.strip.should == 'pong'
126
+ end
127
+ end
128
+
129
+ it '#spawn should call block in fenced child process and return child pid and wait thread' do
130
+ pid, wait = Daemon.spawn do |send_ok, send_error|
131
+ send_ok.call
132
+ sleep 0.2
133
+ end
134
+
135
+ pid.should > 0
136
+ wait.should be_alive
137
+
138
+ wait.value.should be_success
139
+ end
140
+
141
+ it '#spawn should call block in fenced child process raising reported errors in master' do
142
+ expect {
143
+ Daemon.spawn do |send_ok, send_error|
144
+ begin
145
+ fail 'test'
146
+ rescue => error
147
+ send_error.call error
148
+ end
149
+ end
150
+ }.to raise_error RuntimeError, 'test'
151
+ end
152
+ end
153
+
154
+ describe 'IO handling' do
155
+ it '#disconnect should close STDIN and redirect STDIN and STDERR to given log file' do
156
+ pid = fork do
157
+ Daemon.disconnect(log_file)
158
+
159
+ puts 'hello world'
160
+ begin
161
+ STDIN.read # should raise
162
+ rescue IOError
163
+ puts 'foo bar'
164
+ end
165
+ end
166
+ Process.wait(pid)
167
+
168
+ log_file.readlines.map(&:strip).should == ['hello world', 'foo bar']
169
+ end
170
+
171
+ it '#disconnect should provide log file IO' do
172
+ pid = fork do
173
+ log = Daemon.disconnect(log_file)
174
+ log.puts 'hello world'
175
+ puts 'foo bar'
176
+ end
177
+ Process.wait(pid)
178
+
179
+ log_file.readlines.map(&:strip).should == ['hello world', 'foo bar']
180
+ end
181
+
182
+ it '#disconnect should provide /dev/null file IO when no log file specified' do
183
+ pid = fork do
184
+ log = Daemon.disconnect
185
+ log.puts 'foo bar'
186
+ log.path.should == '/dev/null'
187
+ end
188
+
189
+ Process.wait2(pid).last.should be_success
190
+ end
191
+
192
+ it '#disconnect should append log file' do
193
+ pid = fork do
194
+ Daemon.disconnect(log_file)
195
+ puts 'hello world'
196
+ end
197
+ Process.wait(pid)
198
+
199
+ pid = fork do
200
+ Daemon.disconnect(log_file)
201
+ puts 'foo bar'
202
+ end
203
+
204
+ Process.wait(pid)
205
+ log_file.readlines.map(&:strip).should == ['hello world', 'foo bar']
206
+ end
207
+ end
208
+
209
+ it '#deamonize should terminate current process while keeping the script running' do
210
+ log_file.open do |log|
211
+
212
+ pid = fork do
213
+ puts master_pid = Process.pid
214
+ Daemon.daemonize(pid_file, log_file, true)
215
+ Process.pid.should_not == master_pid
216
+ puts 'hello world'
217
+ end
218
+
219
+ Process.wait2(pid).last.should be_success # wait for master to go away (successfully)
220
+
221
+ log.readline.map(&:strip).should == ['hello world']
222
+ end
223
+ end
224
+
225
+ it '#deamonize should return log file IO' do
226
+ log_file.open do |log|
227
+ pid = fork do
228
+ log = Daemon.daemonize(pid_file, log_file, true)
229
+ log.puts 'hello world'
230
+ end
231
+ Process.wait2(pid).last.should be_success # wait for master to go away
232
+
233
+ log.readline.map(&:strip).should == ['hello world']
234
+ end
235
+ end
236
+
237
+ it '#daemonize with block should fork new process with pid file and log file and call block with log IO' do
238
+ pid, wait = Daemon.daemonize(pid_file, log_file) do |log|
239
+ log.puts 'hello world'
240
+ puts 'foo bar'
241
+ end
242
+
243
+ # wait for process to finish
244
+ wait.join
245
+
246
+ log_file.readlines.map(&:strip).should == ['hello world', 'foo bar']
247
+ end
248
+
249
+ it '#daemonize with block should raise error when lock file is busy' do
250
+ pid, wait = Daemon.daemonize(pid_file, log_file) do |log|
251
+ log.puts 'hello world'
252
+ puts 'foo bar'
253
+ sleep 1
254
+ end
255
+
256
+ expect {
257
+ Daemon.daemonize(pid_file, log_file){|log|}
258
+ }.to raise_error Daemon::LockError
259
+
260
+ Process.kill('TERM', pid)
261
+ wait.join
262
+
263
+ log_file.readlines.map(&:strip).should == ['hello world', 'foo bar']
264
+ end
265
+
266
+ it '#daemnize should not call at_exit handler' do
267
+ pid = fork do
268
+ pid = Process.pid
269
+ at_exit do
270
+ fail 'at_exit called' if pid != Process.pid
271
+ end
272
+
273
+ fork do
274
+ Daemon.daemonize(pid_file, '/dev/stdout')
275
+ exit! # dont call at_exit
276
+ end
277
+ Process.wait
278
+ end
279
+ Process.wait2(pid).last.should be_success
21
280
  end
22
281
  end
23
282
 
metadata CHANGED
@@ -1,108 +1,73 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: daemon
3
- version: !ruby/object:Gem::Version
4
- hash: 19
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.2.0
5
5
  prerelease:
6
- segments:
7
- - 1
8
- - 1
9
- - 0
10
- version: 1.1.0
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Jakub Pastuszek
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2011-09-28 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
21
- requirement: &id001 !ruby/object:Gem::Requirement
12
+ date: 2014-09-01 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
22
17
  none: false
23
- requirements:
18
+ requirements:
24
19
  - - ~>
25
- - !ruby/object:Gem::Version
26
- hash: 3
27
- segments:
28
- - 2
29
- - 3
30
- - 0
31
- version: 2.3.0
32
- version_requirements: *id001
33
- name: rspec
34
- prerelease: false
20
+ - !ruby/object:Gem::Version
21
+ version: '2.13'
35
22
  type: :development
36
- - !ruby/object:Gem::Dependency
37
- requirement: &id002 !ruby/object:Gem::Requirement
38
- none: false
39
- requirements:
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- hash: 3
43
- segments:
44
- - 0
45
- version: "0"
46
- version_requirements: *id002
47
- name: shoulda
48
23
  prerelease: false
49
- type: :development
50
- - !ruby/object:Gem::Dependency
51
- requirement: &id003 !ruby/object:Gem::Requirement
24
+ version_requirements: !ruby/object:Gem::Requirement
52
25
  none: false
53
- requirements:
26
+ requirements:
54
27
  - - ~>
55
- - !ruby/object:Gem::Version
56
- hash: 23
57
- segments:
58
- - 1
59
- - 0
60
- - 0
61
- version: 1.0.0
62
- version_requirements: *id003
63
- name: bundler
64
- prerelease: false
65
- type: :development
66
- - !ruby/object:Gem::Dependency
67
- requirement: &id004 !ruby/object:Gem::Requirement
28
+ - !ruby/object:Gem::Version
29
+ version: '2.13'
30
+ - !ruby/object:Gem::Dependency
31
+ name: jeweler
32
+ requirement: !ruby/object:Gem::Requirement
68
33
  none: false
69
- requirements:
34
+ requirements:
70
35
  - - ~>
71
- - !ruby/object:Gem::Version
72
- hash: 7
73
- segments:
74
- - 1
75
- - 6
76
- - 4
77
- version: 1.6.4
78
- version_requirements: *id004
79
- name: jeweler
80
- prerelease: false
36
+ - !ruby/object:Gem::Version
37
+ version: 1.8.4
81
38
  type: :development
82
- - !ruby/object:Gem::Dependency
83
- requirement: &id005 !ruby/object:Gem::Requirement
84
- none: false
85
- requirements:
86
- - - ">="
87
- - !ruby/object:Gem::Version
88
- hash: 3
89
- segments:
90
- - 0
91
- version: "0"
92
- version_requirements: *id005
93
- name: rcov
94
39
  prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 1.8.4
46
+ - !ruby/object:Gem::Dependency
47
+ name: rdoc
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '3.9'
95
54
  type: :development
96
- description: Make calling script to become a daemon with pid file locking support and stdout/stderr redirection
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '3.9'
62
+ description: Make calling script to become a daemon with pid file locking support
63
+ and stdout/stderr redirection
97
64
  email: jpastuszek@gmail.com
98
65
  executables: []
99
-
100
66
  extensions: []
101
-
102
- extra_rdoc_files:
67
+ extra_rdoc_files:
103
68
  - LICENSE.txt
104
69
  - README.rdoc
105
- files:
70
+ files:
106
71
  - .document
107
72
  - Gemfile
108
73
  - Gemfile.lock
@@ -115,37 +80,31 @@ files:
115
80
  - spec/daemon_spec.rb
116
81
  - spec/spec_helper.rb
117
82
  homepage: http://github.com/jpastuszek/daemon
118
- licenses:
83
+ licenses:
119
84
  - MIT
120
85
  post_install_message:
121
86
  rdoc_options: []
122
-
123
- require_paths:
87
+ require_paths:
124
88
  - lib
125
- required_ruby_version: !ruby/object:Gem::Requirement
89
+ required_ruby_version: !ruby/object:Gem::Requirement
126
90
  none: false
127
- requirements:
128
- - - ">="
129
- - !ruby/object:Gem::Version
130
- hash: 3
131
- segments:
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ segments:
132
96
  - 0
133
- version: "0"
134
- required_rubygems_version: !ruby/object:Gem::Requirement
97
+ hash: -3235773960414260177
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
99
  none: false
136
- requirements:
137
- - - ">="
138
- - !ruby/object:Gem::Version
139
- hash: 3
140
- segments:
141
- - 0
142
- version: "0"
100
+ requirements:
101
+ - - ! '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
143
104
  requirements: []
144
-
145
105
  rubyforge_project:
146
- rubygems_version: 1.8.10
106
+ rubygems_version: 1.8.23
147
107
  signing_key:
148
108
  specification_version: 3
149
109
  summary: Daemonize your script with a single line of code
150
110
  test_files: []
151
-