Class | MCollective::Shell |
In: |
lib/mcollective/shell.rb
|
Parent: | Object |
Wrapper around systemu that handles executing of system commands in a way that makes stdout, stderr and status available. Supports timeouts and sets a default sane environment.
s = Shell.new("date", opts) s.runcommand puts s.stdout puts s.stderr puts s.status.exitcode
Options hash can have:
cwd - the working directory the command will be run from stdin - a string that will be sent to stdin of the program stdout - a variable that will receive stdout, must support << stderr - a variable that will receive stdin, must support << environment - the shell environment, defaults to include LC_ALL=C set to nil to clear the environment even of LC_ALL
command | [R] | |
cwd | [R] | |
environment | [R] | |
status | [R] | |
stderr | [R] | |
stdin | [R] | |
stdout | [R] |
# File lib/mcollective/shell.rb, line 24 24: def initialize(command, options={}) 25: @environment = {"LC_ALL" => "C"} 26: @command = command 27: @status = nil 28: @stdout = "" 29: @stderr = "" 30: @stdin = nil 31: @cwd = "/tmp" 32: 33: options.each do |opt, val| 34: case opt.to_s 35: when "stdout" 36: raise "stdout should support <<" unless val.respond_to?("<<") 37: @stdout = val 38: 39: when "stderr" 40: raise "stderr should support <<" unless val.respond_to?("<<") 41: @stderr = val 42: 43: when "stdin" 44: raise "stdin should be a String" unless val.is_a?(String) 45: @stdin = val 46: 47: when "cwd" 48: raise "Directory #{val} does not exist" unless File.directory?(val) 49: @cwd = val 50: 51: when "environment" 52: if val.nil? 53: @environment = {} 54: else 55: @environment.merge!(val.dup) 56: end 57: end 58: end 59: end
Actually does the systemu call passing in the correct environment, stdout and stderr
# File lib/mcollective/shell.rb, line 62 62: def runcommand 63: opts = {"env" => @environment, 64: "stdout" => @stdout, 65: "stderr" => @stderr, 66: "cwd" => @cwd} 67: 68: opts["stdin"] = @stdin if @stdin 69: 70: # Running waitpid on the cid here will start a thread 71: # with the waitpid in it, this way even if the thread 72: # that started this process gets killed due to agent 73: # timeout or such there will still be a waitpid waiting 74: # for the child to exit and not leave zombies. 75: @status = systemu(@command, opts) do |cid| 76: begin 77: sleep 1 78: Process::waitpid(cid) 79: rescue SystemExit 80: rescue Errno::ECHILD 81: rescue Exception => e 82: Log.info("Unexpected exception received while waiting for child process: #{e.class}: #{e}") 83: end 84: end 85: end