Class: Sys::Sv::SvDir
- Inherits:
-
Object
- Object
- Sys::Sv::SvDir
- Defined in:
- lib/sys/sv/svdir.rb
Overview
The SvDir class encapsulates service directories, a scheme for reliably controlling daemon processes (services) introduced in Dan Bernstein’s daemontools software.
Each service is monitored by a supervisor, which is responsible for starting, stopping, restarting and generally controlling the service. Examples of such supervisors include supervise from the daemontools package and runsv from Gerit Pape’s compatible runit software.
Most SvDir methods will raise Errno:: exceptions (each a subclass of SystemCallException) if the underlying filesystem representation of the service directory is not as expected. For example, EACCESS or ENOENT may be raised if the supervisor’s status directory or state files are missing or unreadable. Additionally, ENXIO is raised if the supervisor itself isn’t running.
Constant Summary collapse
- VERSION =
'0.2.1'.freeze
Instance Attribute Summary collapse
-
#path ⇒ Object
readonly
Returns the value of attribute path.
Instance Method Summary collapse
-
#down? ⇒ Boolean
trueif the service is not running. -
#downtime ⇒ Object
Returns the number of seconds the service has been down, as a float, or
nilif the service is in fact running. -
#initialize(path) ⇒ SvDir
constructor
Create a new SvDir corresponding to the service directory
path. -
#log ⇒ Object
Return a SvDir object representing this service’s attendant
logservice, otherwisenil. -
#normally_down? ⇒ Boolean
Returns
trueif a supervisor will not start the service without explicit instruction to do so. -
#normally_up? ⇒ Boolean
Returns
trueif the service is typically running, i.e., if the service directory lacks a./downfile. -
#paused? ⇒ Boolean
Returns
trueif the service is paused, that is, has received a SIGSTOP. -
#pid ⇒ Object
Return the pid of the service running under this SvDir, or
nilif no service is running. -
#signal(cmd) ⇒ Object
Send a signal to the service via its supervisor.
-
#svok? ⇒ Boolean
Returns
trueif the service directory’s supervisor is running. -
#up? ⇒ Boolean
trueif the service is running, even if paused. -
#uptime ⇒ Object
Returns the number of seconds the service has been running, as a float, or
nilif the service is not running. -
#want_down? ⇒ Boolean
Returns
trueif the service’s supervisor has been instructed to bring the service down. -
#want_up? ⇒ Boolean
Returns
trueif the service’s supervisor has been instructed to bring the service up.
Constructor Details
#initialize(path) ⇒ SvDir
Create a new SvDir corresponding to the service directory path.
65 66 67 |
# File 'lib/sys/sv/svdir.rb', line 65 def initialize(path) @path = path end |
Instance Attribute Details
#path ⇒ Object (readonly)
Returns the value of attribute path.
37 38 39 |
# File 'lib/sys/sv/svdir.rb', line 37 def path @path end |
Instance Method Details
#down? ⇒ Boolean
true if the service is not running.
171 172 173 |
# File 'lib/sys/sv/svdir.rb', line 171 def down? pid.nil? end |
#downtime ⇒ Object
Returns the number of seconds the service has been down, as a float, or nil if the service is in fact running.
153 154 155 |
# File 'lib/sys/sv/svdir.rb', line 153 def downtime return elapsed() if down? end |
#log ⇒ Object
Return a SvDir object representing this service’s attendant log service, otherwise nil.
Typical SvDir daemons contain a “nested” SvDir responsible for logging the stdout of the base service. E.g.:
/path/to/services/webserver # <--- base service
/path/to/services/webserver/log # <--- logger
The log service is supervised and controllable just like the base service. (Also, the pipe connecting the base service’s stdout to the log service’s stdin is maintained by a common parent, so that restarting either service won’t lose data in the pipe.)
Example:
my_serv = Sys::Sv::SvDir.new("path/to/my_serv")
my_serv.signal(:down)
if logger = my_serv.log
logger.signal(:down)
end
114 115 116 117 |
# File 'lib/sys/sv/svdir.rb', line 114 def log fn = File.join(@path, 'log') return self.class.new(fn) if File.directory? fn end |
#normally_down? ⇒ Boolean
Returns true if a supervisor will not start the service without explicit instruction to do so.
Note that this method functions whether or not the service is running, and whether or not a supervisor is running.
See also the #want_down? method documentation.
147 148 149 |
# File 'lib/sys/sv/svdir.rb', line 147 def normally_down? File.exist? File.join(@path, 'down') end |
#normally_up? ⇒ Boolean
Returns true if the service is typically running, i.e., if the service directory lacks a ./down file.
Note that this method functions whether or not the service is running, and whether or not a supervisor is running.
See also the #want_up? method documentation.
136 137 138 |
# File 'lib/sys/sv/svdir.rb', line 136 def normally_up? ! normally_down? end |
#paused? ⇒ Boolean
Returns true if the service is paused, that is, has received a SIGSTOP.
182 183 184 |
# File 'lib/sys/sv/svdir.rb', line 182 def paused? statusbytes.pauseflag != 0 end |
#pid ⇒ Object
Return the pid of the service running under this SvDir, or nil if no service is running.
165 166 167 168 |
# File 'lib/sys/sv/svdir.rb', line 165 def pid p = statusbytes.pid return p == 0 ? nil : p end |
#signal(cmd) ⇒ Object
Send a signal to the service via its supervisor.
:up-
start the service if not running, restarting as necessary.
:down-
stop the service, issuing a TERM followed by a CONT. Do not restart it if it stops.
:once-
start the service if not running, but do not restart it if it stops.
:pauseor:STOP-
issue a STOP signal. See also #paused?.
:continueor:CONT-
issue a CONT signal. See also #paused?.
:hangupor:HUP-
issue a HUP signal.
:alarmor:ALRM-
issue an ALRM signal.
:interruptorINT-
issue an INT signal.
:terminateorTERM-
issue a TERM signal.
:killorKILL-
issue a KILL signal.
:exit-
tell the supervisor to exit as soon as the service stops.
:user1or:USR1-
issue a USR1 signal. Not supported by all supervisors
:user2or:USR2-
issue a USR2 signal. Not supported by all supervisors
84 85 86 87 88 89 90 91 |
# File 'lib/sys/sv/svdir.rb', line 84 def signal(cmd) unless byte = Commands[cmd.to_sym] raise ArgumentError.new("unsupported SvDir signal `#{cmd}'") end Util::open_write(svfn('control')) do |f| f.syswrite(byte) end end |
#svok? ⇒ Boolean
Returns true if the service directory’s supervisor is running.
To determine whether the service itself is running, see #up?, #down? and #paused?
123 124 125 126 127 |
# File 'lib/sys/sv/svdir.rb', line 123 def svok? Util::open_write(svfn('ok')) { true } rescue Errno::ENXIO, Errno::ENOENT false # No pipe reader, or no pipe! end |
#up? ⇒ Boolean
true if the service is running, even if paused.
176 177 178 |
# File 'lib/sys/sv/svdir.rb', line 176 def up? !down? end |
#uptime ⇒ Object
Returns the number of seconds the service has been running, as a float, or nil if the service is not running.
159 160 161 |
# File 'lib/sys/sv/svdir.rb', line 159 def uptime return elapsed() if up? end |
#want_down? ⇒ Boolean
Returns true if the service’s supervisor has been instructed to bring the service down.
188 189 190 |
# File 'lib/sys/sv/svdir.rb', line 188 def want_down? statusbytes.wantflag == 'd' end |
#want_up? ⇒ Boolean
Returns true if the service’s supervisor has been instructed to bring the service up.
194 195 196 |
# File 'lib/sys/sv/svdir.rb', line 194 def want_up? statusbytes.wantflag == 'u' end |