234: def execute(command, arguments = {:failonfail => true, :combine => true})
235: if command.is_a?(Array)
236: command = command.flatten.collect { |i| i.to_s }
237: str = command.join(" ")
238: else
239:
240:
241:
242: raise ArgumentError, "Must pass an array to execute()"
243: end
244:
245: if respond_to? :debug
246: debug "Executing '%s'" % str
247: else
248: Puppet.debug "Executing '%s'" % str
249: end
250:
251: if arguments[:uid]
252: arguments[:uid] = Puppet::Util::SUIDManager.convert_xid(:uid, arguments[:uid])
253: end
254: if arguments[:gid]
255: arguments[:gid] = Puppet::Util::SUIDManager.convert_xid(:gid, arguments[:gid])
256: end
257:
258: @@os ||= Facter.value(:operatingsystem)
259: output = nil
260: child_pid, child_status = nil
261:
262:
263:
264:
265:
266: output_file="/dev/null"
267: error_file="/dev/null"
268: if ! arguments[:squelch]
269: require "tempfile"
270: output_file = Tempfile.new("puppet")
271: if arguments[:combine]
272: error_file=output_file
273: end
274: end
275:
276: oldverb = $VERBOSE
277: $VERBOSE = nil
278: child_pid = Kernel.fork
279: $VERBOSE = oldverb
280: if child_pid
281:
282: child_status = (Process.waitpid2(child_pid)[1]).to_i >> 8
283: else
284:
285: Process.setsid
286: begin
287: if arguments[:stdinfile]
288: $stdin.reopen(arguments[:stdinfile])
289: else
290: $stdin.reopen("/dev/null")
291: end
292: $stdout.reopen(output_file)
293: $stderr.reopen(error_file)
294:
295: 3.upto(256){|fd| IO::new(fd).close rescue nil}
296: if arguments[:gid]
297: Process.egid = arguments[:gid]
298: Process.gid = arguments[:gid] unless @@os == "Darwin"
299: end
300: if arguments[:uid]
301: Process.euid = arguments[:uid]
302: Process.uid = arguments[:uid] unless @@os == "Darwin"
303: end
304: ENV['LANG'] = ENV['LC_ALL'] = ENV['LC_MESSAGES'] = ENV['LANGUAGE'] = 'C'
305: if command.is_a?(Array)
306: Kernel.exec(*command)
307: else
308: Kernel.exec(command)
309: end
310: rescue => detail
311: puts detail.to_s
312: exit!(1)
313: end
314: end
315:
316:
317: if ! arguments[:squelch]
318:
319:
320:
321:
322: unless FileTest.exists?(output_file.path)
323: Puppet.warning "sleeping"
324: sleep 0.5
325: unless FileTest.exists?(output_file.path)
326: Puppet.warning "sleeping 2"
327: sleep 1
328: unless FileTest.exists?(output_file.path)
329: Puppet.warning "Could not get output"
330: output = ""
331: end
332: end
333: end
334: unless output
335:
336:
337: output = output_file.open.read
338:
339:
340: output_file.close(true)
341: end
342: end
343:
344: if arguments[:failonfail]
345: unless child_status == 0
346: raise ExecutionFailure, "Execution of '%s' returned %s: %s" % [str, child_status, output]
347: end
348: end
349:
350: return output
351: end