baal 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9fd791002dfcce1998043d8c2933dfe4916f711f
4
+ data.tar.gz: 6eb46c2f1680ef7c4134452324139ad4589c4af1
5
+ SHA512:
6
+ metadata.gz: 9242ed3fc57795d76a102afa72f3cd3eeb2d859461efcdea523109d4e8461ea216baac53137aeea4c57ce0fe5d2878b1075bede930dd77ac7015770bd09586fb
7
+ data.tar.gz: e70d24a8b3af1051f6af9cab25058b131969bb6b3d97ed6662f7fc35bcd7b23085e246e779aae1b7fe83bc94e6b4cc0d1536e0c9adbcdbbca9f12a0298c251ca
@@ -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/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.0
5
+ before_install: gem install bundler -v 1.13.7
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in Baal.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Lukas Nimmo
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.
@@ -0,0 +1,117 @@
1
+ # Baal
2
+
3
+ Baal is a Ruby wrapper for start-stop-daemon that attempts to make your start-stop-daemon scripts easier to build and
4
+ read while still providing the same options you are used to. Baal, through start-stop-daemon, provides a myriad of ways
5
+ to start new daemon processes and check the status of and stop existing ones.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'baal'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install baal
22
+
23
+ ## Usage
24
+
25
+ The intention of Baal is to provide an easily-readable, step-by-step process of building start-stop-daemon scripts.
26
+
27
+ The wrapper provides all methods you are used to and attempts to alert you (with a nice red error) if it notices a mistake.
28
+
29
+ All building is centered around the Daemon object which can be accessed like so:
30
+
31
+ ```ruby
32
+ # Preferred
33
+ daemon = Baal.new
34
+
35
+ # Not preferred
36
+ daemon = Baal::Daemon.new
37
+ ```
38
+
39
+ Once you have your builder object, it is simply a matter of constructing the needed commands and options.
40
+
41
+ ```ruby
42
+ # Start a new process in the background
43
+ daemon.start
44
+ daemon.instance_of_exec('/abs/path/to/executable')
45
+ daemon.with_name('dave')
46
+ ```
47
+
48
+ Then execute what you have built
49
+
50
+ ```ruby
51
+ daemon.daemonize!
52
+ ```
53
+
54
+ You can even check the current status of what you are to execute
55
+
56
+ ```ruby
57
+ puts daemon.execution
58
+ ```
59
+
60
+ You can also clear the current contents of what you have built up
61
+
62
+ ```ruby
63
+ # Begin with start
64
+ daemon.start
65
+ daemon.start_as('/path/to/file')
66
+ daemon.pid_file('/path/to/pid_file')
67
+
68
+ # Something came up! Need to clear it...
69
+ daemon.clear_all!
70
+ ```
71
+
72
+
73
+ All of the methods that build up your start-stop-daemon script are chain-able
74
+
75
+ ```ruby
76
+ # Check the status of a process
77
+ daemon.status.with_pid(1234).daemonize!
78
+ ```
79
+
80
+ All options with dashes have been converted to underscores, ie.
81
+
82
+ ```ruby
83
+ # From
84
+ daemon.make-pidfile
85
+
86
+ # To
87
+ daemon.make_pidfile
88
+ ```
89
+
90
+ and there are many methods that have been written to be more Ruby-like, however, if you still prefer the original
91
+ command and option names (dashes are not allowed), those are available as well
92
+
93
+ ```ruby
94
+ # These are just options...
95
+ daemon.start.start_as('/p/a/t/h').pid_file('/p/a/t/h').change_to_user('dave')
96
+
97
+ # Original language
98
+ daemon.start.startas('/p/a/t/h').pidfile('/p/a/t/h').chuid('dave')
99
+
100
+ # No option for multi-word options with dashes
101
+ daemon.make-pidfile # No method
102
+ daemon.make_pidfile # As above
103
+ ```
104
+
105
+ The documentation in the library should be enough, but if it isn't, or you just don't like my writing style, then there
106
+ is the official [documention](https://manpages.debian.org/jessie/dpkg/start-stop-daemon.8.en.html) of start-stop-daemon.
107
+
108
+ ## Contributing
109
+
110
+ Bug reports and pull requests are welcome on GitHub at https://github.com/numbluk/baal.
111
+
112
+ ## License
113
+
114
+ Copyright (c) 2017 Lukas Nimmo.
115
+
116
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
117
+
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -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 'baal/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'baal'
8
+ spec.version = Baal::VERSION
9
+ spec.authors = ['Lukas Nimmo']
10
+ spec.email = ['Lukas.nimmo@gmail.com']
11
+
12
+ spec.summary = <<-HEREDOC
13
+ Baal is a Ruby wrapper for start-stop-daemon that attempts to make your start-stop-daemon scripts easier to build
14
+ and read while still providing the same options you are used to. Baal, through start-stop-daemon, provides a
15
+ myriad of ways to start new daemon processes and check the status of and stop existing ones.
16
+ HEREDOC
17
+ spec.homepage = 'https://github.com/numbluk/baal'
18
+ spec.license = 'MIT'
19
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
20
+ f.match(%r{^(test|spec|features)/})
21
+ end
22
+ spec.require_paths = ['lib']
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.13'
25
+ spec.add_development_dependency 'rake', '~> 10.0'
26
+ spec.add_development_dependency 'rspec', '~> 3.0'
27
+ spec.add_development_dependency 'pry', '~> 3.0'
28
+ end
@@ -0,0 +1,75 @@
1
+ require 'baal/version'
2
+ require 'baal/commands'
3
+ require 'baal/matching_options'
4
+ require 'baal/optional_options'
5
+
6
+ # The Baal module is the namespace containing all interaction with the Baal gem.
7
+ # Very little is actually done directly on the Baal module. The primary
8
+ # interaction with the Baal module itself will be the instantiation of a Daemon
9
+ # object with the convenience method #new:
10
+ #
11
+ # 1. Baal.new
12
+ #
13
+ # vs
14
+ #
15
+ # 2. Baal::Daemon.new
16
+ #
17
+ module Baal
18
+ def self.new
19
+ Daemon.new
20
+ end
21
+
22
+ # Daemon is a builder object that allows you construct and access, at any
23
+ # time, the start-stop-daemon string that will be executed. All building
24
+ # of the start-stop-daemon string will be through this object.
25
+ #
26
+ # A note should be made that all methods which build the start-stop-daemon
27
+ # script return the Daemon instance for the intention of method chaining
28
+ # where possible so as to read like written English.
29
+ #
30
+ class Daemon
31
+ include Baal::Commands
32
+ include Baal::MatchingOptions
33
+ include Baal::OptionalOptions
34
+
35
+ PROGRAM_NAME = 'start-stop-daemon'.freeze
36
+
37
+ def initialize
38
+ @execution = [PROGRAM_NAME]
39
+ @testing = false
40
+ end
41
+
42
+ # TODO: Add method to remove a single command or option
43
+
44
+ # Clears @execution and starts over with only the PROGRAM_NAME
45
+ #
46
+ def clear_all!
47
+ @execution.clear
48
+ @execution = [PROGRAM_NAME]
49
+ self
50
+ end
51
+
52
+ # @return [String] the built up, whitespace-formatted start-stop-daemon
53
+ # string to be executed
54
+ #
55
+ def execution
56
+ @execution.join(' ').strip
57
+ end
58
+
59
+ # Executes the built up start-stop-daemon string and throws an error if
60
+ # there isn't at least one command and at least one matching option.
61
+ #
62
+ # @return [true, false, nil]
63
+ # true: if command was successful (exit status 0)
64
+ # false: if command was unsuccessful (exit status non-zero)
65
+ # nil: if command execution fails
66
+ #
67
+ # TODO: remove usage of system
68
+ #
69
+ def daemonize!
70
+ at_least_one_command?
71
+ at_least_one_matching_option?
72
+ system @execution
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,105 @@
1
+ module Baal
2
+
3
+ # Commands contains all of the necessary methods to perform all of the
4
+ # possible start-stop-daemon commands.
5
+ #
6
+ module Commands
7
+ # Hash constant containing all possible commands.
8
+ COMMANDS = {
9
+ start: '--start',
10
+ stop: '--stop',
11
+ status: '--status',
12
+ help: '--help',
13
+ version: '--version'
14
+ }.freeze
15
+
16
+ # Command that attempts to start a process specified through an option.
17
+ # Initially, it will check whether or not a specified process (through an
18
+ # option) exits. Then it will do one of the following:
19
+ #
20
+ # 1. If a specified process already exists then it will do nothing and exit
21
+ # with an error status of 1 (or 0 if oknodo option is specified).
22
+ #
23
+ # 2. If a matching process does not exist, then it will start an instance of
24
+ # one using one of the following options:
25
+ #
26
+ # I. exec: an absolute pathname to an executable
27
+ #
28
+ # II. start_as: a path_name to a process
29
+ #
30
+ def start
31
+ @execution.insert 1, COMMANDS[:start]
32
+ include_multiple_commands?
33
+ self
34
+ end
35
+
36
+ # Command that attempts to stop a specified process. Initially, it will
37
+ # check whether or not a specified process (through an option) exists. Then
38
+ # it will do one the following:
39
+ #
40
+ # 1. If a process DOES exist it will send it a signal specified by the
41
+ # option:
42
+ #
43
+ # signal: the signal to be sent to processes being stopped. If none
44
+ # specified then it defaults to TERM
45
+ #
46
+ # 2. If a process DOES NOT exist it it will exit with an error status of 1
47
+ # (or 1 if the oknodo option is specified).
48
+ #
49
+ # 3. If the following option is specified then start-stop-daemon will check
50
+ # that the process(es) have finished:
51
+ #
52
+ # retry: option to check whether or not process(es) finish
53
+ #
54
+ def stop
55
+ @execution.insert 1, COMMANDS[:stop]
56
+ include_multiple_commands?
57
+ self
58
+ end
59
+ alias kill stop
60
+
61
+ # Command that checks for whether or not a process specified by an option
62
+ # exists. An exit code is returned accord to the LSB Init Script Actions.
63
+ # TODO: provide better error messages based on LSB.
64
+ def status
65
+ @execution.insert 1, COMMANDS[:status]
66
+ include_multiple_commands?
67
+ self
68
+ end
69
+
70
+ # Command that shows cli help information and then exits.
71
+ def help
72
+ @execution.insert 1, COMMANDS[:help]
73
+ include_multiple_commands?
74
+ self
75
+ end
76
+
77
+ # Command that shows your program version of start-stop-daemon and then
78
+ # exits.
79
+ def version
80
+ @execution.insert 1, COMMANDS[:version]
81
+ include_multiple_commands?
82
+ self
83
+ end
84
+
85
+ private
86
+
87
+ # TODO: Added better errors?
88
+ def include_multiple_commands?
89
+ command_count = 0
90
+ COMMANDS.each do |_, command|
91
+ command_count += 1 if execution.include? command
92
+
93
+ raise ArgumentError, 'You can only have one command.' if command_count > 1
94
+ end
95
+ end
96
+
97
+ def at_least_one_command?
98
+ COMMANDS.each do |_, command|
99
+ return if execution.include? command
100
+ end
101
+
102
+ raise ArgumentError, 'You must have at least one command.'
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,125 @@
1
+ module Baal
2
+
3
+ # MatchingOptions is a container for all methods relating to adding Matching
4
+ # Options to your start-stop-daemon script. Matching Options are used to
5
+ # target existing processes or identify new ones to be acted upon using a
6
+ # Command.
7
+ #
8
+ # At least one Matching Option is required to execute a start-stop-daemon
9
+ # script.
10
+ #
11
+ module MatchingOptions
12
+ # All possible Matching Options
13
+ MATCHING_OPTIONS = {
14
+ pid: '--pid',
15
+ ppid: '--ppid',
16
+ pid_file: '--pidfile',
17
+ exec: '--exec',
18
+ name: '--name',
19
+ user: '--user'
20
+ }.freeze
21
+
22
+ # Checks for a process with a specified process id.
23
+ #
24
+ # @param id [String, Integer] the process id to be targeted. Must be
25
+ # greater than 0.
26
+ # TODO: Add error to catch for 0 or less.
27
+ #
28
+ def pid(id)
29
+ @execution.push "#{MATCHING_OPTIONS[:pid]}=#{id}"
30
+ self
31
+ end
32
+ alias with_pid pid
33
+
34
+ # Checks for a process with a specified parent process id.
35
+ #
36
+ # @param id [String, Integer] the parent process id to be targeted. Must be
37
+ # greater than 0.
38
+ # TODO: Add error to catch for 0 or less.
39
+ #
40
+ def ppid(id)
41
+ @execution.push "#{MATCHING_OPTIONS[:ppid]}=#{id}"
42
+ self
43
+ end
44
+ alias with_ppid ppid
45
+
46
+ # Checks whether or not a process has created the pid_file.
47
+ #
48
+ # @param path [String] the path to the pid_file to be checked.
49
+ #
50
+ # WARNING: if used alone AND the old process terminated without removing
51
+ # the pid_file specified by @path, then this might cause
52
+ # unintended consequences.
53
+ #
54
+ def pid_file(path)
55
+ @execution.push "#{MATCHING_OPTIONS[:pid_file]}=#{path}"
56
+ self
57
+ end
58
+ alias with_pid_file pid_file
59
+ alias pidfile pid_file
60
+
61
+ # Used with Commands#start.
62
+ #
63
+ # Checks for processes that are instances of the executable specified by
64
+ # abs_path_to_exec.
65
+ #
66
+ # @param abs_path_to_exec [String] the absolute path to the executable
67
+ #
68
+ # NOTE: might not work if used with interpreted scripts, as the executable
69
+ # will point to the interpreter.
70
+ #
71
+ # WARNING: take into account processes running from inside a chroot will
72
+ # also be identified, so other restrictions might be needed to
73
+ # avoid this.
74
+ #
75
+ def exec(abs_path_to_exec)
76
+ @execution.push "#{MATCHING_OPTIONS[:exec]}=#{abs_path_to_exec}"
77
+ self
78
+ end
79
+ alias instance_of_exec exec
80
+
81
+ # Checks for processes with the name specified by @process_name
82
+ #
83
+ # @param process_name [String] name of process
84
+ #
85
+ # NOTE: the name of the process is often the filename, but be wary that it
86
+ # could have been changed by process itself
87
+ #
88
+ # NOTE: for most systems the process name is retrieved from the process
89
+ # comm name from the kernel. This is typically a shortened version
90
+ # of the expected process name that is 15 characters long.
91
+ #
92
+ def name(process_name)
93
+ @execution.push "#{MATCHING_OPTIONS[:name]}=#{process_name}"
94
+ self
95
+ end
96
+ alias with_name name
97
+
98
+ # Checks for processes owned by the user specified by a username or uid.
99
+ #
100
+ # @param username_or_uid [String, Symbol, Integer]
101
+ #
102
+ # WARNING: Using this matching option ALONE will cause all matching
103
+ # processes to be acted upon.
104
+ #
105
+ def user(username_or_uid)
106
+ @execution.push "#{MATCHING_OPTIONS[:user]}=#{username_or_uid}"
107
+ self
108
+ end
109
+ alias username user
110
+ alias uid user
111
+ alias owned_by_user user
112
+ alias owned_by_username user
113
+ alias owned_by_uid user
114
+
115
+ private
116
+
117
+ def at_least_one_matching_option?
118
+ MATCHING_OPTIONS.each do |_, option|
119
+ return if execution.include? option
120
+ end
121
+
122
+ raise ArgumentError, 'You must have at least one matching option.'
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,297 @@
1
+ module Baal
2
+
3
+ # Optional Options is a container for all methods relating to options that
4
+ # can be added to your start-stop-daemon script, but are not required
5
+ #
6
+ module OptionalOptions
7
+ class InvalidPolicyError < ArgumentError; end
8
+ class InvalidScheduleClassError < ArgumentError; end
9
+
10
+ # All optional options
11
+ OPTIONAL_OPTS = {
12
+ group: '--group',
13
+ signal: '--signal',
14
+ retry: '--retry',
15
+ start_as: '--startas',
16
+ test: '--test',
17
+ oknodo: '--oknodo',
18
+ quiet: '--quiet',
19
+ chuid: '--chuid',
20
+ chroot: '--chroot',
21
+ chdir: '--chdir',
22
+ background: '--background',
23
+ no_close: '--no-close',
24
+ nice_level: '--nicelevel',
25
+ proc_sched: '--procsched',
26
+ io_sched: '--iosched',
27
+ umask: '--umask',
28
+ make_pid_file: '--make-pidfile',
29
+ remove_pid_file: '--remove-pidfile',
30
+ verbose: '--verbose'
31
+ }.freeze
32
+
33
+ # Change to a group or group id before starting the process
34
+ #
35
+ # @param group_name_or_gid [String, Integer, Symbol] the group name or group
36
+ # id to be changed to
37
+ #
38
+ def group(group_name_or_gid)
39
+ @execution.push "#{OPTIONAL_OPTS[:group]}=#{group_name_or_gid}"
40
+ self
41
+ end
42
+ alias group_name group
43
+ alias gid group
44
+ alias change_to_group group
45
+ alias change_to_group_name group
46
+ alias change_to_gid group
47
+
48
+ # Used with Commands#stop. Specifies the signal to send to the
49
+ # processes attempting to be stopped.
50
+ #
51
+ # @param signal[String, Symbol] the signal to send
52
+ #
53
+ def signal(signal = 'TERM')
54
+ @execution.push "#{OPTIONAL_OPTS[:signal]}=#{signal}"
55
+ self
56
+ end
57
+ alias with_signal signal
58
+
59
+ # Used with Commands#stop. Specifies that start-stop-daemon is to check
60
+ # whether the process(es) do finish. It will check repeatedly whether any
61
+ # matching processes are running, until none are. If the processes do not
62
+ # exit it will then take futher action as defined by the schedule.
63
+ #
64
+ # @param timeout_or_schedule [String, Integer]
65
+ # If a timeout (in seconds) is specified, then the following schedule is
66
+ # used:
67
+ #
68
+ # signal/timeout/KILL/timeout, where signal is specified with
69
+ # OptionalOptions#signal.
70
+ #
71
+ # To specify a schedule: a schedule is a list of at least two items
72
+ # separated by slashes; each item may be any of the following:
73
+ #
74
+ # 1. signal number or signal name, which means to send that signal
75
+ # 2. timeout, which means to wait that many seconds for processes to
76
+ # exit
77
+ # 3. forever, which means to repeat the rest of the schedule forever if
78
+ # necessary
79
+ #
80
+ # If the end of the schedule is reached and forever is not specified, then
81
+ # start-stop-daemon exits with the error status of 2.
82
+ #
83
+ # WARNING: If a schedule is specified, then any signal specified with
84
+ # OptionalOptions#signal is ignored.
85
+ #
86
+ # TODO: Add better arguments for constructing a schedule
87
+ #
88
+ def retry(timeout_or_schedule)
89
+ @execution.push "#{OPTIONAL_OPTS[:retry]}=#{timeout_or_schedule}"
90
+ self
91
+ end
92
+ alias retry_timeout retry
93
+ alias retry_schedule retry
94
+
95
+ # Used with Commands#start.
96
+ #
97
+ # Starts the process at the specified path. If not added as an option to
98
+ # Commands#start, the path will default to the one provided to
99
+ # MatchhingOptions#exec.
100
+ #
101
+ # @param path [String] path to process to attempt to start as
102
+ #
103
+ def start_as(path)
104
+ @execution.push "#{OPTIONAL_OPTS[:start_as]}=#{path}"
105
+ self
106
+ end
107
+ alias startas start_as
108
+
109
+ # Print actions that would be taken and set an appropriate return value,
110
+ # but take no action
111
+ #
112
+ def test
113
+ @execution.push OPTIONAL_OPTS[:test]
114
+ self
115
+ end
116
+
117
+ # Return an exit status of 0 instead of 1 if no actions are, or would not
118
+ # be, taken
119
+ #
120
+ def oknodo
121
+ @execution.push OPTIONAL_OPTS[:oknodo]
122
+ self
123
+ end
124
+
125
+ # Do not print informational messages; only display error messages
126
+ #
127
+ def quiet
128
+ @execution.push OPTIONAL_OPTS[:quiet]
129
+ self
130
+ end
131
+
132
+ # Change to the specified username or uid before starting the process.
133
+ #
134
+ # @param username_or_uid [String, Integer, Symbol] username or uid to change
135
+ # to.
136
+ # @param group_or_gid [String, Integer, Symbol] group name or group id to
137
+ # change to.
138
+ #
139
+ # NOTE: If a user is specified without a group, the primary GID for that
140
+ # user is used.
141
+ #
142
+ # NOTE: Primary and supplemental groups are set as well, even if the
143
+ # OptionalOptions#group option is not specified. The
144
+ # OptionalOptions#group option is only groups that the user isn't
145
+ # normally a member of.
146
+ #
147
+ def chuid(username_or_uid, group_or_gid = nil)
148
+ group_or_gid = group_or_gid.nil? ? '' : ":#{group_or_gid}"
149
+ @execution.push "#{OPTIONAL_OPTS[:chuid]}=#{username_or_uid}#{group_or_gid}"
150
+ self
151
+ end
152
+ alias change_to_user chuid
153
+ alias change_to_uid chuid
154
+
155
+ # Change directories and chroot to root before starting the process.
156
+ #
157
+ # @param new_root_dir [String] path to chroot to
158
+ #
159
+ # NOTE: the pid_file is written after the chroot
160
+ #
161
+ def chroot(new_root_dir)
162
+ @execution.push "#{OPTIONAL_OPTS[:chroot]}=#{new_root_dir}"
163
+ self
164
+ end
165
+
166
+ # Change directories to @path before starting the process.
167
+ #
168
+ # Chdir is done AFTER the chroot if the OptionalOptions#chroot option is
169
+ # set. When no OptionalOptions#chroot is set, start-stop-daemon will
170
+ # chdir to the root directory before starting the process.
171
+ #
172
+ def chdir(path)
173
+ @execution.push "#{OPTIONAL_OPTS[:chdir]}=#{path}"
174
+ self
175
+ end
176
+
177
+ def background
178
+ @execution.push OPTIONAL_OPTS[:background]
179
+ self
180
+ end
181
+ alias in_background background
182
+
183
+ # Only relevant when using --background
184
+ def no_close
185
+ @execution.push OPTIONAL_OPTS[:no_close]
186
+ self
187
+ end
188
+
189
+ # Alters the priority of the process before starting it.
190
+ #
191
+ # @param incr [String, Integer] amount to alter the priority level, can be
192
+ # positive or negative
193
+ #
194
+ def nice_level(incr)
195
+ @execution.push "#{OPTIONAL_OPTS[:nice_level]}=#{incr}"
196
+ self
197
+ end
198
+ alias incr_nice_level nice_level
199
+
200
+ VALID_POLICIES = %w(other fifo rr).freeze
201
+
202
+ # Alters the process scheduler class and priority of the process before
203
+ # starting it.
204
+ #
205
+ # Default priority is 0 when executed.
206
+ #
207
+ # @param policy [String, Symbol] the process scheduler policy.
208
+ # Supported values: :other, :fifo, :rr
209
+ # @param priority [String, Integer] the process priority
210
+ def proc_sched(policy, priority = nil)
211
+ unless VALID_POLICIES.include? policy.to_s
212
+ raise InvalidPolicyError, 'Invalid policy. Expected: other, fifo, rr'
213
+ end
214
+
215
+ priority = priority.nil? ? ' ' : ":#{priority}"
216
+ @execution.push "#{OPTIONAL_OPTS[:proc_sched]}=#{policy}#{priority}"
217
+ self
218
+ end
219
+ alias procshed proc_sched
220
+ alias process_schedule proc_sched
221
+
222
+ VALID_SCHEDULE_CLASSES = %w(idle best-effort real-time).freeze
223
+
224
+ # Alters the io IO scheduler class and priority of the process before
225
+ # starting it.
226
+ #
227
+ # Default priority is 4, unless the sched_class is :idle, then it's 7.
228
+ #
229
+ # @param sched_class [String, Symbol] the io scheduler class.
230
+ # Supported values: :idle, :best-effort, :real-time
231
+ # @param priority [String, Integer] the process priority.
232
+ #
233
+ def io_sched(sched_class, priority = nil)
234
+ puts sched_class
235
+ unless VALID_SCHEDULE_CLASSES.include? sched_class.to_s
236
+ raise InvalidScheduleClassError,
237
+ 'Invalid schedule class. Expected: idle, best-effort, real-time'
238
+ end
239
+
240
+ priority = priority.nil? ? ' ' : ":#{priority}"
241
+ @execution.push "#{OPTIONAL_OPTS[:io_sched]}=#{sched_class}#{priority}"
242
+ self
243
+ end
244
+ alias iosched io_sched
245
+ alias io_schedule io_sched
246
+
247
+ # Sets the umask of the process before starting it
248
+ #
249
+ # @param mask [String, Integer] umask value
250
+ def umask(mask)
251
+ @execution.push "#{OPTIONAL_OPTS[:umask]}=#{mask}"
252
+ self
253
+ end
254
+
255
+ # Used when starting a program that does not create its own pid file.
256
+ #
257
+ # Used together with the file specified by the MatchingOptions#pidfile
258
+ # option.
259
+ #
260
+ # This will place the pid into the file specified by the
261
+ # MatchingOptions#pidfile option, just before executing the process.
262
+ #
263
+ # NOTE: The file will only be removed if the OptionalOptions#remove_pid_file
264
+ # option is used.
265
+ #
266
+ # WARNING: Will not work in all cases, such as when the program being
267
+ # executed forks from its main process. Because of this, it is
268
+ # usually only useful when combined with the
269
+ # OptionalOptions#background option.
270
+ #
271
+ def make_pid_file
272
+ @execution.push OPTIONAL_OPTS[:make_pid_file]
273
+ self
274
+ end
275
+ alias make_pidfile make_pid_file
276
+
277
+ # Used when stopping a program that will NOT remove its own pid file.
278
+ #
279
+ # Used together with the file specified by the MatchingOptions#pidfile
280
+ # option.
281
+ #
282
+ # This will remove the file specified by the MatchingOptions#pidfile
283
+ # option.
284
+ #
285
+ def remove_pid_file
286
+ @execution.push OPTIONAL_OPTS[:remove_pid_file]
287
+ self
288
+ end
289
+ alias remove_pidfile remove_pid_file
290
+
291
+ # Print verbose informational messages when executing the script
292
+ def verbose
293
+ @execution.push OPTIONAL_OPTS[:verbose]
294
+ self
295
+ end
296
+ end
297
+ end
@@ -0,0 +1,3 @@
1
+ module Baal
2
+ VERSION = '0.1.0'
3
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: baal
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Lukas Nimmo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-05-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.13'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.13'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ description:
70
+ email:
71
+ - Lukas.nimmo@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".rspec"
78
+ - ".travis.yml"
79
+ - Gemfile
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - baal.gemspec
84
+ - lib/baal.rb
85
+ - lib/baal/commands.rb
86
+ - lib/baal/matching_options.rb
87
+ - lib/baal/optional_options.rb
88
+ - lib/baal/version.rb
89
+ homepage: https://github.com/numbluk/baal
90
+ licenses:
91
+ - MIT
92
+ metadata: {}
93
+ post_install_message:
94
+ rdoc_options: []
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ requirements: []
108
+ rubyforge_project:
109
+ rubygems_version: 2.6.8
110
+ signing_key:
111
+ specification_version: 4
112
+ summary: Baal is a Ruby wrapper for start-stop-daemon that attempts to make your start-stop-daemon
113
+ scripts easier to build and read while still providing the same options you are
114
+ used to. Baal, through start-stop-daemon, provides a myriad of ways to start new
115
+ daemon processes and check the status of and stop existing ones.
116
+ test_files: []