module Kernel

def qbash(cmd, stdin: '', env: {}, log: Loog::NULL, accept: [0], both: false, timeout: nil)

Returns:
  • (String) - Everything that was printed to the +stdout+ by the command

Parameters:
  • timeout (Integer) -- If it's set to non-NIL, the execution will fail after this number of seconds
  • both (Boolean) -- If set to TRUE, the function returns an array +(stdout, code)+
  • accept (Array) -- List of accepted exit codes (accepts all if the list is empty)
  • log (Loog|IO) -- Logging facility with +.debug()+ method (or +$stdout+)
  • env (Hash) -- Hash of environment variables
  • stdin (String) -- The +stdin+ to provide to the command
  • cmd (String) -- The command to run, for example +echo "Hello, world!"+
def qbash(cmd, stdin: '', env: {}, log: Loog::NULL, accept: [0], both: false, timeout: nil)
  cmd = cmd.join(' ') if cmd.is_a?(Array)
  if log.respond_to?(:debug)
    log.debug("+ #{cmd}")
  else
    log.print("+ #{cmd}\n")
  end
  buf = ''
  e = 1
  start = Time.now
  thread =
    Thread.new do
      Open3.popen2e(env, "/bin/bash -c #{Shellwords.escape(cmd)}") do |sin, sout, thr|
        sin.write(stdin)
        sin.close
        until sout.eof?
          begin
            ln = sout.gets
          rescue IOError => e
            ln = Backtrace.new(e).to_s
          end
          if log.respond_to?(:debug)
            log.debug(ln)
          else
            log.print("#{ln}\n")
          end
          buf += ln
        end
        e = thr.value.to_i
        if !accept.empty? && !accept.include?(e)
          raise "The command '#{cmd}' failed with exit code ##{e} in #{start.ago}\n#{buf}"
        end
      end
    end
  raise "Execution of #{cmd} timed out in #{start.ago}" if thread.join(timeout).nil?
  return [buf, e] if both
  buf
end