Module: MiGA::Common::SystemCall

Included in:
MiGA
Defined in:
lib/miga/common/system_call.rb

Overview

General functions for process (system call) execution

Instance Method Summary collapse

Instance Method Details

#run_cmd(cmd, opts = {}) ⇒ Object

Execute the command cmd with options opts determined by #run_cmd_opts

The command cmd can be:

  • String: The command is processed as is, without changes

  • Array: The command is built with shelljoin so each value is escaped



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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/miga/common/system_call.rb', line 12

def run_cmd(cmd, opts = {})
  opts = run_cmd_opts(opts)
  cmd = cmd.shelljoin if cmd.is_a?(Array)
  spawn_opts = {}
  spawn_opts[:out] = opts[:stdout] if opts[:stdout]
  spawn_opts[:err] = opts[:stderr] if opts[:stderr]
  out_io, spawn_opts[:out] = IO.pipe if opts[:return] == :output
  spawn_opts[:err] = [:child, :out] if opts[:err2out] && spawn_opts[:out]
  opts[:source] = MiGA::MiGA.rc_path if opts[:source] == :miga
  if opts[:source] && File.exist?(opts[:source])
    cmd = ". #{opts[:source].shellescape} && #{cmd}"
  end

  DEBUG "CMD: #{cmd}"
  puts "CMD: #{cmd}" if opts[:show_cmd]
  return if opts[:dry]

  pid = nil
  error = nil
  begin
    pid = spawn(opts[:env], cmd, spawn_opts)
    Process.wait(pid)
  rescue => e
    error = e
  end
  status = $?

  if opts[:raise] && !status&.success?
    raise MiGA::SystemCallError.new(
      "Command failed with status " \
        "#{status&.exitstatus}#{' (core dump)' if status&.coredump?}:\n" \
        "#{error&.class}: #{error&.message}\n" \
        "OPT: #{opts}\n" \
        "CMD: #{cmd}"
    )
  end

  case opts[:return]
  when :status ; status
  when :pid    ; pid
  when :error  ; error
  when :output
    spawn_opts[:out].close
    output = out_io.read
    out_io.close
    output
  end
end

#run_cmd_opts(opts = {}) ⇒ Object

Options for #run_cmd using a Hash opts to modify defaults

Supported keys (as Symbol) include:

  • stdout: Redirect STDOUT to this file

  • stderr: Redirect STDOUT to this file

  • dry: Don’t run, just send the command to debug (default: false)

  • return: What should the function return, supported values are :status (Process::Status, default), :pid (Integer, process ID), :error (Error if failed, nil otherwise), :output (String, contents sent to STDOUT)

  • raise: Raise an exception (MiGA::SystemCallError) in case of failure (default: true)

  • show_cmd: Print command to the STDOUT (prefixed with CMD: ) to ease debugging (default: false)

  • err2out: Redirect STDERR to STDOUT

  • env: Environmental variables as a Hash, keys and values must be strings

  • source: A file to be sourced before running, or the Symbol :miga to source the MiGA configuration file



80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/miga/common/system_call.rb', line 80

def run_cmd_opts(opts = {})
  {
    stdout: nil,
    stderr: nil,
    dry: false,
    return: :status,
    raise: true,
    show_cmd: false,
    err2out: false,
    env: {},
    source: nil
  }.merge(opts)
end