Module: System

Defined in:
lib/system_run.rb

Class Method Summary collapse

Class Method Details

.run(cmd, *args, timeout: nil, env: {}, capture: :default, file: nil, cwd: '.', on_timeout: nil, **kwargs) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/system_run.rb', line 6

def self.run(cmd, *args, timeout: nil, env: {}, capture: :default, file: nil, cwd: '.', on_timeout: nil, **kwargs)
  cmd = cmd.dup << ' ' << args.join(' ')
  env = env.dup.map { |k, v| [k.to_s, v.to_s] }.to_h

  unless file.nil? || file.all? { |f| f.is_a?(File) || f.is_a?(Tempfile) }
    raise ArgumentError, 'file(s) must be instance of File or Tempfile'
  end

  unless capture != :default || file.nil? || file.is_a?(Array) && file.size == 2
    raise ArgumentError, 'invalid file redirects for default capture, expected array of two'
  end

  out, err = case capture
             when :default then file ? [file.first, file.last] : [Tempfile.new('sysrun-out'), Tempfile.new('sysrun-err')]
             when :out then [file || Tempfile.new('sysrun-out'), '/dev/null']
             when :err then ['/dev/null', file || Tempfile.new('sysrun-err')]
             when :both then [file || Tempfile.new('sysrun-outerr')] * 2
             else raise ArgumentError, "unknown capture: #{capture}"
             end

  pid = spawn env, cmd, out: out, err: err, chdir: cwd, **kwargs
  status = wait_or_kill pid, timeout, on_timeout
  [out, err].each { |f| f.rewind if f.respond_to? :rewind }

  file ? status : case capture
                  when :default then [status, out.read, err.read]
                  when :out, :both then [status, out.read]
                  when :err then [status, err.read]
                  end
ensure
  [out, err].each { |f| f.unlink if f.is_a?(Tempfile) && f.path&.include?('sysrun') }
end