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