daemons 1.2.4 → 1.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 860b58ef469300cda2269a45f189796af8f36bcb
4
- data.tar.gz: 29894094754c8013a9901f918f9e9ca2d700258f
2
+ SHA256:
3
+ metadata.gz: 5114c4c5cb5dba3befcc82f6eaa45d901036bc7357a6d4d81cfd8cad8c49dae6
4
+ data.tar.gz: 0eb7b12972a659d053b87d4d59e24d5a3de21a9ff94c3432e8da62ac08f5c127
5
5
  SHA512:
6
- metadata.gz: cd7e03dbc97d7dcaa21b582b868cea9b5610e52b975737b8c8309ce71f803647d3a87444e04a79b63feb2da895b0ee5ab8624985540c4a5dfba0be916f23d55a
7
- data.tar.gz: c42a97021220ffbbe114349c8fe2ebeff0894b265cd4c2a960cf9efbdce5b0bcf873d92dd393b54fdde336b4d53c8ea4c53d827f567d0313829fd0f4f23c7cdb
6
+ metadata.gz: '00970b9deb9eab30e1ce69b31ceca7617bf406692f5dbbb5a9459c5a5a898bc8a0e751fb751cb463f027be1977b54c0b914fcee996ad0cbea997829ce54d2360'
7
+ data.tar.gz: f98f5696a4f482e29eb22c38fddc9fa6dafcfaaa4c6989a5015191c53711848e703267dc3c0da25080d9509035bf91b7aac7f009b4ccbb6de53fd8a299a4834b
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2005-2016 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,6 +1,6 @@
1
1
  Ruby Daemons
2
2
  ============
3
- [![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)
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)
6
6
  to be _run as a daemon_ and to be _controlled by simple start/stop/restart commands_.
@@ -201,7 +201,12 @@ end
201
201
  Daemons.run('myserver.rb', { show_status_callback: :custom_show_status })
202
202
  ```
203
203
 
204
+ Documentation
205
+ -------------------
206
+
207
+ Documentation can be found at http://www.rubydoc.info/gems/daemons.
208
+
204
209
  Author
205
210
  ------
206
211
 
207
- Written 2005-2016 by Thomas Uehlinger, 2014-2016 by Aaron Stone.
212
+ Written 2005-2021 by Thomas Uehlinger, 2014-2016 by Aaron Stone.
data/Releases CHANGED
@@ -1,5 +1,30 @@
1
1
  = Daemons Release History
2
2
 
3
+ == Release 1.4.0: May 1, 2021
4
+
5
+ * Allow for customization which signals are sent to stop process (thanks to philister)
6
+ * Resolves mismatched indentations (thanks to Luis M Rodriguez)
7
+ * Allow to use pry-byebug 3.8.0 (thanks to kamipo)
8
+
9
+ == Release 1.3.1: December 14, 2018
10
+
11
+ * Fix undefined local variable or method `pid_delimiter'
12
+
13
+ == Release 1.3.0: December 10, 2018
14
+
15
+ * Make logging more configurable.
16
+ * Add configuration options for pid file delimters, force_kill_waittime
17
+ * All status callback to be anything callable.
18
+
19
+ == Release 1.2.6: December 24, 2017
20
+
21
+ * Add links to rubydoc.info documentation.
22
+
23
+ == Release 1.2.5: October 22, 2017
24
+
25
+ * In Application#stop, call zap, not cleanup on the pidfile (thanks to wevanscfi)
26
+ * Use File.expand_path on and output and log files (thanks to Dave Harris)
27
+
3
28
  == Release 1.2.4: August 1, 2016
4
29
 
5
30
  * add :shush option
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,
@@ -238,23 +240,26 @@ module Daemons
238
240
  # end
239
241
  #
240
242
  def call(options = {}, &block)
241
- unless block_given?
242
- fail 'Daemons.call: no block given'
243
- end
243
+ new_app = Daemons.new(options, &block)
244
+ new_app.start
245
+ new_app
246
+ end
247
+ module_function :call
244
248
 
245
- options[:proc] = block
246
- options[:mode] = :proc
249
+ # Create a new Daemon application, like <tt>Daemons.call</tt>, but will not start it automatically
250
+ def new(options = {}, &block)
251
+ fail 'Daemons.call: no block given' unless block_given?
247
252
 
248
253
  options[:app_name] ||= 'proc'
254
+ options[:proc] = Proc.new
255
+ options[:mode] = :proc
256
+ options[:dir_mode] = :normal
249
257
 
250
258
  @group ||= ApplicationGroup.new(options[:app_name], options)
251
259
 
252
- new_app = @group.new_application(options)
253
- new_app.start
254
-
255
- new_app
260
+ @group.new_application(options)
256
261
  end
257
- module_function :call
262
+ module_function :new
258
263
 
259
264
  # Daemonize the currently runnig process, i.e. the calling process will become a daemon.
260
265
  #
@@ -28,10 +28,16 @@ module Daemons
28
28
  @options = group.options.dup
29
29
  @options.update(add_options)
30
30
 
31
+ ['dir', 'log_dir', 'logfilename', 'output_logfilename'].each do |k|
32
+ @options[k] = File.expand_path(@options[k]) if @options.key?(k)
33
+ end
34
+
31
35
  @dir_mode = @dir = @script = nil
32
36
 
33
37
  @force_kill_waittime = @options[:force_kill_waittime] || 20
34
38
 
39
+ @signals_and_waits = parse_signals_and_waits(@options[:signals_and_waits])
40
+
35
41
  @show_status_callback = method(:default_show_status)
36
42
 
37
43
  @report = Reporter.new(@options)
@@ -40,7 +46,7 @@ module Daemons
40
46
  if @options[:no_pidfiles]
41
47
  @pid = PidMem.new
42
48
  elsif dir = pidfile_dir
43
- @pid = PidFile.new(dir, @group.app_name, @group.multiple)
49
+ @pid = PidFile.new(dir, @group.app_name, @group.multiple, @options[:pid_delimiter])
44
50
  else
45
51
  @pid = PidMem.new
46
52
  end
@@ -48,7 +54,12 @@ module Daemons
48
54
  end
49
55
 
50
56
  def show_status_callback=(function)
51
- @show_status_callback = method(function)
57
+ @show_status_callback =
58
+ if function.respond_to?(:call)
59
+ function
60
+ else
61
+ method(function)
62
+ end
52
63
  end
53
64
 
54
65
  def change_privilege
@@ -194,7 +205,7 @@ module Daemons
194
205
  if $daemons_stop_proc
195
206
  $daemons_stop_proc.call
196
207
  end
197
- rescue ::Exception
208
+ rescue ::Exception
198
209
  end
199
210
 
200
211
  begin; @pid.cleanup; rescue ::Exception; end
@@ -251,7 +262,7 @@ module Daemons
251
262
  if $daemons_stop_proc
252
263
  $daemons_stop_proc.call
253
264
  end
254
- rescue ::Exception
265
+ rescue ::Exception
255
266
  end
256
267
 
257
268
  begin; @pid.cleanup; rescue ::Exception; end
@@ -364,6 +375,7 @@ module Daemons
364
375
  return
365
376
  end
366
377
 
378
+ # confusing: pid is also a attribute_reader
367
379
  pid = @pid.pid
368
380
 
369
381
  # Catch errors when trying to kill a process that doesn't
@@ -371,55 +383,43 @@ module Daemons
371
383
  # restarted by the monitor yet. By catching the error, we allow the
372
384
  # pid file clean-up to occur.
373
385
  begin
374
- Process.kill(SIGNAL, pid)
386
+ wait_and_retry_kill_harder(pid, @signals_and_waits, no_wait)
375
387
  rescue Errno::ESRCH => e
376
388
  @report.output_message("#{e} #{pid}")
377
389
  @report.output_message('deleting pid-file.')
378
390
  end
379
391
 
380
- unless no_wait
381
- if @force_kill_waittime > 0
382
- @report.stopping_process(group.app_name, pid)
383
- $stdout.flush
384
-
385
- begin
386
- Timeout.timeout(@force_kill_waittime, TimeoutError) do
387
- while Pid.running?(pid)
388
- sleep(0.2)
389
- end
390
- end
391
- rescue TimeoutError
392
- @report.forcefully_stopping_process(group.app_name, pid)
393
- $stdout.flush
394
-
395
- begin
396
- Process.kill('KILL', pid)
397
- rescue Errno::ESRCH
398
- end
399
-
400
- begin
401
- Timeout.timeout(20, TimeoutError) do
402
- while Pid.running?(pid)
403
- sleep(1)
404
- end
405
- end
406
- rescue TimeoutError
407
- @report.cannot_stop_process(group.app_name, pid)
408
- $stdout.flush
409
- end
410
- end
411
- end
412
-
413
- end
414
-
415
392
  sleep(0.1)
416
393
  unless Pid.running?(pid)
417
394
  # We try to remove the pid-files by ourselves, in case the application
418
395
  # didn't clean it up.
419
- begin; @pid.cleanup; rescue ::Exception; end
396
+ zap!
420
397
 
421
398
  @report.stopped_process(group.app_name, pid)
422
- $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
423
423
  end
424
424
  end
425
425
 
@@ -469,5 +469,15 @@ module Daemons
469
469
  def dir
470
470
  @dir or group.dir
471
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
472
482
  end
473
483
  end
@@ -23,19 +23,25 @@ module Daemons
23
23
  @app_name = app_name
24
24
  @options = options
25
25
 
26
- if options[:script]
27
- @script = File.expand_path(options[:script])
26
+ if @options[:script]
27
+ @script = File.expand_path(@options[:script])
28
28
  end
29
29
 
30
30
  @monitor = nil
31
31
 
32
- @multiple = options[:multiple] || false
32
+ @multiple = @options[:multiple] || false
33
33
 
34
- @dir_mode = options[:dir_mode] || :script
35
- @dir = options[:dir] || ''
34
+ @dir_mode = @options[:dir_mode] || :script
35
+ ['dir'].each do |k|
36
+ @options[k] = File.expand_path(@options[k]) if @options.key?(k)
37
+ end
38
+ @dir = @options[:dir] || ''
39
+
40
+ @keep_pid_files = @options[:keep_pid_files] || false
41
+
42
+ @no_pidfiles = @options[:no_pidfiles] || false
36
43
 
37
- @keep_pid_files = options[:keep_pid_files] || false
38
- @no_pidfiles = options[:no_pidfiles] || false
44
+ @pid_delimiter = @options[:pid_delimiter]
39
45
 
40
46
  @applications = []
41
47
  end
@@ -77,7 +83,7 @@ module Daemons
77
83
  end
78
84
  pids = processes.map { |p| p.split(/\s/)[0].to_i }
79
85
  end
80
- rescue ::Exception
86
+ rescue ::Exception
81
87
  end
82
88
 
83
89
  pids.map do |f|
@@ -91,7 +97,7 @@ module Daemons
91
97
  @monitor = Monitor.find(dir, app_name + '_monitor')
92
98
 
93
99
  reporter = Reporter.new(options)
94
- 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|
95
101
  reporter.deleted_found_pidfile(pid, file)
96
102
  end
97
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)
@@ -61,7 +61,7 @@ module Daemons
61
61
  @group.stop_all(@options[:no_wait])
62
62
  when 'restart'
63
63
  unless @group.applications.empty?
64
- @group.stop_all
64
+ @group.stop_all(@options[:no_wait])
65
65
  sleep(1)
66
66
  @group.start_all
67
67
  else
@@ -107,7 +107,7 @@ module Daemons
107
107
  end
108
108
  rescue ::Exception => e
109
109
  $stderr.puts "exception while trying to stop monitor process #{pid}: #{e}"
110
- $stderr.puts 'deleting pid-file.'
110
+ $stderr.puts "deleting pid-file."
111
111
  end
112
112
 
113
113
  # We try to remove the pid-files by ourselves, in case the monitor
@@ -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?
@@ -100,9 +103,9 @@ module Daemons
100
103
  end
101
104
 
102
105
  def zap
103
- File.delete(filename)
106
+ File.delete(filename) if exist?
104
107
  end
105
-
108
+
106
109
  def pid
107
110
  begin
108
111
  File.open(filename) do |f|
@@ -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.4'
2
+ VERSION = '1.4.0'
3
3
  end
metadata CHANGED
@@ -1,71 +1,77 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: daemons
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.4
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Uehlinger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-01 00:00:00.000000000 Z
11
+ date: 2021-05-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
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
30
36
  requirements:
31
- - - ~>
37
+ - - "~>"
32
38
  - !ruby/object:Gem::Version
33
39
  version: '3.1'
34
40
  type: :development
35
41
  prerelease: false
36
42
  version_requirements: !ruby/object:Gem::Requirement
37
43
  requirements:
38
- - - ~>
44
+ - - "~>"
39
45
  - !ruby/object:Gem::Version
40
46
  version: '3.1'
41
47
  - !ruby/object:Gem::Dependency
42
48
  name: simplecov
43
49
  requirement: !ruby/object:Gem::Requirement
44
50
  requirements:
45
- - - ~>
51
+ - - "~>"
46
52
  - !ruby/object:Gem::Version
47
53
  version: '0'
48
54
  type: :development
49
55
  prerelease: false
50
56
  version_requirements: !ruby/object:Gem::Requirement
51
57
  requirements:
52
- - - ~>
58
+ - - "~>"
53
59
  - !ruby/object:Gem::Version
54
60
  version: '0'
55
61
  - !ruby/object:Gem::Dependency
56
62
  name: pry-byebug
57
63
  requirement: !ruby/object:Gem::Requirement
58
64
  requirements:
59
- - - ~>
65
+ - - "~>"
60
66
  - !ruby/object:Gem::Version
61
- version: '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: '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
@@ -130,24 +136,24 @@ files:
130
136
  homepage: https://github.com/thuehlinger/daemons
131
137
  licenses:
132
138
  - MIT
133
- metadata: {}
139
+ metadata:
140
+ documentation_uri: http://www.rubydoc.info/gems/daemons
134
141
  post_install_message:
135
142
  rdoc_options: []
136
143
  require_paths:
137
144
  - lib
138
145
  required_ruby_version: !ruby/object:Gem::Requirement
139
146
  requirements:
140
- - - '>='
147
+ - - ">="
141
148
  - !ruby/object:Gem::Version
142
149
  version: '0'
143
150
  required_rubygems_version: !ruby/object:Gem::Requirement
144
151
  requirements:
145
- - - '>='
152
+ - - ">="
146
153
  - !ruby/object:Gem::Version
147
154
  version: '0'
148
155
  requirements: []
149
- rubyforge_project:
150
- rubygems_version: 2.4.6
156
+ rubygems_version: 3.0.3
151
157
  signing_key:
152
158
  specification_version: 4
153
159
  summary: A toolkit to create and control daemons in different ways