class YleTf::System
Helpers
to execute system commands with error handling
Constants
- DEFAULT_ERROR_HANDLER
- DEFAULT_IO_HANDLERS
- ExecuteError
Public Class Methods
attach_input_handler(handler, io, progname)
click to toggle source
# File lib/yle_tf/system.rb, line 77 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)
click to toggle source
# File lib/yle_tf/system.rb, line 82 def self.attach_output_handler(handler, io, progname) io_proc = IOHandlers.output_handler(handler) io_proc.call(io, progname) end
cmd(*args, **opts)
click to toggle source
Executes the command and attaches IO streams
# File lib/yle_tf/system.rb, line 35 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)
click to toggle source
# File lib/yle_tf/system.rb, line 54 def self.cmd_string(args, env = nil) "`#{args.shelljoin}`#{" with env '#{env}'" if env && !env.empty?}" end
console_cmd(*args, **opts)
click to toggle source
# File lib/yle_tf/system.rb, line 25 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)
click to toggle source
# File lib/yle_tf/system.rb, line 94 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)
click to toggle source
# File lib/yle_tf/system.rb, line 58 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)
click to toggle source
# File lib/yle_tf/system.rb, line 48 def self.read_cmd(*args, **opts) buffer = StringIO.new cmd(*args, **opts.merge(stdout: buffer)) buffer.string end
verify_exit_status(status, handler, cmd)
click to toggle source
# File lib/yle_tf/system.rb, line 87 def self.verify_exit_status(status, handler, cmd) status.success? || error(handler, "Failed to execute #{cmd} (#{status.exitstatus})", status.exitstatus) end