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. :quiet : If specified, the output from the command will not be logged
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 83 def self.oo_spawn(command, options = {}) options[:env] ||= (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_context' current_context = SelinuxContext.instance.getcon target_context = SelinuxContext.instance.from_defaults(SelinuxContext.instance.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 -s /bin/sh #{target_name} -c "#{exec}"} end end NodeLogger.logger.trace { "oo_spawn running #{command}: #{opts}" } pid = Kernel.spawn(options[:env], command, opts) unless pid raise ::OpenShift::Runtime::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=#{options[:quiet] ? "[SILENCED]" : Runtime::Utils.sanitize_credentials(out)}" } if (!options[:expected_exitstatus].nil?) && (status.exitstatus != options[:expected_exitstatus]) raise ::OpenShift::Runtime::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 kill_process_tree(pid) raise ::OpenShift::Runtime::Utils::ShellExecutionException.new( "Shell command '#{command}' exceeded timeout of #{e.seconds}", -1, out, err) end end end end
# File lib/openshift-origin-node/utils/sanitize.rb, line 14 def self.sanitize_argument(arg) arg.to_s.gsub(/'/, '') end
# File lib/openshift-origin-node/utils/sanitize.rb, line 4 def self.sanitize_credentials(arg) begin arg.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '') .gsub(/(passwo?r?d\s*[:=]+\s*)\S+/, '\1[HIDDEN]') .gsub(/(usern?a?m?e?\s*[:=]+\s*)\S+/,'\1[HIDDEN]') rescue # If we were unable to encode the string, then just return it verbatim arg end end
Generated with the Darkfish Rdoc Generator 2.