oo_spawn(command, [, options]) -> [stdout, stderr, exit status]
spawn executes specified command and return its stdout, stderr and exit status. Or, raise exceptions if certain conditions are not met.
command: command line string which is passed to the standard shell
options: hash
:env: hash name => val : set the environment variable name => nil : unset the environment variable :unsetenv_others => true : clear environment variables except specified by :env :chdir => path : set current directory when running command :expected_exitstatus : An Integer value for the expected return code of command : If not set spawn() returns exitstatus from command otherwise : raise an error if exitstatus is not expected_exitstatus :timeout : Maximum number of seconds to wait for command to finish. default: 3600 :uid : spawn command as given user in a SELinux context using runuser/runcon, : stdin for the command is /dev/null :out : If specified, STDOUT from the child process will be redirected to the provided +IO+ object. :err : If specified, STDERR from the child process will be redirected to the provided +IO+ object.
NOTE: If the out or err options are specified, the corresponding return value from oo_spawn will be the incoming/provided IO objects instead of the buffered String output. It's the responsibility of the caller to correctly handle the resulting data type.
# File lib/openshift-origin-node/utils/shell_exec.rb, line 80 def self.oo_spawn(command, options = {}) options[:env] ||= {} options[:timeout] ||= 3600 options[:buffer_size] ||= 32768 opts = {} opts[:unsetenv_others] = (options[:unsetenv_others] || false) opts[:close_others] = true opts[:in] = (options[:in] || '/dev/null') opts[:chdir] = options[:chdir] if options[:chdir] IO.pipe do |read_stderr, write_stderr| IO.pipe do |read_stdout, write_stdout| opts[:out] = write_stdout opts[:err] = write_stderr if options[:uid] # lazy init otherwise we end up with a cyclic require... require 'openshift-origin-node/utils/selinux' current_context = SELinux.getcon target_context = SELinux.context_from_defaults(SELinux.get_mcs_label(options[:uid])) # Only switch contexts if necessary if (current_context != target_context) || (Process.uid != options[:uid]) target_name = Etc.getpwuid(options[:uid]).name exec = %{exec /usr/bin/runcon '#{target_context}' /bin/sh -c \\"#{command}\\"} command = %{/sbin/runuser -m -s /bin/sh #{target_name} -c "#{exec}"} end end NodeLogger.trace_logger.debug { "oo_spawn running #{command}: #{opts}" } pid = Kernel.spawn(options[:env], command, opts) unless pid raise OpenShift::Utils::ShellExecutionException.new( "Kernel.spawn failed for command '#{command}'") end begin write_stdout.close write_stderr.close out, err, status = read_results(pid, read_stdout, read_stderr, options) NodeLogger.logger.debug { "Shell command '#{command}' ran. rc=#{status.exitstatus} out=#{out}" } if (!options[:expected_exitstatus].nil?) && (status.exitstatus != options[:expected_exitstatus]) raise OpenShift::Utils::ShellExecutionException.new( "Shell command '#{command}' returned an error. rc=#{status.exitstatus}", status.exitstatus, out, err) end return [out, err, status.exitstatus] rescue TimeoutExceeded => e ShellExec.kill_process_tree(pid) raise OpenShift::Utils::ShellExecutionException.new( "Shell command '#{command}'' exceeded timeout of #{e.seconds}", -1, out, err) end end end end
Generated with the Darkfish Rdoc Generator 2.