When developing ansible playbooks a common pattern is to run a command and use the output in a future task. Here is a simple example:
---
- hosts: localhost
connection: local
tasks:
- name: Check if mlocate is installed
command: dnf info mlocate
register: mlocate_output
- name: Update the locate database
command: updatedb
when: '"No matching Packages to list" in mlocate_output.stderr'
In the first task dnf will run and the output from the command will be placed in either STDOUT or STDERR. But how do you know which one? One way is to add a debug statement to your playbook:
---
- hosts: localhost
connection: local
tasks:
- name: Check if mlocate is installed
command: dnf info mlocate
register: mlocate_output
- name: Print the contents of mlocate_output
debug:
var: mlocate_output
Once the task runs you can view the stderr and stdout fields to see which of the two is populated:
TASK [Print the contents of mlocate_output]
ok: [localhost] => {
"mlocate_output": {
"changed": true,
"cmd": [
"dnf",
"info",
"mlocate"
],
"delta": "0:00:31.239145",
"end": "2017-09-27 16:39:46.919038",
"rc": 0,
"start": "2017-09-27 16:39:15.679893",
"stderr": "",
"stderr_lines": [],
"stdout": "Last metadata expiration check: 0:43:16 ago on Wed 27 Sep 2017 03:56:05 PM EDT.nInstalled PackagesnName : mlocatenVersion : 0.26nRelease : 16.fc26nArch : armv7hlnSize : 366 knSource : mlocate-0.26-16.fc26.src.rpmnRepo : @SystemnFrom repo : fedoranSummary : An utility for finding files by namenURL : https://fedorahosted.org/mlocate/nLicense : GPLv2nDescription : mlocate is a locate/updatedb implementation. It keeps a databasen : of all existing files and allows you to lookup files by name.n : n : The 'm' stands for "merging": updatedb reuses the existingn : database to avoid rereading most of the file system, which makesn : updatedb faster and does not trash the system caches as much asn : traditional locate implementations.",
.....
In the output above we can see that stderr is empty and stdout contains the output from the command. While this works fine it requires you to write a playbook and wait for it to run to get feedback. Strace can provide the same information and in most cases is a much quicker. To get the same information we can pass the command as as argument to strace and limit the output to just write(2) system calls:
$ strace -yy -s 8192 -e trace=write dnf info mlocate
.....
write(1, "Description : mlocate is a locate/updatedb implementation. It keeps a database ofn : all existing files and allows you to lookup files by name.n : n : The 'm' stands for "merging": updatedb reuses the existing database to avoidn : rereading most of the file system, which makes updatedb faster and does notn : trash the system caches as much as traditional locate implementations.", 442Description : mlocate is a locate/updatedb implementation. It keeps a database of
.....
The first argument to write(2) is the file descriptor being written to. In this case that’s STDOUT. This took less than 2 seconds to run and by observing the first argument to write you know which file descriptor the application is writing to.