Class: YleTf::System
- Inherits:
-
Object
- Object
- YleTf::System
- Defined in:
- lib/yle_tf/system.rb,
lib/yle_tf/system/io_handlers.rb,
lib/yle_tf/system/output_logger.rb,
lib/yle_tf/system/tf_hook_output_logger.rb
Overview
Helpers to execute system commands with error handling
Defined Under Namespace
Classes: IOHandlers, OutputLogger, TfHookOutputLogger
Constant Summary collapse
- ExecuteError =
Class.new(YleTf::Error)
- DEFAULT_ERROR_HANDLER =
->(_exit_code, error) { raise error }.freeze
- DEFAULT_IO_HANDLERS =
{ stdin: :dev_null, stdout: :info, stderr: :error }.freeze
Class Method Summary collapse
- .attach_input_handler(handler, io, progname) ⇒ Object
- .attach_output_handler(handler, io, progname) ⇒ Object
-
.cmd(*args, **opts) ⇒ Object
Executes the command and attaches IO streams.
- .cmd_string(args, env = nil) ⇒ Object
- .console_cmd(*args, **opts) ⇒ Object
- .error(handler, error_msg, exit_code = nil) ⇒ Object
- .handle_io(progname, handlers) ⇒ Object
- .read_cmd(*args, **opts) ⇒ Object
- .verify_exit_status(status, handler, cmd) ⇒ Object
Class Method Details
.attach_input_handler(handler, io, progname) ⇒ Object
74 75 76 77 |
# File 'lib/yle_tf/system.rb', line 74 def self.attach_input_handler(handler, io, progname) io_proc = IOHandlers.input_handler(handler) io_proc.call(io, progname) end |
.attach_output_handler(handler, io, progname) ⇒ Object
79 80 81 82 |
# File 'lib/yle_tf/system.rb', line 79 def self.attach_output_handler(handler, io, progname) io_proc = IOHandlers.output_handler(handler) io_proc.call(io, progname) end |
.cmd(*args, **opts) ⇒ Object
Executes the command and attaches IO streams
32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/yle_tf/system.rb', line 32 def self.cmd(*args, **opts) opts = DEFAULT_IO_HANDLERS.merge(opts) env = opts[:env] || {} progname = opts.fetch(:progname) { args.first } YleTf::Logger.debug { "Calling #{cmd_string(args, env)}" } status = Open3.popen3(env, *args, &handle_io(progname, opts)) verify_exit_status(status, opts[:error_handler], cmd_string(args)) rescue Interrupt, Errno::ENOENT => e error(opts[:error_handler], "Failed to execute #{cmd_string(args)}: #{e}") end |
.cmd_string(args, env = nil) ⇒ Object
51 52 53 |
# File 'lib/yle_tf/system.rb', line 51 def self.cmd_string(args, env = nil) "`#{args.shelljoin}`#{" with env '#{env}'" if env && !env.empty?}" end |
.console_cmd(*args, **opts) ⇒ Object
22 23 24 25 26 27 28 29 |
# File 'lib/yle_tf/system.rb', line 22 def self.console_cmd(*args, **opts) env = opts[:env] || {} YleTf::Logger.debug { "Calling #{cmd_string(args, env)}" } system(env, *args) verify_exit_status($CHILD_STATUS, opts[:error_handler], cmd_string(args)) end |
.error(handler, error_msg, exit_code = nil) ⇒ Object
91 92 93 94 95 96 |
# File 'lib/yle_tf/system.rb', line 91 def self.error(handler, error_msg, exit_code = nil) YleTf::Logger.debug(error_msg) handler ||= DEFAULT_ERROR_HANDLER handler.call(exit_code, ExecuteError.new(error_msg)) end |
.handle_io(progname, handlers) ⇒ Object
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/yle_tf/system.rb', line 55 def self.handle_io(progname, handlers) lambda do |stdin, stdout, stderr, wait_thr| in_thr = attach_input_handler(handlers[:stdin], stdin, progname) out_thr = [ attach_output_handler(handlers[:stdout], stdout, progname), attach_output_handler(handlers[:stderr], stderr, progname) ] # Wait for the process to exit wait_thr.value.tap do YleTf::Logger.debug("`#{progname}` exited, killing input handler thread") in_thr.kill if in_thr.is_a?(Thread) YleTf::Logger.debug('Waiting for output handler threads to stop') ThreadsWait.all_waits(out_thr) end end end |
.read_cmd(*args, **opts) ⇒ Object
45 46 47 48 49 |
# File 'lib/yle_tf/system.rb', line 45 def self.read_cmd(*args, **opts) buffer = StringIO.new cmd(*args, opts.merge(stdout: buffer)) buffer.string end |
.verify_exit_status(status, handler, cmd) ⇒ Object
84 85 86 87 88 89 |
# File 'lib/yle_tf/system.rb', line 84 def self.verify_exit_status(status, handler, cmd) status.success? || error(handler, "Failed to execute #{cmd} (#{status.exitstatus})", status.exitstatus) end |