Module: CemAcpt::Utils::Shell

Defined in:
lib/cem_acpt/utils/shell.rb

Overview

Generic utilities for running local shell commands

Class Method Summary collapse

Class Method Details

.run_cmd(cmd, env = {}, output: $stdout, raise_on_fail: true, combine_out_err: true) ⇒ String

Runs a command in a subshell and returns the Process::Status and the string output of the command.



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
# File 'lib/cem_acpt/utils/shell.rb', line 26

def self.run_cmd(cmd, env = {}, output: $stdout, raise_on_fail: true, combine_out_err: true)
  io_out = StringIO.new
  if output.respond_to?(:debug)
    output.debug('CemAcpt::Utils::Shell') { "Running command:\n\t#{cmd}\nWith environment:\n\t#{env}" }
  elsif output
    output << "Running command:\n\t#{cmd}\nWith environment:\n\t#{env}\n"
  end
  val = Open3.popen3(env, cmd) do |i, o, e, t|
    i.close
    o.sync = true
    e.sync = true
    output_thread = Thread.new do
      while (line = o.gets("\n"))
        output << line if output
        io_out.write(line) unless line.chomp.empty?
      end
      if combine_out_err
        while (line = e.gets("\n"))
          output << line if output && combine_out_err
          io_out.write(line) unless line.chomp.empty?
        end
      end
    end
    t.join
    output_thread.exit
    t.value
  end
  io_string = io_out.string
  raise CemAcpt::ShellCommandError, "Error running command: #{cmd}\n#{io_string}" if raise_on_fail && !val.success?

  io_string
end

.which(cmd, include_ruby_bin: false, raise_if_not_found: false) ⇒ String?

Mimics the behavior of the which command.

Raises:



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/cem_acpt/utils/shell.rb', line 67

def self.which(cmd, include_ruby_bin: false, raise_if_not_found: false)
  return cmd if File.executable?(cmd) && !File.directory?(cmd)

  exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
  ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
    next if path.include?('/ruby') && !include_ruby_bin

    exts.each do |ext|
      exe = File.join(path, "#{cmd}#{ext}")
      return exe if File.executable?(exe) && !File.directory?(exe)
    end
  end
  raise CemAcpt::ShellCommandNotFoundError, "Command #{cmd} not found in PATH" if raise_if_not_found

  nil
end