| 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