Module: Mixlib::ShellOut::Unix
- Included in:
- Mixlib::ShellOut
- Defined in:
- lib/mixlib/shellout/unix.rb
Constant Summary collapse
- ONE_DOT_EIGHT_DOT_SEVEN =
“1.8.7” as a frozen string. We use this with a hack that disables GC to avoid segfaults on Ruby 1.8.7, so we need to allocate the fewest objects we possibly can.
"1.8.7".freeze
Instance Method Summary collapse
-
#all_seconderies ⇒ Object
Helper method for sgids.
-
#logon_environment ⇒ Object
The environment variables that are deduced from simulating logon Only valid if login is used.
-
#process_environment ⇒ Object
Merges the two environments for the process.
-
#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. -
#sgids ⇒ Object
The secondary groups that the subprocess will switch to.
-
#using_login? ⇒ Boolean
Whether we’re simulating a login shell.
-
#validate_options(opts) ⇒ Object
Option validation that is unix specific.
Instance Method Details
#all_seconderies ⇒ Object
Helper method for sgids
41 42 43 44 45 46 47 48 49 |
# File 'lib/mixlib/shellout/unix.rb', line 41 def all_seconderies ret = [] Etc.endgrent while ( g = Etc.getgrent ) ret << g end Etc.endgrent ret end |
#logon_environment ⇒ Object
The environment variables that are deduced from simulating logon Only valid if login is used
63 64 65 66 67 68 69 70 71 |
# File 'lib/mixlib/shellout/unix.rb', line 63 def logon_environment return {} unless using_login? entry = Etc.getpwuid(uid) # According to `man su`, the set fields are: # $HOME, $SHELL, $USER, $LOGNAME, $PATH, and $IFS # Values are copied from "shadow" package in Ubuntu 14.10 { "HOME" => entry.dir, "SHELL" => entry.shell, "USER" => entry.name, "LOGNAME" => entry.name, "PATH" => "/sbin:/bin:/usr/sbin:/usr/bin", "IFS" => "\t\n" } end |
#process_environment ⇒ Object
Merges the two environments for the process
74 75 76 |
# File 'lib/mixlib/shellout/unix.rb', line 74 def process_environment logon_environment.merge(environment) 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)
-
Chef::Exceptions::CommandTimeout when the command does not complete within
timeout
seconds (default: 600s). When this happens, ShellOut will send a TERM and then KILL to the entire process group to ensure that any grandchild processes are terminated. If the invocation of the child process spawned multiple child processes (which commonly happens if the command is passed as a single string to be interpreted by bin/sh, and bin/sh is not bash), the exit status object may not contain the correct exit code of the process (of course there is no exit code if the command is killed by SIGKILL, also).
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/mixlib/shellout/unix.rb', line 96 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. Disabling GC works around the # segfault, but obviously it's a bad workaround. We no longer support # 1.8.6 so we only need this hack for 1.8.7. GC.disable if RUBY_VERSION == ONE_DOT_EIGHT_DOT_SEVEN # 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 @status = nil @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 |
#sgids ⇒ Object
The secondary groups that the subprocess will switch to. Currently valid only if login is used, and is set to the user’s secondary groups
54 55 56 57 58 59 |
# File 'lib/mixlib/shellout/unix.rb', line 54 def sgids return nil unless using_login? user_name = Etc.getpwuid(uid).name all_seconderies.select { |g| g.mem.include?(user_name) }.map(&:gid) end |
#using_login? ⇒ Boolean
Whether we’re simulating a login shell
36 37 38 |
# File 'lib/mixlib/shellout/unix.rb', line 36 def using_login? login && user end |
#validate_options(opts) ⇒ Object
Option validation that is unix specific
29 30 31 32 33 |
# File 'lib/mixlib/shellout/unix.rb', line 29 def (opts) if opts[:elevated] raise InvalidCommandOption, "Option `elevated` is supported for Powershell commands only" end end |