| 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