The Puppet Labs Issue Tracker has Moved: https://tickets.puppetlabs.com

Feature #7019

Display output of failed commands

Added by John Crenshaw over 3 years ago. Updated over 3 years ago.

Status:InvestigatingStart date:04/08/2011
Priority:NormalDue date:
Assignee:-% Done:

0%

Category:-
Target version:-
Affected Puppet version: Branch:
Keywords:

We've Moved!

Ticket tracking is now hosted in JIRA: https://tickets.puppetlabs.com

This ticket may be automatically exported to the PUP project on JIRA using the button below:


Description

When a command is executed, Puppet silently discards output in almost all cases (I think it is discarding stdout, and only displaying stderr?). A quick example:

Puppet gave me the following error: err: /Stage[main]/Apache::Base/Service[apache]: Failed to call refresh: Could not restart Service[apache]: Execution of '/etc/init.d/apache2 restart' returned 1: at /etc/puppet/modules/apache/manifests/classes/apache-base.pp:65

To get the actual details of the problem, I have to manually run the command: sudo /etc/init.d/apache2 restart

This gives me something more meaningful: Syntax error on line 2 of /etc/apache2/sites-enabled/example.com: Missing address for VirtualHost Action 'configtest' failed. The Apache error log may have more information.

Puppet should have displayed this information on its own when it detected that there was an error.

History

#1 Updated by Ben Hughes over 3 years ago

  • Status changed from Unreviewed to Investigating

This is deliberate I’m afraid. From my reading of the code STDIN, OUT and ERR are mapped to /dev/null on execution to avoid having to use IO#read on the process which blocks.

My best recommendation would be to use something like the following:

exec{ "apache2ctl conftest":
    notfiy => Service["apache2":],
    logoutout => on_failure, 
   ....,
}

Which would get you the output and not restart the service if it has errors.

#2 Updated by John Crenshaw over 3 years ago

Blast, I always forget about that reading deadlock.

Non-blocking reads are possible, but it can be a bit tricky to get right sometimes. The really hard part is that the other process can actually block itself by filling up one of the outputs. If you use something like gets() to read the output, you’ll end up listening for the wrong output sometimes, and everything will deadlock. The solution is to use a stream select (I think this is IO.Select in Ruby?) to wait for data on BOTH streams at once. The select should return when either stream has data for you, and should indicate which stream has the data, ensuring that you never deadlock by looking at the wrong stream. I have a working PHP implementation that I could share if needed; this would at least point the way in terms of how the code needs to flow for this to work.

Alternately, it looks like the code also uses the tempfile hack in some cases to avoid the blocking reads. An alternative would be to always use the temp files (never dev null). Then you could get the responses from the files when handling failures.

Also available in: Atom PDF