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] ||= {} 113: 114: # Default on C locale so parsing commands output can be done 115: # independently of the node's default locale. 116: # "LC_ALL" could be set to nil, in which case we also must ignore it. 117: unless args[:environment].has_key?("LC_ALL") 118: args[:environment]["LC_ALL"] = "C" 119: end 120: 121: pw, pr, pe, ps = IO.pipe, IO.pipe, IO.pipe, IO.pipe 122: 123: verbose = $VERBOSE 124: begin 125: $VERBOSE = nil 126: ps.last.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) 127: 128: cid = fork { 129: pw.last.close 130: STDIN.reopen pw.first 131: pw.first.close 132: 133: pr.first.close 134: STDOUT.reopen pr.last 135: pr.last.close 136: 137: pe.first.close 138: STDERR.reopen pe.last 139: pe.last.close 140: 141: STDOUT.sync = STDERR.sync = true 142: 143: if args[:user] 144: Process.euid = args[:user] 145: Process.uid = args[:user] 146: end 147: 148: if args[:group] 149: Process.egid = args[:group] 150: Process.gid = args[:group] 151: end 152: 153: args[:environment].each do |key,value| 154: ENV[key] = value 155: end 156: 157: begin 158: if cmd.kind_of?(Array) 159: exec(*cmd) 160: else 161: exec(cmd) 162: end 163: raise 'forty-two' 164: rescue Exception => e 165: Marshal.dump(e, ps.last) 166: ps.last.flush 167: end 168: ps.last.close unless (ps.last.closed?) 169: exit! 170: } 171: ensure 172: $VERBOSE = verbose 173: end 174: 175: [pw.first, pr.last, pe.last, ps.last].each{|fd| fd.close} 176: 177: begin 178: e = Marshal.load ps.first 179: # If we get here, exec failed. Collect status of child to prevent 180: # zombies. 181: Process.waitpid(cid) 182: raise(Exception === e ? e : "unknown failure!") 183: rescue EOFError # If we get an EOF error, then the exec was successful 184: 42 185: ensure 186: ps.first.close 187: end 188: 189: pw.last.sync = true 190: 191: pi = [pw.last, pr.first, pe.first] 192: 193: if b 194: begin 195: b[cid, *pi] 196: Process.waitpid2(cid).last 197: ensure 198: pi.each{|fd| fd.close unless fd.closed?} 199: end 200: else 201: [cid, pw.last, pr.first, pe.first] 202: end 203: 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