Module: Mixlib::ShellOut::Unix

Included in:
Mixlib::ShellOut
Defined in:
lib/mixlib/shellout/unix.rb

Instance Method Summary collapse

Instance Method Details

#run_commandObject

Run the command, writing the command’s standard out and standard error to stdout and stderr, and saving its exit status object to status

Returns

returns self; stdout, stderr, status, and exitstatus will be populated with results of the command

Raises

  • Errno::EACCES when you are not privileged to execute the command

  • Errno::ENOENT when the command is not available on the system (or not in the current $PATH)

  • Chef::Exceptions::CommandTimeout when the command does not complete within timeout seconds (default: 600s)



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/mixlib/shellout/unix.rb', line 39

def run_command
  @child_pid = fork_subprocess
  @reaped = false

  configure_parent_process_file_descriptors

  # Ruby 1.8.7 and 1.8.6 from mid 2009 try to allocate objects during GC
  # when calling IO.select and IO#read. Some OS Vendors are not interested
  # in updating their ruby packages (Apple, *cough*) and we *have to*
  # make it work. So I give you this epic hack:
  GC.disable

  # CHEF-3390: Marshall.load on Ruby < 1.8.7p369 also has a GC bug related
  # to Marshall.load, so try disabling GC first.
  propagate_pre_exec_failure

  @result = nil
  @execution_time = 0

  write_to_child_stdin

  until @status
    ready_buffers = attempt_buffer_read
    unless ready_buffers
      @execution_time += READ_WAIT_TIME
      if @execution_time >= timeout && !@result
        # kill the bad proccess
        reap_errant_child
        # read anything it wrote when we killed it
        attempt_buffer_read
        # raise
        raise CommandTimeout, "Command timed out after #{@execution_time.to_i}s:\n#{format_for_exception}"
      end
    end

    attempt_reap
  end

  self
rescue Errno::ENOENT
  # When ENOENT happens, we can be reasonably sure that the child process
  # is going to exit quickly, so we use the blocking variant of waitpid2
  reap
  raise
ensure
  reap_errant_child if should_reap?
  # make one more pass to get the last of the output after the
  # child process dies
  attempt_buffer_read
  # no matter what happens, turn the GC back on, and hope whatever busted
  # version of ruby we're on doesn't allocate some objects during the next
  # GC run.
  GC.enable
  close_all_pipes
end

#validate_options(opts) ⇒ Object

Option validation that is unix specific



24
25
26
# File 'lib/mixlib/shellout/unix.rb', line 24

def validate_options(opts)
  # No options to validate, raise exceptions here if needed
end