daemons 1.2.6 → 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: fc83cd9641e813a84137af3a5ee5a0ce14ae8b3f
4
- data.tar.gz: 6ff0dedb0c407a49ab2b3037fe7aeba50c161ee4
2
+ SHA256:
3
+ metadata.gz: cb08e3c11dd04ba70fdfa9a27e41d004839a48318b77bf7edb5e93976de129f7
4
+ data.tar.gz: 683d0ed93f6a41378a3ed585035b773f4008a147542ab6f29281374aa746ccf9
5
5
  SHA512:
6
- metadata.gz: e712b26c9135ec38e02d4283ae52cfdf2b13f22c7168d66e66563223e34653f1603232e6e2dc65c1a5f39df8411f59fd9a1e6be106ae878456a4ef6d314d5eed
7
- data.tar.gz: 8ba557b1f944a37544079bac30b25a86395c8e74366eca728ef9e245f12c1d2483a9ee777f715390c6975c45f6fb522162e69a95fc2d2b945ee512814f7d3047
6
+ metadata.gz: 9a8743b8307c977149bcfbb1d6b6b36897a1c750ef63a25f7225d7b1774eaffd128843a1d92d626c3062ff680066831214eed8dc3523216b61f15b355701f4d5
7
+ data.tar.gz: de074de7aa4ba81a507d9b06f900c2eb044628ceb3a02b5cf4abb717dfdbf6df52c56f709caa85b223d8a18b9da2c0057017074089832412a231499ef050dcde
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2005-2017 Thomas Uehlinger, 2014-2016 Aaron Stone
1
+ Copyright (c) 2005-2021 Thomas Uehlinger, 2014-2016 Aaron Stone
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person
4
4
  obtaining a copy of this software and associated documentation
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
- Ruby Daemons
2
- ============
1
+ # Ruby Daemons
2
+
3
3
  [![Build Status](https://travis-ci.org/thuehlinger/daemons.svg?branch=master)](https://travis-ci.org/thuehlinger/daemons)[![Code Climate](https://codeclimate.com/github/acuppy/daemons/badges/gpa.svg)](https://codeclimate.com/github/acuppy/daemons)[![Test Coverage](https://circleci.com/gh/acuppy/daemons.svg?style=shield&circle-token=a4f96fd41f7682661d6543e30207427ac8870c0d)](https://circleci.com/gh/acuppy/daemons)
4
4
 
5
5
  Daemons provides an easy way to wrap existing ruby scripts (for example a self-written server)
@@ -12,8 +12,7 @@ Besides this basic functionality, daemons offers many advanced features like _ex
12
12
  and logging (in case your ruby script crashes) and _monitoring_ and automatic restarting of your processes
13
13
  if they crash.
14
14
 
15
- Basic Usage
16
- -----------
15
+ ## Basic Usage
17
16
 
18
17
  You can use Daemons in four different ways:
19
18
 
@@ -45,7 +44,7 @@ Daemons.run('myserver.rb')
45
44
 
46
45
  And use it like this from the console:
47
46
 
48
- ``` ruby
47
+ ``` sh
49
48
  $ ruby myserver_control.rb start
50
49
  (myserver.rb is now running in the background)
51
50
  $ ruby myserver_control.rb restart
@@ -55,18 +54,17 @@ $ ruby myserver_control.rb stop
55
54
 
56
55
  For testing purposes you can even run `myserver.rb` _without forking_ in the background:
57
56
 
58
- ``` ruby
57
+ ``` sh
59
58
  $ ruby myserver_control.rb run
60
59
  ```
61
60
 
62
61
  An additional nice feature of Daemons is that you can pass _additional arguments_ to the script that
63
62
  should be daemonized by seperating them by two _hyphens_:
64
63
 
65
- ``` ruby
64
+ ``` sh
66
65
  $ ruby myserver_control.rb start -- --file=anyfile --a_switch another_argument
67
66
  ```
68
67
 
69
-
70
68
  ### 2. Create wrapper scripts that include your server procs
71
69
 
72
70
  Layout: suppose you have some code you want to run in the background and control that background process
@@ -96,7 +94,7 @@ end
96
94
 
97
95
  And use it like this from the console:
98
96
 
99
- ``` ruby
97
+ ``` sh
100
98
  $ ruby myproc_control.rb start
101
99
  (myproc.rb is now running in the background)
102
100
  $ ruby myproc_control.rb restart
@@ -106,7 +104,7 @@ $ ruby myproc_control.rb stop
106
104
 
107
105
  For testing purposes you can even run `myproc.rb` _without forking_ in the background:
108
106
 
109
- ``` ruby
107
+ ``` sh
110
108
  $ ruby myproc_control.rb run
111
109
  ```
112
110
 
@@ -169,13 +167,12 @@ end
169
167
 
170
168
  For further documentation, refer to the module documentation of Daemons.
171
169
 
172
- Displaying daemon status
173
- ------------------------
170
+ ## Displaying daemon status
174
171
 
175
172
  When daemonizing a process using a wrapper script, as examples 1 and 2 above,
176
173
  the status can be shown using
177
174
 
178
- ``` ruby
175
+ ``` sh
179
176
  $ ruby myproc_control.rb status
180
177
  ```
181
178
 
@@ -201,12 +198,10 @@ end
201
198
  Daemons.run('myserver.rb', { show_status_callback: :custom_show_status })
202
199
  ```
203
200
 
204
- Documenation
205
- -------------------
201
+ ## Documentation
206
202
 
207
- Documentation can be found at http://www.rubydoc.info/gems/daemons.
203
+ Documentation can be found at <http://www.rubydoc.info/gems/daemons>.
208
204
 
209
- Author
210
- ------
205
+ ## Author
211
206
 
212
- Written 2005-2017 by Thomas Uehlinger, 2014-2016 by Aaron Stone.
207
+ Written 2005-2021 by Thomas Uehlinger, 2014-2016 by Aaron Stone.
data/Releases CHANGED
@@ -1,5 +1,26 @@
1
1
  = Daemons Release History
2
2
 
3
+ == Release 1.4.1: August 26, 2021
4
+
5
+ * Fix :proc mode (pass &block explicitly) (thanks to Graham Rogers)
6
+ * Fix style of REAMDE.md
7
+
8
+ == Release 1.4.0: May 1, 2021
9
+
10
+ * Allow for customization which signals are sent to stop process (thanks to philister)
11
+ * Resolves mismatched indentations (thanks to Luis M Rodriguez)
12
+ * Allow to use pry-byebug 3.8.0 (thanks to kamipo)
13
+
14
+ == Release 1.3.1: December 14, 2018
15
+
16
+ * Fix undefined local variable or method `pid_delimiter'
17
+
18
+ == Release 1.3.0: December 10, 2018
19
+
20
+ * Make logging more configurable.
21
+ * Add configuration options for pid file delimters, force_kill_waittime
22
+ * All status callback to be anything callable.
23
+
3
24
  == Release 1.2.6: December 24, 2017
4
25
 
5
26
  * Add links to rubydoc.info documentation.
@@ -31,11 +31,13 @@ module Daemons
31
31
  ['dir', 'log_dir', 'logfilename', 'output_logfilename'].each do |k|
32
32
  @options[k] = File.expand_path(@options[k]) if @options.key?(k)
33
33
  end
34
-
34
+
35
35
  @dir_mode = @dir = @script = nil
36
36
 
37
37
  @force_kill_waittime = @options[:force_kill_waittime] || 20
38
38
 
39
+ @signals_and_waits = parse_signals_and_waits(@options[:signals_and_waits])
40
+
39
41
  @show_status_callback = method(:default_show_status)
40
42
 
41
43
  @report = Reporter.new(@options)
@@ -44,7 +46,7 @@ module Daemons
44
46
  if @options[:no_pidfiles]
45
47
  @pid = PidMem.new
46
48
  elsif dir = pidfile_dir
47
- @pid = PidFile.new(dir, @group.app_name, @group.multiple)
49
+ @pid = PidFile.new(dir, @group.app_name, @group.multiple, @options[:pid_delimiter])
48
50
  else
49
51
  @pid = PidMem.new
50
52
  end
@@ -52,7 +54,12 @@ module Daemons
52
54
  end
53
55
 
54
56
  def show_status_callback=(function)
55
- @show_status_callback = method(function)
57
+ @show_status_callback =
58
+ if function.respond_to?(:call)
59
+ function
60
+ else
61
+ method(function)
62
+ end
56
63
  end
57
64
 
58
65
  def change_privilege
@@ -198,7 +205,7 @@ module Daemons
198
205
  if $daemons_stop_proc
199
206
  $daemons_stop_proc.call
200
207
  end
201
- rescue ::Exception
208
+ rescue ::Exception
202
209
  end
203
210
 
204
211
  begin; @pid.cleanup; rescue ::Exception; end
@@ -255,7 +262,7 @@ module Daemons
255
262
  if $daemons_stop_proc
256
263
  $daemons_stop_proc.call
257
264
  end
258
- rescue ::Exception
265
+ rescue ::Exception
259
266
  end
260
267
 
261
268
  begin; @pid.cleanup; rescue ::Exception; end
@@ -368,6 +375,7 @@ module Daemons
368
375
  return
369
376
  end
370
377
 
378
+ # confusing: pid is also a attribute_reader
371
379
  pid = @pid.pid
372
380
 
373
381
  # Catch errors when trying to kill a process that doesn't
@@ -375,47 +383,12 @@ module Daemons
375
383
  # restarted by the monitor yet. By catching the error, we allow the
376
384
  # pid file clean-up to occur.
377
385
  begin
378
- Process.kill(SIGNAL, pid)
386
+ wait_and_retry_kill_harder(pid, @signals_and_waits, no_wait)
379
387
  rescue Errno::ESRCH => e
380
388
  @report.output_message("#{e} #{pid}")
381
389
  @report.output_message('deleting pid-file.')
382
390
  end
383
391
 
384
- unless no_wait
385
- if @force_kill_waittime > 0
386
- @report.stopping_process(group.app_name, pid)
387
- $stdout.flush
388
-
389
- begin
390
- Timeout.timeout(@force_kill_waittime, TimeoutError) do
391
- while Pid.running?(pid)
392
- sleep(0.2)
393
- end
394
- end
395
- rescue TimeoutError
396
- @report.forcefully_stopping_process(group.app_name, pid)
397
- $stdout.flush
398
-
399
- begin
400
- Process.kill('KILL', pid)
401
- rescue Errno::ESRCH
402
- end
403
-
404
- begin
405
- Timeout.timeout(20, TimeoutError) do
406
- while Pid.running?(pid)
407
- sleep(1)
408
- end
409
- end
410
- rescue TimeoutError
411
- @report.cannot_stop_process(group.app_name, pid)
412
- $stdout.flush
413
- end
414
- end
415
- end
416
-
417
- end
418
-
419
392
  sleep(0.1)
420
393
  unless Pid.running?(pid)
421
394
  # We try to remove the pid-files by ourselves, in case the application
@@ -423,7 +396,30 @@ module Daemons
423
396
  zap!
424
397
 
425
398
  @report.stopped_process(group.app_name, pid)
426
- $stdout.flush
399
+ end
400
+ end
401
+
402
+ # @param Hash remaing_signals
403
+ # @param Boolean no_wait Send first Signal and return
404
+ def wait_and_retry_kill_harder(pid, remaining_signals, no_wait = false)
405
+ sig_wait = remaining_signals.shift
406
+ sig = sig_wait[:sig]
407
+ wait = sig_wait[:wait]
408
+ Process.kill(sig, pid)
409
+ return if no_wait || !wait.positive?
410
+
411
+ @report.stopping_process(group.app_name, pid, sig, wait)
412
+
413
+ begin
414
+ Timeout.timeout(wait, TimeoutError) do
415
+ sleep(0.2) while Pid.running?(pid)
416
+ end
417
+ rescue TimeoutError
418
+ if remaining_signals.any?
419
+ wait_and_retry_kill_harder(pid, remaining_signals)
420
+ else
421
+ @report.cannot_stop_process(group.app_name, pid)
422
+ end
427
423
  end
428
424
  end
429
425
 
@@ -473,5 +469,15 @@ module Daemons
473
469
  def dir
474
470
  @dir or group.dir
475
471
  end
472
+
473
+ def parse_signals_and_waits(argv)
474
+ unless argv
475
+ return [
476
+ { sig: 'TERM', wait: @force_kill_waittime },
477
+ { sig: 'KILL', wait: 20 }
478
+ ]
479
+ end
480
+ argv.split('|').collect{ |part| splitted = part.split(':'); {sig: splitted[0], wait: splitted[1].to_i}}
481
+ end
476
482
  end
477
483
  end
@@ -38,8 +38,11 @@ module Daemons
38
38
  @dir = @options[:dir] || ''
39
39
 
40
40
  @keep_pid_files = @options[:keep_pid_files] || false
41
+
41
42
  @no_pidfiles = @options[:no_pidfiles] || false
42
43
 
44
+ @pid_delimiter = @options[:pid_delimiter]
45
+
43
46
  @applications = []
44
47
  end
45
48
 
@@ -80,7 +83,7 @@ module Daemons
80
83
  end
81
84
  pids = processes.map { |p| p.split(/\s/)[0].to_i }
82
85
  end
83
- rescue ::Exception
86
+ rescue ::Exception
84
87
  end
85
88
 
86
89
  pids.map do |f|
@@ -94,7 +97,7 @@ module Daemons
94
97
  @monitor = Monitor.find(dir, app_name + '_monitor')
95
98
 
96
99
  reporter = Reporter.new(options)
97
- pid_files = PidFile.find_files(dir, app_name, ! @keep_pid_files) do |pid, file|
100
+ pid_files = PidFile.find_files(dir, app_name, ! @keep_pid_files, @pid_delimiter) do |pid, file|
98
101
  reporter.deleted_found_pidfile(pid, file)
99
102
  end
100
103
 
@@ -12,7 +12,7 @@ module Daemons
12
12
  opts.on('-t', '--ontop', 'Stay on top (does not daemonize)') do |t|
13
13
  @options[:ontop] = t
14
14
  end
15
-
15
+
16
16
  opts.on('-s', '--shush', 'Silent mode (no output to the terminal)') do |t|
17
17
  @options[:shush] = t
18
18
  end
@@ -25,9 +25,40 @@ module Daemons
25
25
  @options[:no_wait] = t
26
26
  end
27
27
 
28
+ opts.on('-w', '--force_kill_waittime SECONDS', Integer, 'Maximum time to wait for processes to stop before force-killing') do |t|
29
+ @options[:force_kill_waittime] = t
30
+ end
31
+ opts.on('--signals_and_waits STRING', String, 'which signal to use to stop and how long to wait e.g. TERM:20|KILL:20') do |t|
32
+ @options[:signals_and_waits] = t
33
+ end
34
+
35
+ opts.on('--pid_delimiter STRING', 'Text used to separate process number in full process name and pid-file name') do |value|
36
+ @options[:pid_delimiter] = value
37
+ end
38
+
28
39
  opts.separator ''
29
40
  opts.separator 'Common options:'
30
41
 
42
+ opts.on('-l', '--log_output', 'Enable input/output stream redirection') do |value|
43
+ @options[:log_output] = value
44
+ end
45
+
46
+ opts.on('--logfilename FILE', String, 'Custom log file name for exceptions') do |value|
47
+ @options[:logfilename] = value
48
+ end
49
+
50
+ opts.on('--output_logfilename FILE', String, 'Custom file name for input/output stream redirection log') do |value|
51
+ @options[:output_logfilename] = value
52
+ end
53
+
54
+ opts.on('--log_dir DIR', String, 'Directory for log files') do |value|
55
+ @options[:log_dir] = value
56
+ end
57
+
58
+ opts.on('--syslog', 'Enable output redirction into SYSLOG instead of a file') do |value|
59
+ @options[:log_output_syslog] = value
60
+ end
61
+
31
62
  # No argument, shows at tail. This will print an options summary
32
63
  opts.on_tail('-h', '--help', 'Show this message') do
33
64
  controller.print_usage
@@ -62,7 +93,7 @@ END
62
93
  def parse(args)
63
94
  # The options specified on the command line will be collected in *options*.
64
95
  # We set default values here.
65
-
96
+
66
97
  @opts.parse(args)
67
98
 
68
99
  @options
@@ -71,20 +102,21 @@ END
71
102
 
72
103
  class Controller
73
104
  def print_usage
74
- puts "Usage: #{@app_name} <command> <options> -- <application options>"
75
- puts
76
- puts '* where <command> is one of:'
77
- puts ' start start an instance of the application'
78
- puts ' stop stop all instances of the application'
79
- puts ' restart stop all instances and restart them afterwards'
80
- puts ' reload send a SIGHUP to all instances of the application'
81
- puts ' run start the application and stay on top'
82
- puts ' zap set the application to a stopped state'
83
- puts ' status show status (PID) of application instances'
84
- puts
85
- puts '* and where <options> may contain several of the following:'
86
-
87
- puts @optparse.usage
105
+ puts <<-USAGE.gsub(/^ {6}/, '')
106
+ Usage: #{@app_name} <command> <options> -- <application options>
107
+
108
+ * where <command> is one of:
109
+ start start an instance of the application
110
+ stop stop all instances of the application
111
+ restart stop all instances and restart them afterwards
112
+ reload send a SIGHUP to all instances of the application
113
+ run run the application in the foreground (same as start -t)
114
+ zap set the application to a stopped state
115
+ status show status (PID) of application instances
116
+
117
+ * and where <options> may contain several of the following:
118
+ #{@optparse.usage}
119
+ USAGE
88
120
  end
89
121
 
90
122
  def catch_exceptions(&block)
@@ -13,8 +13,8 @@ module Daemons
13
13
  # === How does a Pid-File look like?
14
14
  #
15
15
  # Pid-Files generated by Daemons have to following format:
16
- # <scriptname>.rb<number>.pid
17
- # (Note that <tt><number></tt> is omitted if only one instance of the script can
16
+ # <scriptname>_num<number>.pid
17
+ # (Note that <tt>_num<number></tt> is omitted if only one instance of the script can
18
18
  # run at any time)
19
19
  #
20
20
  # Each file just contains one line with the pid as string (for example <tt>6432</tt>).
@@ -28,10 +28,11 @@ module Daemons
28
28
  # 3. in the preconfigured directory <tt>/var/run</tt> (<tt>:system</tt> option for <tt>:dir_mode</tt>)
29
29
  #
30
30
  class PidFile < Pid
31
- attr_reader :dir, :progname, :multiple, :number
31
+ DEFAULT_PID_DELIMITER = '_num'
32
+ attr_reader :dir, :progname, :multiple, :number, :pid_delimiter
32
33
 
33
- def self.find_files(dir, progname, delete = false)
34
- files = Dir[File.join(dir, "#{progname}_num*.pid")]
34
+ def self.find_files(dir, progname, delete = false, pid_delimiter = nil)
35
+ files = Dir[File.join(dir, "#{progname}#{pid_delimiter || DEFAULT_PID_DELIMITER}*.pid")]
35
36
  files = Dir[File.join(dir, "#{progname}.pid")] if files.size == 0
36
37
 
37
38
  files.delete_if { |f| not (File.file?(f) and File.readable?(f)) }
@@ -62,10 +63,11 @@ module Daemons
62
63
  new_instance
63
64
  end
64
65
 
65
- def initialize(dir, progname, multiple = false)
66
+ def initialize(dir, progname, multiple = false, pid_delimiter = nil)
66
67
  @dir = File.expand_path(dir)
67
68
  @progname = progname
68
69
  @multiple = multiple
70
+ @pid_delimiter = pid_delimiter || DEFAULT_PID_DELIMITER
69
71
  @number = nil
70
72
  @number = 0 if multiple
71
73
 
@@ -81,7 +83,8 @@ module Daemons
81
83
  end
82
84
 
83
85
  def filename
84
- File.join(@dir, "#{@progname}#{@number ? '_num' + @number.to_s : '' }.pid")
86
+ suffix = "#{pid_delimiter}#{@number}" if @number
87
+ File.join(@dir, "#{@progname}#{suffix}.pid")
85
88
  end
86
89
 
87
90
  def exist?
@@ -32,20 +32,19 @@ module Daemons
32
32
  output_message 'option :backtrace is not supported with :mode => :exec, ignoring'
33
33
  end
34
34
 
35
- def stopping_process(app_name, pid)
36
- output_message "#{app_name}: trying to stop process with pid #{pid}..."
37
- end
38
-
39
- def forcefully_stopping_process(app_name, pid)
40
- output_message "#{app_name}: process with pid #{pid} won't stop, we forcefully kill it..."
35
+ def stopping_process(app_name, pid, sig, wait)
36
+ output_message "#{app_name}: trying to stop process with pid #{pid}#{' forcefully :(' if sig == 'KILL'} sending #{sig} and waiting #{wait}s ..."
37
+ $stdout.flush
41
38
  end
42
39
 
43
40
  def cannot_stop_process(app_name, pid)
44
41
  output_message "#{app_name}: unable to forcefully kill process with pid #{pid}."
42
+ $stdout.flush
45
43
  end
46
44
 
47
45
  def stopped_process(app_name, pid)
48
46
  output_message "#{app_name}: process with pid #{pid} successfully stopped."
47
+ $stdout.flush
49
48
  end
50
49
 
51
50
  def status(app_name, running, pid_exists, pid)
@@ -1,3 +1,3 @@
1
1
  module Daemons
2
- VERSION = '1.2.6'
2
+ VERSION = '1.4.1'
3
3
  end
data/lib/daemons.rb CHANGED
@@ -99,6 +99,7 @@ module Daemons
99
99
  # <tt>:dir</tt>:: Used in combination with <tt>:dir_mode</tt> (description above)
100
100
  # <tt>:multiple</tt>:: Specifies whether multiple instances of the same script are allowed to run at the
101
101
  # same time
102
+ # <tt>:pid_delimiter</tt>:: Specifies the separator used when enumerating multiple process names/pid-files. Default is '_num'.
102
103
  # <tt>:ontop</tt>:: When given (i.e. set to true), stay on top, i.e. do not daemonize the application
103
104
  # (but the pid-file and other things are written as usual)
104
105
  # <tt>:shush</tt>:: When given (i.e. set to true), turn on silent mode (no output to the terminal)
@@ -129,6 +130,7 @@ module Daemons
129
130
  # :dir_mode => :script,
130
131
  # :dir => 'pids',
131
132
  # :multiple => true,
133
+ # :pid_delimiter => '.n',
132
134
  # :ontop => true,
133
135
  # :shush => false,
134
136
  # :mode => :exec,
@@ -249,7 +251,7 @@ module Daemons
249
251
  fail 'Daemons.call: no block given' unless block_given?
250
252
 
251
253
  options[:app_name] ||= 'proc'
252
- options[:proc] = Proc.new
254
+ options[:proc] = Proc.new(&block)
253
255
  options[:mode] = :proc
254
256
  options[:dir_mode] = :normal
255
257
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: daemons
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.6
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Uehlinger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-12-24 00:00:00.000000000 Z
11
+ date: 2021-08-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -16,14 +16,20 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '12.3'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 12.3.3
20
23
  type: :development
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
27
  - - "~>"
25
28
  - !ruby/object:Gem::Version
26
- version: '0'
29
+ version: '12.3'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 12.3.3
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: rspec
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -58,14 +64,14 @@ dependencies:
58
64
  requirements:
59
65
  - - "~>"
60
66
  - !ruby/object:Gem::Version
61
- version: 3.0.0
67
+ version: '3.0'
62
68
  type: :development
63
69
  prerelease: false
64
70
  version_requirements: !ruby/object:Gem::Requirement
65
71
  requirements:
66
72
  - - "~>"
67
73
  - !ruby/object:Gem::Version
68
- version: 3.0.0
74
+ version: '3.0'
69
75
  description: |2
70
76
  Daemons provides an easy way to wrap existing ruby scripts (for example a
71
77
  self-written server) to be run as a daemon and to be controlled by simple
@@ -147,8 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
147
153
  - !ruby/object:Gem::Version
148
154
  version: '0'
149
155
  requirements: []
150
- rubyforge_project:
151
- rubygems_version: 2.5.2
156
+ rubygems_version: 3.0.3
152
157
  signing_key:
153
158
  specification_version: 4
154
159
  summary: A toolkit to create and control daemons in different ways