<p>[Converting my comment to an answer]</p>

<p>One way to do it would be to write the logs to some external file, and then having a task after it which makes use of failed_when condition, and remove the log file, if the previous task was successful.</p>

<p>Something like this should help you.</p>

<pre><code> - name: Run Py script
      command: &lt;&gt;.py  &gt; &lt;&gt;.log
      become: yes
      register: PyScript
      ignore_errors: True

    - name: PyScript on success
      command: rm &lt;&gt;.log
      when: PyScript|succeeded
</code></pre>

<p>Note: This might not be the best way to handle your problem. But, this was a hack which helped me do my logging and monitoring.</p>

CC BY-SA 3.0
2017-06-06T13:43:02.083Z
I'd go one further and say you could keep your command writing to stdout/stderr then just dump them out as a response to a failure. So, as an example in your above example if you did want to halt execution in the event of a failure then using a fail task to just output the stdout and stderr registered in PyScript when the rc != 0 would seem a more holistic solution. If you use ansibles inbuilt mechanisms then if you have ansible logging set up on a control server, as an example, then that control server would log the failure in the ansible log. Which *I* think would be the correct place for it
hvindin
CC BY-SA 3.0
2017-06-06T10:29:14.870Z
2017-06-06T10:36:39.897Z
2017-06-06T10:36:39.897Z
Dawny33
<p>I think that all you need to do is to register the output of every command you need (store it in a variable) and then simply dump the variable in a file. That way you can review it later. </p>

<pre><code>tasks:
  - name: Dump all vars
    action: template src=templates/dumpall.j2 dest=/tmp/ansible.all
</code></pre>

<p>Then in dumpall.j2:</p>

<pre><code>Module Variables ("vars"):
--------------------------------
{{ vars | to_nice_json }} 

Environment Variables ("environment"):
--------------------------------
{{ environment | to_nice_json }} 

GROUP NAMES Variables ("group_names"):
--------------------------------
{{ group_names | to_nice_json }}

GROUPS Variables ("groups"):
--------------------------------
{{ groups | to_nice_json }}

HOST Variables ("hostvars"):
--------------------------------
{{ hostvars | to_nice_json }} 
</code></pre>

<p>The example I'm using is from <a href="https://coderwall.com/p/13lh6w/dump-all-variables" rel="nofollow noreferrer">here</a></p>

CC BY-SA 3.0
2017-06-05T07:20:17.617Z
2017-06-05T07:27:49.990Z
2017-06-05T07:27:49.990Z
13dimitar
<p>I solved this by adding </p>

<pre><code>ignore_errors: true
register: results
</code></pre>

<p>to the no_log-task. This makes ansible continue to the next task, even when the task fails. Then for the next task define a debug task, which always fails and outputs the registered variable, but only runs when the previous task failed:</p>

<pre><code>- name: Error output
  debug:
     var: results
  failed_when: true
  when:
     results is failed
</code></pre>

<p>So even with no_log: true, this will make ansible display the output of the failed task.
This solution is not logging it to a file as requested but fullfils your need to 'see the log when failed' , and of course, you can redirect or use tee to output the full ansible output to a file, which will, with this solution also contain the the log of the failed task.</p>

CC BY-SA 4.0
2019-04-29T10:15:00.350Z
2019-04-29T10:15:00.350Z
Robin Roevens
<p>What I do when I've a command to execute and wish to get the log only in case of failure is as follow (prefixed by a shell comamnd like <code>/bin/sh -c '...'</code> in case the initiator doesn't use a <code>system</code> call or execute the command directly without shell):</p>
<pre><code>command 2&gt;&amp;1 &gt; command-log.txt || cat command-log.txt
</code></pre>
<p>This will redirect error and standard output to a file and display the content of the file in case of failure only. If the command is very verbose and you don't wish to keep the log when it's ok you can go with:</p>
<pre><code>command 2&gt;&amp;1 &gt; command-log.txt &amp;&amp; rm command-log.txt || cat command-log.txt
</code></pre>
<p>Quote for <code>&amp;&amp;</code> and <code>||</code> usage from <a href="http://heirloom.sourceforge.net/sh/sh.1.html" rel="nofollow noreferrer">sh manpage</a>:</p>
<blockquote>
<p>The symbol &amp;&amp; (||) causes the list following to be executed only if
the preceding pipeline returns a zero (non zero) value.</p>
</blockquote>
<p>That's probably not the most idiomatic way to do it with ansible but has the advantage of being very portable with any configuration management system giving the ability to display command stdout.</p>

CC BY-SA 4.0
2020-07-29T18:27:02.440Z
I love this answer but I think the > and the & are swapped. Do you mean 'command 2>&1...' rather than 'command 2>&1...'?
Justin Wrobel
CC BY-SA 4.0
2020-07-30T06:52:12.227Z
You're right, I probably typed it quickly at that time. Thanks for the heads up
Tensibai
CC BY-SA 4.0
2020-07-31T18:35:21.227Z
Sadly, I wasn't able to get this to work within Ansible.
Justin Wrobel
CC BY-SA 4.0
2017-06-06T14:25:58.197Z
2020-07-30T06:52:40.987Z
2020-07-30T06:52:40.987Z
Tensibai
<p>Assuming ansible properly throws errors to stderr you can capture the output of errors in any program to a file using output redirection:</p>

<p><code>some command 2&gt; error.log</code></p>

<p>However I don't think this is the case.</p>

<p>Instead you will likely want to refer to this guide to decide when errors will occur <a href="http://docs.ansible.com/ansible/playbooks_error_handling.html" rel="nofollow noreferrer">http://docs.ansible.com/ansible/playbooks_error_handling.html</a> and then grep your output for strings that indicate an error before outputting to a file</p>

<p>ie. </p>

<p><code>ansible-playbook my-playbook | grep 'error' &gt; error.log</code></p>

CC BY-SA 3.0
2017-06-04T18:41:19.060Z
2017-06-04T18:41:19.060Z
yosefrow
<p>Tee will be a very simple tool for logging, you can refer the following command.</p>

<pre><code>eric@eric-MacBookPro:~$ ansible -m ping all | tee &gt; /tmp/ansible.log
eric@eric-MacBookPro:~$ cat /tmp/ansible.log 
localhost | SUCCESS =&gt; {
    "changed": false,
    "ping": "pong"
}
</code></pre>

CC BY-SA 3.0
2017-06-03T16:13:11.063Z
1. This affects the entire run, not just one task. 2. There's no point to piping through tee if you're going to redirect its stdout to a file; that's not how you use the command. 3. If you were using tee properly, it would still output all the spam to the console, which OP doesn't want.
Xiong Chiamiov
CC BY-SA 3.0
2017-06-03T02:23:22.113Z
2017-06-04T14:59:00.820Z
2017-06-04T14:59:00.820Z
Eric Zhang
<p>I think what you're looking for might be too simply redirect stdout and street to file.</p>

<p>Typically ,     some-command  &amp;>  logfile.log </p>

<p>or some variant....</p>

CC BY-SA 3.0
2017-06-04T10:13:51.357Z
Which is only a partial answer, OP wants to see the log in case if error.
Tensibai
CC BY-SA 3.0
2017-06-04T12:01:52.833Z
I don't this is even a partial answer to this question.  It is fine for a shell script, but useless for coding in [tag:ansible].
chicks
CC BY-SA 3.0
2017-06-06T14:13:23.523Z
@chicks I think it could be a valid workaround on a 'shell' method approach within ansible (which I don't know much)
Tensibai
CC BY-SA 3.0
2017-06-04T04:45:59.363Z
2017-06-04T04:45:59.363Z
sparq
<p>One of my ansible tasks imports an Oracle database using <code>impdp</code>.</p>

<p>This generates a <em>lot</em> of output to the console so I have set <code>no_log: True</code>.</p>

<p>However, when this fails I want to see the log!</p>

<p>How can I make this particular task log to a file and not to the console?</p>

CC BY-SA 3.0
2017-06-03T16:10:30.197Z
You're using the command module?
Xiong Chiamiov
CC BY-SA 3.0
2017-06-04T14:46:47.423Z
One idea [more of a hack] would be to write the logs to some external file, and then having a task after it which makes use of `failed_when` condition, and remove the log file, if the prev. task was succesful :)
Dawny33
CC BY-SA 3.0
2017-06-04T15:00:39.240Z
Why can you see the console output during successful runs anyway? I've not seen a configuration for, nor did I think it was possible to, show stdout during a successful task execution, it should just come up [ ok: host name ]. However when an error is detected the output gets dumped to the ansible control console (and any ansible logs defined) would you mind sharing the configuration which gives you the large stdout during a regular successful run?
hvindin
CC BY-SA 3.0
2017-06-05T06:02:53.133Z
@hvindin Put in `-vvv` after the `ansible-playbook` command for getting verbose logs.
Dawny33
CC BY-SA 3.0
2017-06-05T19:52:18.860Z
Have you considered using less v's? Each one makes it all the more verbose.  Or perhaps running without verbose mode on at all, if a step fails ansible should print the entire stout/stderr/rc/etc. That causes the failure without any verbose logging.
hvindin
CC BY-SA 3.0
2017-06-06T10:29:38.760Z
@hvindin Have expanded my comment to an [answer](https://devops.stackexchange.com/a/1304/46).  Does that help?
Dawny33
CC BY-SA 3.0
2017-06-06T13:44:17.133Z
Registering a variable does seem the best logical move, see my comment on your answer for my opinions about what to do with the outputs from ansible triggered commands.
hvindin
<ansible><logging>
How Do I Log Task Output To A File?
opticyclic
# How Do I Log Task Output To A File?

(Asked by: username_0 on 2017-06-02)

One of my ansible tasks imports an Oracle database using `impdp`.

This generates a *lot* of output to the console so I have set `no_log: True`.

However, when this fails I want to see the log!

How can I make this particular task log to a file and not to the console?

**Tags:** ansible, logging

> **Comments:**
> **username_1**: You're using the command module?  
> **username_2**: One idea [more of a hack] would be to write the logs to some external file, and then having a task after it which makes use of `failed_when` condition, and remove the log file, if the prev. task was succesful :)  
> **username_3**: Why can you see the console output during successful runs anyway? I've not seen a configuration for, nor did I think it was possible to, show stdout during a successful task execution, it should just come up [ ok: host name ]. However when an error is detected the output gets dumped to the ansible control console (and any ansible logs defined) would you mind sharing the configuration which gives you the large stdout during a regular successful run?  
> **username_2**: @username_3 Put in `-vvv` after the `ansible-playbook` command for getting verbose logs.  
> **username_3**: Have you considered using less v's? Each one makes it all the more verbose.  Or perhaps running without verbose mode on at all, if a step fails ansible should print the entire stout/stderr/rc/etc. That causes the failure without any verbose logging.  
> **username_2**: @username_3 Have expanded my comment to an [answer](https://devops.stackexchange.com/a/1304/46).  Does that help?  
> **username_3**: Registering a variable does seem the best logical move, see my comment on your answer for my opinions about what to do with the outputs from ansible triggered commands.  

---

## 7 answers

### Answer by username_2 on 2017-06-06. Score: 4

[Converting my comment to an answer]
One way to do it would be to write the logs to some external file, and then having a task after it which makes use of failed_when condition, and remove the log file, if the previous task was successful.
Something like this should help you.
 - name: Run Py script
      command: <>.py  > <>.log
      become: yes
      register: PyScript
      ignore_errors: True

    - name: PyScript on success
      command: rm <>.log
      when: PyScript|succeeded

Note: This might not be the best way to handle your problem. But, this was a hack which helped me do my logging and monitoring.

> **Comments:**
> **username_3**: I'd go one further and say you could keep your command writing to stdout/stderr then just dump them out as a response to a failure. So, as an example in your above example if you did want to halt execution in the event of a failure then using a fail task to just output the stdout and stderr registered in PyScript when the rc != 0 would seem a more holistic solution. If you use ansibles inbuilt mechanisms then if you have ansible logging set up on a control server, as an example, then that control server would log the failure in the ansible log. Which *I* think would be the correct place for it  

---

### Answer by username_4 on 2017-06-05. Score: 4

I think that all you need to do is to register the output of every command you need (store it in a variable) and then simply dump the variable in a file. That way you can review it later. 
tasks:
  - name: Dump all vars
    action: template src=templates/dumpall.j2 dest=/tmp/ansible.all

Then in dumpall.j2:
Module Variables ("vars"):
--------------------------------
{{ vars | to_nice_json }} 

Environment Variables ("environment"):
--------------------------------
{{ environment | to_nice_json }} 

GROUP NAMES Variables ("group_names"):
--------------------------------
{{ group_names | to_nice_json }}

GROUPS Variables ("groups"):
--------------------------------
{{ groups | to_nice_json }}

HOST Variables ("hostvars"):
--------------------------------
{{ hostvars | to_nice_json }} 

The example I'm using is from here


---

### Answer by username_5 on 2019-04-29. Score: 3

I solved this by adding 
ignore_errors: true
register: results

to the no_log-task. This makes ansible continue to the next task, even when the task fails. Then for the next task define a debug task, which always fails and outputs the registered variable, but only runs when the previous task failed:
- name: Error output
  debug:
     var: results
  failed_when: true
  when:
     results is failed

So even with no_log: true, this will make ansible display the output of the failed task.
This solution is not logging it to a file as requested but fullfils your need to 'see the log when failed' , and of course, you can redirect or use tee to output the full ansible output to a file, which will, with this solution also contain the the log of the failed task.


---

### Answer by username_6 on 2017-06-06. Score: 2

What I do when I've a command to execute and wish to get the log only in case of failure is as follow (prefixed by a shell comamnd like /bin/sh -c '...' in case the initiator doesn't use a system call or execute the command directly without shell):
command 2>&1 > command-log.txt || cat command-log.txt

This will redirect error and standard output to a file and display the content of the file in case of failure only. If the command is very verbose and you don't wish to keep the log when it's ok you can go with:
command 2>&1 > command-log.txt && rm command-log.txt || cat command-log.txt

Quote for && and || usage from sh manpage:

The symbol && (||) causes the list following to be executed only if
the preceding pipeline returns a zero (non zero) value.

That's probably not the most idiomatic way to do it with ansible but has the advantage of being very portable with any configuration management system giving the ability to display command stdout.

> **Comments:**
> **username_7**: I love this answer but I think the > and the & are swapped. Do you mean 'command 2>&1...' rather than 'command 2>&1...'?  
> **username_6**: You're right, I probably typed it quickly at that time. Thanks for the heads up  
> **username_7**: Sadly, I wasn't able to get this to work within Ansible.  

---

### Answer by username_8 on 2017-06-04. Score: 0

Assuming ansible properly throws errors to stderr you can capture the output of errors in any program to a file using output redirection:

`some command 2> error.log`

However I don't think this is the case.

Instead you will likely want to refer to this guide to decide when errors will occur <http://docs.ansible.com/ansible/playbooks_error_handling.html> and then grep your output for strings that indicate an error before outputting to a file

ie.

`ansible-playbook my-playbook | grep 'error' > error.log`


---

### Answer by username_9 on 2017-06-03. Score: -2

Tee will be a very simple tool for logging, you can refer the following command.
eric@eric-MacBookPro:~$ ansible -m ping all | tee > /tmp/ansible.log
eric@eric-MacBookPro:~$ cat /tmp/ansible.log 
localhost | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

> **Comments:**
> **username_1**: 1. This affects the entire run, not just one task. 2. There's no point to piping through tee if you're going to redirect its stdout to a file; that's not how you use the command. 3. If you were using tee properly, it would still output all the spam to the console, which OP doesn't want.  

---

### Answer by username_10 on 2017-06-04. Score: -2

I think what you're looking for might be too simply redirect stdout and street to file.

Typically , some-command &> logfile.log

or some variant....

> **Comments:**
> **username_6**: Which is only a partial answer, OP wants to see the log in case if error.  
> **username_11**: I don't this is even a partial answer to this question.  It is fine for a shell script, but useless for coding in [tag:ansible].  
> **username_6**: @username_11 I think it could be a valid workaround on a 'shell' method approach within ansible (which I don't know much)  

---

