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