module Mixlib::ShellOut::Unix
def run_command
* Chef::Exceptions::CommandTimeout when the command does not complete
in the current $PATH)
* Errno::ENOENT when the command is not available on the system (or not
* Errno::EACCES when you are not privileged to execute the command
=== Raises
populated with results of the command
returns +self+; +stdout+, +stderr+, +status+, and +exitstatus+ will be
=== Returns
to +stdout+ and +stderr+, and saving its exit status object to +status+
Run the command, writing the command's standard out and standard error
def run_command @child_pid = fork_subprocess configure_parent_process_file_descriptors propagate_pre_exec_failure @result = nil @execution_time = 0 write_to_child_stdin # 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 until @status ready = IO.select(open_pipes, nil, nil, READ_WAIT_TIME) unless ready @execution_time += READ_WAIT_TIME if @execution_time >= timeout && !@result raise CommandTimeout, "command timed out:\n#{format_for_exception}" end end if ready && ready.first.include?(child_stdout) read_stdout_to_buffer end if ready && ready.first.include?(child_stderr) read_stderr_to_buffer end unless @status # make one more pass to get the last of the output after the # child process dies if results = Process.waitpid2(@child_pid, Process::WNOHANG) @status = results.last redo end end end self rescue Exception # do our best to kill zombies Process.waitpid2(@child_pid, Process::WNOHANG) rescue nil raise ensure # 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