Class: Mixlib::ShellOut
- Inherits:
-
Object
- Object
- Mixlib::ShellOut
- Defined in:
- lib/mixlib/shellout.rb,
lib/mixlib/shellout/unix.rb,
lib/mixlib/shellout/version.rb,
lib/mixlib/shellout/windows.rb,
lib/mixlib/shellout/exceptions.rb
Defined Under Namespace
Modules: Unix, Windows Classes: CommandTimeout, InvalidCommandOption, ShellCommandFailed
Constant Summary collapse
- READ_WAIT_TIME =
0.01
- READ_SIZE =
4096
- DEFAULT_READ_TIMEOUT =
600
- DEFAULT_ENVIRONMENT =
{'LC_ALL' => 'C'}
- VERSION =
"1.3.0"
Constants included from Windows
Instance Attribute Summary collapse
-
#command ⇒ Object
readonly
The command to be executed.
-
#cwd ⇒ Object
Working directory for the subprocess.
-
#domain ⇒ Object
Returns the value of attribute domain.
-
#environment ⇒ Object
readonly
Environment variables that will be set for the subcommand.
-
#execution_time ⇒ Object
readonly
The amount of time the subcommand took to execute.
-
#group ⇒ Object
Group the command will run as.
-
#input ⇒ Object
ShellOut will push data from :input down the stdin of the subprocss.
-
#live_stream ⇒ Object
When live_stream is set, stdout of the subprocess will be copied to it as the subprocess is running.
-
#log_level ⇒ Object
The log level at which ShellOut should log.
-
#log_tag ⇒ Object
A string which will be prepended to the log message.
-
#logger ⇒ Object
If a logger is set, ShellOut will log a message before it executes the command.
-
#password ⇒ Object
Returns the value of attribute password.
-
#process_status_pipe ⇒ Object
readonly
Returns the value of attribute process_status_pipe.
-
#status ⇒ Object
readonly
A Process::Status (or ducktype) object collected when the subprocess is reaped.
-
#stderr ⇒ Object
readonly
Data written to stderr by the subprocess.
-
#stderr_pipe ⇒ Object
readonly
Returns the value of attribute stderr_pipe.
-
#stdin_pipe ⇒ Object
readonly
Returns the value of attribute stdin_pipe.
-
#stdout ⇒ Object
readonly
Data written to stdout by the subprocess.
-
#stdout_pipe ⇒ Object
readonly
Returns the value of attribute stdout_pipe.
- #timeout ⇒ Object
-
#umask ⇒ Object
The umask that will be set for the subcommand.
-
#user ⇒ Object
User the command will run as.
-
#valid_exit_codes ⇒ Object
An Array of acceptable exit codes.
-
#with_logon ⇒ Object
Returns the value of attribute with_logon.
Instance Method Summary collapse
-
#error! ⇒ Object
Checks the
exitstatus
against the set ofvalid_exit_codes
. -
#exitstatus ⇒ Object
The exit status of the subprocess.
-
#format_for_exception ⇒ Object
Creates a String showing the output of the command, including a banner showing the exact command executed.
-
#gid ⇒ Object
The gid that the subprocess will switch to.
-
#initialize(*command_args) ⇒ ShellOut
constructor
Arguments: Takes a single command, or a list of command fragments.
- #inspect ⇒ Object
-
#invalid!(msg = nil) ⇒ Object
Raises a ShellCommandFailed exception, appending the command’s stdout, stderr, and exitstatus to the exception message.
-
#run_command ⇒ Object
Run the command, writing the command’s standard out and standard error to
stdout
andstderr
, and saving its exit status object tostatus
=== Returns returnsself
;stdout
,stderr
,status
, andexitstatus
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) * CommandTimeout when the command does not complete withintimeout
seconds (default: 600s). -
#uid ⇒ Object
The uid that the subprocess will switch to.
Constructor Details
#initialize(*command_args) ⇒ ShellOut
Arguments:
Takes a single command, or a list of command fragments. These are used as arguments to Kernel.exec. See the Kernel.exec documentation for more explanation of how arguments are evaluated. The last argument can be an options Hash.
Options:
If the last argument is a Hash, it is removed from the list of args passed to exec and used as an options hash. The following options are available:
-
user
: the user the commmand should run as. if an integer is given, it is used as a uid. A string is treated as a username and resolved to a uid with Etc.getpwnam -
group
: the group the command should run as. works similarly touser
-
cwd
: the directory to chdir to before running the command -
umask
: a umask to set before running the command. If given as an Integer, be sure to use two leading zeros so it’s parsed as Octal. A string will be treated as an octal integer -
returns
: one or more Integer values to use as valid exit codes for the subprocess. This only has an effect if you callerror!
afterrun_command
. -
environment
: a Hash of environment variables to set before the command is run. By default, the environment will always be set to ‘LC_ALL’ => ‘C’ to prevent issues with multibyte characters in Ruby 1.8. To avoid this, use :environment => nil for no extra environment settings, or :environment => … to set other environment settings without changing the locale. -
timeout
: a Numeric value for the number of seconds to wait on the child process before raising an Exception. This is calculated as the total amount of time that ShellOut waited on the child process without receiving any output (i.e., IO.select returned nil). Default is 60 seconds. Note: the stdlib Timeout library is not used.
Examples:
Invoke find(1) to search for .rb files:
find = Mixlib::ShellOut.new("find . -name '*.rb'")
find.run_command
# If all went well, the results are on +stdout+
puts find.stdout
# find(1) prints diagnostic info to STDERR:
puts "error messages" + find.stderr
# Raise an exception if it didn't exit with 0
find.error!
Run a command as the www
user with no extra ENV settings from /tmp
cmd = Mixlib::ShellOut.new("apachectl", "start", :user => 'www', :env => nil, :cwd => '/tmp')
cmd.run_command # etc.
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/mixlib/shellout.rb', line 148 def initialize(*command_args) @stdout, @stderr = '', '' @live_stream = nil @input = nil @log_level = :debug @log_tag = nil @environment = DEFAULT_ENVIRONMENT @cwd = nil @valid_exit_codes = [0] @terminate_reason = nil if command_args.last.is_a?(Hash) (command_args.pop) end @command = command_args.size == 1 ? command_args.first : command_args end |
Instance Attribute Details
#command ⇒ Object (readonly)
The command to be executed.
77 78 79 |
# File 'lib/mixlib/shellout.rb', line 77 def command @command end |
#cwd ⇒ Object
Working directory for the subprocess. Normally set via options to new
50 51 52 |
# File 'lib/mixlib/shellout.rb', line 50 def cwd @cwd end |
#domain ⇒ Object
Returns the value of attribute domain.
42 43 44 |
# File 'lib/mixlib/shellout.rb', line 42 def domain @domain end |
#environment ⇒ Object (readonly)
Environment variables that will be set for the subcommand. Refer to the documentation of new to understand how ShellOut interprets this.
84 85 86 |
# File 'lib/mixlib/shellout.rb', line 84 def environment @environment end |
#execution_time ⇒ Object (readonly)
The amount of time the subcommand took to execute
91 92 93 |
# File 'lib/mixlib/shellout.rb', line 91 def execution_time @execution_time end |
#group ⇒ Object
Group the command will run as. Normally set via options passed to new
47 48 49 |
# File 'lib/mixlib/shellout.rb', line 47 def group @group end |
#input ⇒ Object
ShellOut will push data from :input down the stdin of the subprocss. Normally set via options passed to new. Default: nil
64 65 66 |
# File 'lib/mixlib/shellout.rb', line 64 def input @input end |
#live_stream ⇒ Object
When live_stream is set, stdout of the subprocess will be copied to it as the subprocess is running. For example, if live_stream is set to STDOUT, the command’s output will be echoed to STDOUT.
59 60 61 |
# File 'lib/mixlib/shellout.rb', line 59 def live_stream @live_stream end |
#log_level ⇒ Object
The log level at which ShellOut should log.
71 72 73 |
# File 'lib/mixlib/shellout.rb', line 71 def log_level @log_level end |
#log_tag ⇒ Object
A string which will be prepended to the log message.
74 75 76 |
# File 'lib/mixlib/shellout.rb', line 74 def log_tag @log_tag end |
#logger ⇒ Object
If a logger is set, ShellOut will log a message before it executes the command.
68 69 70 |
# File 'lib/mixlib/shellout.rb', line 68 def logger @logger end |
#password ⇒ Object
Returns the value of attribute password.
43 44 45 |
# File 'lib/mixlib/shellout.rb', line 43 def password @password end |
#process_status_pipe ⇒ Object (readonly)
Returns the value of attribute process_status_pipe.
103 104 105 |
# File 'lib/mixlib/shellout.rb', line 103 def process_status_pipe @process_status_pipe end |
#status ⇒ Object (readonly)
A Process::Status (or ducktype) object collected when the subprocess is reaped.
101 102 103 |
# File 'lib/mixlib/shellout.rb', line 101 def status @status end |
#stderr ⇒ Object (readonly)
Data written to stderr by the subprocess
97 98 99 |
# File 'lib/mixlib/shellout.rb', line 97 def stderr @stderr end |
#stderr_pipe ⇒ Object (readonly)
Returns the value of attribute stderr_pipe.
103 104 105 |
# File 'lib/mixlib/shellout.rb', line 103 def stderr_pipe @stderr_pipe end |
#stdin_pipe ⇒ Object (readonly)
Returns the value of attribute stdin_pipe.
103 104 105 |
# File 'lib/mixlib/shellout.rb', line 103 def stdin_pipe @stdin_pipe end |
#stdout ⇒ Object (readonly)
Data written to stdout by the subprocess
94 95 96 |
# File 'lib/mixlib/shellout.rb', line 94 def stdout @stdout end |
#stdout_pipe ⇒ Object (readonly)
Returns the value of attribute stdout_pipe.
103 104 105 |
# File 'lib/mixlib/shellout.rb', line 103 def stdout_pipe @stdout_pipe end |
#timeout ⇒ Object
186 187 188 |
# File 'lib/mixlib/shellout.rb', line 186 def timeout @timeout || DEFAULT_READ_TIMEOUT end |
#umask ⇒ Object
The umask that will be set for the subcommand.
80 81 82 |
# File 'lib/mixlib/shellout.rb', line 80 def umask @umask end |
#user ⇒ Object
User the command will run as. Normally set via options passed to new
41 42 43 |
# File 'lib/mixlib/shellout.rb', line 41 def user @user end |
#valid_exit_codes ⇒ Object
An Array of acceptable exit codes. #error! uses this list to determine if the command was successful. Normally set via options to new
54 55 56 |
# File 'lib/mixlib/shellout.rb', line 54 def valid_exit_codes @valid_exit_codes end |
#with_logon ⇒ Object
Returns the value of attribute with_logon.
44 45 46 |
# File 'lib/mixlib/shellout.rb', line 44 def with_logon @with_logon end |
Instance Method Details
#error! ⇒ Object
Checks the exitstatus
against the set of valid_exit_codes
. If exitstatus
is not in the list of valid_exit_codes
, calls invalid!
, which raises an Exception.
Returns
- nil:
-
always returns nil when it does not raise
Raises
- ::ShellCommandFailed:
-
via
invalid!
237 238 239 240 241 |
# File 'lib/mixlib/shellout.rb', line 237 def error! unless Array(valid_exit_codes).include?(exitstatus) invalid!("Expected process to exit with #{valid_exit_codes.inspect}, but received '#{exitstatus}'") end end |
#exitstatus ⇒ Object
The exit status of the subprocess. Will be nil if the command is still running or died without setting an exit status (e.g., terminated by ‘kill -9`).
207 208 209 |
# File 'lib/mixlib/shellout.rb', line 207 def exitstatus @status && @status.exitstatus end |
#format_for_exception ⇒ Object
Creates a String showing the output of the command, including a banner showing the exact command executed. Used by invalid!
to show command results when the command exited with an unexpected status.
193 194 195 196 197 198 199 200 201 202 |
# File 'lib/mixlib/shellout.rb', line 193 def format_for_exception msg = "" msg << "#{@terminate_reason}\n" if @terminate_reason msg << "---- Begin output of #{command} ----\n" msg << "STDOUT: #{stdout.strip}\n" msg << "STDERR: #{stderr.strip}\n" msg << "---- End output of #{command} ----\n" msg << "Ran #{command} returned #{status.exitstatus}" if status msg end |
#gid ⇒ Object
The gid that the subprocess will switch to. If the group attribute is given as a group name, it is converted to a gid by Etc.getgrnam
181 182 183 184 |
# File 'lib/mixlib/shellout.rb', line 181 def gid return nil unless group group.kind_of?(Integer) ? group : Etc.getgrnam(group.to_s).gid end |
#inspect ⇒ Object
256 257 258 259 260 |
# File 'lib/mixlib/shellout.rb', line 256 def inspect "<#{self.class.name}##{object_id}: command: '#@command' process_status: #{@status.inspect} " + "stdout: '#{stdout.strip}' stderr: '#{stderr.strip}' child_pid: #{@child_pid.inspect} " + "environment: #{@environment.inspect} timeout: #{timeout} user: #@user group: #@group working_dir: #@cwd >" end |
#invalid!(msg = nil) ⇒ Object
Raises a ShellCommandFailed exception, appending the command’s stdout, stderr, and exitstatus to the exception message.
Arguments
msg
: A String to use as the basis of the exception message. The default explanation is very generic, providing a more informative message is highly encouraged.
Raises
ShellCommandFailed always
251 252 253 254 |
# File 'lib/mixlib/shellout.rb', line 251 def invalid!(msg=nil) msg ||= "Command produced unexpected results" raise ShellCommandFailed, msg + "\n" + format_for_exception end |
#run_command ⇒ Object
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)
-
CommandTimeout when the command does not complete within
timeout
seconds (default: 600s)
222 223 224 225 226 227 228 |
# File 'lib/mixlib/shellout.rb', line 222 def run_command if logger = (log_tag.nil? ? "" : "#@log_tag ") << "sh(#@command)" logger.send(log_level, ) end super end |
#uid ⇒ Object
The uid that the subprocess will switch to. If the user attribute was given as a username, it is converted to a uid by Etc.getpwnam
174 175 176 177 |
# File 'lib/mixlib/shellout.rb', line 174 def uid return nil unless user user.kind_of?(Integer) ? user : Etc.getpwnam(user.to_s).uid end |