daemon_runner 0.2.2

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 113e941352f0f027e74475522fbf103a2e2ab2b2
4
+ data.tar.gz: c0fe5567cab12d9db836c618a52295a7a1e4e5d2
5
+ SHA512:
6
+ metadata.gz: a72c199d673e3edcb3af7ea87c307ea85325a76441eaa7aca735d76a30a6f4589e26cd87343fe5cbef7a20d10345d30da3bf830d3554d3d7620a3d7a9f5cdab9
7
+ data.tar.gz: bd0fa329b8ebea978f1344e63eccf15cb416c3770f573d3fd73d0fb35cf2049c670400bd7212a694dcbd6e9226238f35cf2cf997c6481b298b6b71eb44d01642
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.2.4
5
+ before_install: gem install bundler -v 1.12.5
@@ -0,0 +1,49 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of
4
+ fostering an open and welcoming community, we pledge to respect all people who
5
+ contribute through reporting issues, posting feature requests, updating
6
+ documentation, submitting pull requests or patches, and other activities.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, ethnicity, age, religion, or nationality.
12
+
13
+ Examples of unacceptable behavior by participants include:
14
+
15
+ * The use of sexualized language or imagery
16
+ * Personal attacks
17
+ * Trolling or insulting/derogatory comments
18
+ * Public or private harassment
19
+ * Publishing other's private information, such as physical or electronic
20
+ addresses, without explicit permission
21
+ * Other unethical or unprofessional conduct
22
+
23
+ Project maintainers have the right and responsibility to remove, edit, or
24
+ reject comments, commits, code, wiki edits, issues, and other contributions
25
+ that are not aligned to this Code of Conduct, or to ban temporarily or
26
+ permanently any contributor for other behaviors that they deem inappropriate,
27
+ threatening, offensive, or harmful.
28
+
29
+ By adopting this Code of Conduct, project maintainers commit themselves to
30
+ fairly and consistently applying these principles to every aspect of managing
31
+ this project. Project maintainers who do not follow or enforce the Code of
32
+ Conduct may be permanently removed from the project team.
33
+
34
+ This code of conduct applies both within project spaces and in public spaces
35
+ when an individual is representing the project or its community.
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported by contacting a project maintainer at Andrew_Thompson@rapid7.com. All
39
+ complaints will be reviewed and investigated and will result in a response that
40
+ is deemed necessary and appropriate to the circumstances. Maintainers are
41
+ obligated to maintain confidentiality with regard to the reporter of an
42
+ incident.
43
+
44
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
45
+ version 1.3.0, available at
46
+ [http://contributor-covenant.org/version/1/3/0/][version]
47
+
48
+ [homepage]: http://contributor-covenant.org
49
+ [version]: http://contributor-covenant.org/version/1/3/0/
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in daemon_runner.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ gem 'bundler', '~> 1.7'
8
+ gem 'thor-scmversion', '= 1.7.0'
9
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Andrew Thompson
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,119 @@
1
+ # DaemonRunner
2
+
3
+ This is a library that will assist you in writing long running services that are composed of discrete tasks. For example you may want to check that a service is running, or run some command and send it's output somewhere.
4
+
5
+ The basic design consists of a list of tasks that loop forever. The user is responsible to defining what those tasks are and what they do in a subclass.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'daemon_runner'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install daemon_runner
22
+
23
+ ## Usage
24
+
25
+ In order to use this gem you must subclass `DaemonRunner::Client` and add a few methods:
26
+
27
+ * `tasks` - This is an array of tasks to run (**required**)
28
+
29
+ ```ruby
30
+ [
31
+ [ClassName1, method_name, args],
32
+ [ClassName2, method_name, args]
33
+ ]
34
+ ```
35
+
36
+ * `wait` - Setup hook to run before starting tasks (**optional**)
37
+
38
+ * `options` - Options hash to pass to `initialize` (**required**)
39
+ * :loop_sleep_time - Number of seconds to sleep before starting tasks again (**optional**, _default_: 5 seconds)
40
+ * :error_sleep_time - Number of seconds to sleep before retying a failed task (**optional**, _default_: 5 seconds)
41
+ * :post_task_sleep_time - Number of seconds to sleep after each task (**optional**, _default_: 1 seconds)
42
+
43
+ ### Example
44
+
45
+ ```ruby
46
+ #!/usr/bin/env ruby
47
+
48
+ require_relative '../lib/daemon_runner'
49
+
50
+ class MyService
51
+ class Tasks
52
+ class Foo
53
+ def run!
54
+ puts 'foo'
55
+ 'foo'
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ class MyService
62
+ class Tasks
63
+ class Bar
64
+ def run!(name)
65
+ puts name
66
+ name
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ class MyService
73
+ class Tasks
74
+ class Baz
75
+ class << self
76
+ def run!(args)
77
+ name = args[0]
78
+ reason = args[1]
79
+ puts name
80
+ puts reason
81
+ name
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ class MyService
89
+ class Client < DaemonRunner::Client
90
+ def tasks
91
+ [
92
+ [::MyService::Tasks::Foo.new, 'run!'],
93
+ [::MyService::Tasks::Bar.new, 'run!', 'bar'],
94
+ [::MyService::Tasks::Baz, 'run!', 'baz', 'because']
95
+ ]
96
+ end
97
+ end
98
+ end
99
+
100
+ options = {}
101
+ service = MyService::Client.new(options)
102
+ service.start!
103
+ ```
104
+
105
+
106
+ ## Development
107
+
108
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
109
+
110
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
111
+
112
+ ## Contributing
113
+
114
+ Bug reports and pull requests are welcome on GitHub at https://github.com/rapid7/daemon_runner. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
115
+
116
+
117
+ ## License
118
+
119
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :test
data/Thorfile ADDED
@@ -0,0 +1,5 @@
1
+ # encoding: utf-8
2
+
3
+ require 'bundler'
4
+ require 'bundler/setup'
5
+ require 'thor/scmversion'
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "daemon_runner"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'daemon_runner/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "daemon_runner"
8
+ spec.version = DaemonRunner::VERSION
9
+ spec.authors = ["Andrew Thompson"]
10
+ spec.email = ["Andrew_Thompson@rapid7.com"]
11
+
12
+ spec.summary = %q{Small library to make writing long running services easy}
13
+ spec.homepage = "https://github.com/rapid7/daemon_runner/"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "logging", "~> 2.1"
22
+ spec.add_dependency "mixlib-shellout", "~> 2.2"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.12"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "minitest", "~> 5.0"
27
+ spec.add_development_dependency "yard", "~> 0.8.7"
28
+ end
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/daemon_runner'
4
+
5
+ class MyService
6
+ class Tasks
7
+ class Foo
8
+ def run!
9
+ puts 'foo'
10
+ 'foo'
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ class MyService
17
+ class Tasks
18
+ class Bar
19
+ def run!(name)
20
+ puts name
21
+ name
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ class MyService
28
+ class Tasks
29
+ class Baz
30
+ class << self
31
+ def run!(args)
32
+ name = args[0]
33
+ reason = args[1]
34
+ puts name
35
+ puts reason
36
+ name
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ class MyService
44
+ class Client < DaemonRunner::Client
45
+ def tasks
46
+ [
47
+ [::MyService::Tasks::Foo.new, 'run!'],
48
+ [::MyService::Tasks::Bar.new, 'run!', 'bar'],
49
+ [::MyService::Tasks::Baz, 'run!', 'baz', 'because']
50
+ ]
51
+ end
52
+ end
53
+ end
54
+
55
+ options = {}
56
+ service = MyService::Client.new(options)
57
+ service.start!
@@ -0,0 +1,132 @@
1
+ module DaemonRunner
2
+ class Client
3
+ include Logger
4
+
5
+ # @attribute [r]
6
+ # Options hash
7
+ attr_reader :options
8
+
9
+
10
+ def initialize(options)
11
+ @options = options
12
+ end
13
+
14
+ # Hook to allow initial setup tasks before running tasks.
15
+ # @abstract Override {#wait} to pause before starting.
16
+ # @return [void]
17
+ def wait
18
+ end
19
+
20
+ # List of tasks that get executed in {#start!}
21
+ # @abstract Override {#tasks} in a subclass.
22
+ # @return [Array<Array>]
23
+ # @example Example tasks method
24
+ # def tasks
25
+ # [
26
+ # [::MyService::Tasks::Foo.new, 'run!'],
27
+ # [::MyService::Tasks::Bar.new, 'run!', 'bar'],
28
+ # [::MyService::Tasks::Baz, 'run!', 'baz', 'because']
29
+ # ]
30
+ # end
31
+ def tasks
32
+ raise NotImplementedError, 'Must implement this in a subclass. \
33
+ This must be an array of methods for the runner to call'
34
+ end
35
+
36
+ # @return [Fixnum] Number of seconds to sleep between loop interations.
37
+ def loop_sleep_time
38
+ return @loop_sleep_time unless @loop_sleep_time.nil?
39
+ @loop_sleep_time = if options[:loop_sleep_time].nil?
40
+ 5
41
+ else
42
+ options[:loop_sleep_time]
43
+ end
44
+ end
45
+
46
+ # @return [Fixnum] Number of seconds to sleep before retrying an error
47
+ def error_sleep_time
48
+ return @error_sleep_time unless @error_sleep_time.nil?
49
+ @error_sleep_time = if options[:error_sleep_time].nil?
50
+ 5
51
+ else
52
+ options[:error_sleep_time]
53
+ end
54
+ end
55
+
56
+ # @return [Fixnum] Number of seconds to sleep after each task
57
+ def post_task_sleep_time
58
+ return @post_task_sleep_time unless @post_task_sleep_time.nil?
59
+ @post_task_sleep_time = if options[:post_task_sleep_time].nil?
60
+ 1
61
+ else
62
+ options[:post_task_sleep_time]
63
+ end
64
+ end
65
+
66
+ # Start the service
67
+ # @return [nil]
68
+ def start!
69
+ wait
70
+
71
+ loop do # Loop on tasks
72
+ logger.warn 'Tasks list is empty' if tasks.empty?
73
+ tasks.each do |task|
74
+ run_task(task)
75
+ sleep post_task_sleep_time
76
+ end
77
+
78
+ sleep loop_sleep_time
79
+ end
80
+
81
+ rescue StandardError => e
82
+ # Don't exit the process if initialization fails.
83
+ logger.error(e)
84
+
85
+ sleep error_sleep_time
86
+ retry
87
+ end
88
+
89
+ private
90
+
91
+ # @private
92
+ # @param [Array] task task to parse
93
+ # @return [Array<String, String, Array>] task parsed in parts: Class, method, and arguments
94
+ def parse_task(task)
95
+ raise ArgumentError, 'Not enough elements in the Array' if task.length < 2
96
+ out = {}
97
+ out[:instance] = task[0]
98
+
99
+ out[:class_name] = if out[:instance].class.to_s == 'Class'
100
+ out[:instance].name.to_s
101
+ else
102
+ out[:instance].class.to_s
103
+ end
104
+
105
+ out[:method] = task[1]
106
+ out[:args] = task[2..-1].flatten
107
+ out
108
+ end
109
+
110
+ # @private
111
+ # @param [Array<String, String, Array>] task to run
112
+ # @return [String] output returned from task
113
+ def run_task(task)
114
+ parsed_task = parse_task(task)
115
+ instance = parsed_task[:instance]
116
+ class_name = parsed_task[:class_name]
117
+ method = parsed_task[:method]
118
+ args = parsed_task[:args]
119
+ log_line = "Running #{class_name}.#{method}"
120
+ log_line += "(#{args})" unless args.empty?
121
+ logger.debug log_line
122
+
123
+ out = if args.empty?
124
+ instance.send(method.to_sym)
125
+ else
126
+ instance.send(method.to_sym, args)
127
+ end
128
+ logger.debug "Got: #{out}"
129
+ out
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,17 @@
1
+ require 'logging'
2
+
3
+ module DaemonRunner
4
+ #
5
+ # Logging module
6
+ #
7
+ module Logger
8
+
9
+ def logger_name
10
+ STDOUT
11
+ end
12
+
13
+ def logger
14
+ @logger ||= ::Logging.logger(logger_name)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,79 @@
1
+ require 'mixlib/shellout'
2
+
3
+ module DaemonRunner
4
+ class ShellOut
5
+ attr_reader :runner, :stdout
6
+ attr_reader :command, :cwd, :timeout, :wait
7
+
8
+ # @param command [String] the command to run
9
+ # @param cwd [String] the working directory to run the command
10
+ # @param timeout [Fixnum] the command timeout
11
+ # @param wait [Boolean] wheather to wait for the command to finish
12
+ def initialize(command: nil, cwd: '/tmp', timeout: 15, wait: true)
13
+ @command = command
14
+ @cwd = cwd
15
+ @timeout = timeout
16
+ @wait = wait
17
+ end
18
+
19
+ # Run command
20
+ # @return [Mixlib::ShellOut, Fixnum] mixlib shellout client or a pid depending on the value of {#wait}
21
+ def run!
22
+ validate_command
23
+ if wait
24
+ run_and_wait
25
+ else
26
+ run_and_detach
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ # Run a command and wait for it to finish
33
+ # @return [Mixlib::ShellOut] client
34
+ def run_and_wait
35
+ validate_args
36
+ runner
37
+ @runner.run_command
38
+ @runner.error!
39
+ @stdout = @runner.stdout
40
+ @runner
41
+ end
42
+
43
+ # Run a command in a new process group, thus ignoring any furthur
44
+ # updates about the status of the process
45
+ # @return [Fixnum] process id
46
+ def run_and_detach
47
+ log_r, log_w = IO.pipe
48
+ Process.spawn(command, pgroup: true, err: :out, out: log_w)
49
+ log_r.close
50
+ log_w.close
51
+ end
52
+
53
+ # Validate command is defined before trying to start the command
54
+ # @ raise [ArgumentError] if any of the arguments are missing
55
+ def validate_command
56
+ if @command.nil? && !respond_to?(:command)
57
+ raise ArgumentError, 'Must pass a command or implement a command method'
58
+ end
59
+ end
60
+
61
+ # Validate arguments before trying to start the command
62
+ # @ raise [ArgumentError] if any of the arguments are missing
63
+ def validate_args
64
+ if @cwd.nil? && !respond_to?(:cwd)
65
+ raise ArgumentError, 'Must pass a cwd or implement a cwd method'
66
+ end
67
+
68
+ if @timeout.nil? && !respond_to?(:timeout)
69
+ raise ArgumentError, 'Must pass a timeout or implement a timeout method'
70
+ end
71
+ end
72
+
73
+ # Setup a new Mixlib::ShellOut client runner
74
+ # @return [Mixlib::ShellOut] client
75
+ def runner
76
+ @runner ||= Mixlib::ShellOut.new(command, :cwd => cwd, :timeout => timeout)
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,3 @@
1
+ module DaemonRunner
2
+ VERSION = IO.read(File.expand_path('../../../VERSION', __FILE__)) rescue '0.0.1'
3
+ end
@@ -0,0 +1,4 @@
1
+ require_relative 'daemon_runner/version'
2
+ require_relative 'daemon_runner/logger'
3
+ require_relative 'daemon_runner/client'
4
+ require_relative 'daemon_runner/shell_out'
metadata ADDED
@@ -0,0 +1,146 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: daemon_runner
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.2
5
+ platform: ruby
6
+ authors:
7
+ - Andrew Thompson
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-10-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: logging
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mixlib-shellout
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.12'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.12'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '5.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '5.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: yard
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.8.7
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.8.7
97
+ description:
98
+ email:
99
+ - Andrew_Thompson@rapid7.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - ".travis.yml"
106
+ - CODE_OF_CONDUCT.md
107
+ - Gemfile
108
+ - LICENSE.txt
109
+ - README.md
110
+ - Rakefile
111
+ - Thorfile
112
+ - bin/console
113
+ - bin/setup
114
+ - daemon_runner.gemspec
115
+ - examples/example1.rb
116
+ - lib/daemon_runner.rb
117
+ - lib/daemon_runner/client.rb
118
+ - lib/daemon_runner/logger.rb
119
+ - lib/daemon_runner/shell_out.rb
120
+ - lib/daemon_runner/version.rb
121
+ homepage: https://github.com/rapid7/daemon_runner/
122
+ licenses:
123
+ - MIT
124
+ metadata: {}
125
+ post_install_message:
126
+ rdoc_options: []
127
+ require_paths:
128
+ - lib
129
+ required_ruby_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ requirements: []
140
+ rubyforge_project:
141
+ rubygems_version: 2.4.3
142
+ signing_key:
143
+ specification_version: 4
144
+ summary: Small library to make writing long running services easy
145
+ test_files: []
146
+ has_rdoc: