| 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