Module | Ohai::Mixin::Command |
In: |
lib/ohai/mixin/command.rb
|
This is taken directly from Ara T Howard‘s Open4 library, and then modified to suit the needs of Ohai. Any bugs here are most likely my own, and not Ara‘s.
The original appears in external/open4.rb in its unmodified form.
Thanks Ara!
# File lib/ohai/mixin/command.rb, line 99 99: def popen4(cmd, args={}, &b) 100: 101: args[:user] ||= nil 102: unless args[:user].kind_of?(Integer) 103: args[:user] = Etc.getpwnam(args[:user]).uid if args[:user] 104: end 105: args[:group] ||= nil 106: unless args[:group].kind_of?(Integer) 107: args[:group] = Etc.getgrnam(args[:group]).gid if args[:group] 108: end 109: args[:environment] ||= {} 110: 111: # Default on C locale so parsing commands output can be done 112: # independently of the node's default locale. 113: # "LC_ALL" could be set to nil, in which case we also must ignore it. 114: unless args[:environment].has_key?("LC_ALL") 115: args[:environment]["LC_ALL"] = "C" 116: end 117: 118: pw, pr, pe, ps = IO.pipe, IO.pipe, IO.pipe, IO.pipe 119: 120: verbose = $VERBOSE 121: begin 122: $VERBOSE = nil 123: ps.last.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) 124: 125: cid = fork { 126: pw.last.close 127: STDIN.reopen pw.first 128: pw.first.close 129: 130: pr.first.close 131: STDOUT.reopen pr.last 132: pr.last.close 133: 134: pe.first.close 135: STDERR.reopen pe.last 136: pe.last.close 137: 138: STDOUT.sync = STDERR.sync = true 139: 140: if args[:user] 141: Process.euid = args[:user] 142: Process.uid = args[:user] 143: end 144: 145: if args[:group] 146: Process.egid = args[:group] 147: Process.gid = args[:group] 148: end 149: 150: args[:environment].each do |key,value| 151: ENV[key] = value 152: end 153: 154: begin 155: if cmd.kind_of?(Array) 156: exec(*cmd) 157: else 158: exec(cmd) 159: end 160: raise 'forty-two' 161: rescue Exception => e 162: Marshal.dump(e, ps.last) 163: ps.last.flush 164: end 165: ps.last.close unless (ps.last.closed?) 166: exit! 167: } 168: ensure 169: $VERBOSE = verbose 170: end 171: 172: [pw.first, pr.last, pe.last, ps.last].each{|fd| fd.close} 173: 174: begin 175: e = Marshal.load ps.first 176: # If we get here, exec failed. Collect status of child to prevent 177: # zombies. 178: Process.waitpid(cid) 179: raise(Exception === e ? e : "unknown failure!") 180: rescue EOFError # If we get an EOF error, then the exec was successful 181: 42 182: ensure 183: ps.first.close 184: end 185: 186: pw.last.sync = true 187: 188: pi = [pw.last, pr.first, pe.first] 189: 190: if b 191: begin 192: b[cid, *pi] 193: Process.waitpid2(cid).last 194: ensure 195: pi.each{|fd| fd.close unless fd.closed?} 196: end 197: else 198: [cid, pw.last, pr.first, pe.first] 199: end 200: end
# File lib/ohai/mixin/command.rb, line 31 31: def run_command(args={}) 32: if args.has_key?(:creates) 33: if File.exists?(args[:creates]) 34: Ohai::Log.debug("Skipping #{args[:command]} - creates #{args[:creates]} exists.") 35: return false 36: end 37: end 38: 39: stdout_string = nil 40: stderr_string = nil 41: 42: args[:cwd] ||= Dir.tmpdir 43: unless File.directory?(args[:cwd]) 44: raise Ohai::Exceptions::Exec, "#{args[:cwd]} does not exist or is not a directory" 45: end 46: 47: status = nil 48: Dir.chdir(args[:cwd]) do 49: if args[:timeout] 50: begin 51: Timeout.timeout(args[:timeout]) do 52: status, stdout_string, stderr_string = systemu(args[:command]) 53: end 54: rescue Exception => e 55: Ohai::Log.error("#{args[:command_string]} exceeded timeout #{args[:timeout]}") 56: raise(e) 57: end 58: else 59: status, stdout_string, stderr_string = systemu(args[:command]) 60: end 61: 62: # systemu returns 42 when it hits unexpected errors 63: if status.exitstatus == 42 and stderr_string == "" 64: stderr_string = "Failed to run: #{args[:command]}, assuming command not found" 65: Ohai::Log.debug(stderr_string) 66: end 67: 68: if stdout_string 69: Ohai::Log.debug("---- Begin #{args[:command]} STDOUT ----") 70: Ohai::Log.debug(stdout_string.strip) 71: Ohai::Log.debug("---- End #{args[:command]} STDOUT ----") 72: end 73: if stderr_string 74: Ohai::Log.debug("---- Begin #{args[:command]} STDERR ----") 75: Ohai::Log.debug(stderr_string.strip) 76: Ohai::Log.debug("---- End #{args[:command]} STDERR ----") 77: end 78: 79: args[:returns] ||= 0 80: args[:no_status_check] ||= false 81: if status.exitstatus != args[:returns] and not args[:no_status_check] 82: raise Ohai::Exceptions::Exec, "#{args[:command_string]} returned #{status.exitstatus}, expected #{args[:returns]}" 83: else 84: Ohai::Log.debug("Ran #{args[:command_string]} (#{args[:command]}) returned #{status.exitstatus}") 85: end 86: end 87: return status, stdout_string, stderr_string 88: end