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.exitstatus
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 = Dir.tmpdir 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: # Check if the parent thread is alive. If it should die, 71: # and the process spawned by systemu is still alive, 72: # fire off a blocking waitpid and wait for the process to 73: # finish so that we can avoid zombies. 74: thread = Thread.current 75: @status = systemu(@command, opts) do |cid| 76: begin 77: while(thread.alive?) 78: sleep 0.1 79: end 80: 81: Process.waitpid(cid) if Process.getpgid(cid) 82: rescue SystemExit 83: rescue Errno::ESRCH 84: rescue Errno::ECHILD 85: rescue Exception => e 86: Log.info("Unexpected exception received while waiting for child process: #{e.class}: #{e}") 87: end 88: end 89: end