Ansible Advanced Course

Variables and Jinja2

Use variables to retrieve the results of running commands

In this article, you'll learn how to capture the output of tasks executed with Ansible using the register directive and reuse that data later in your playbook. Capturing command output can be invaluable—for instance, if you want to read the contents of a file and then use that information in subsequent tasks.

Capturing Command Output with a Registered Variable

Consider the following playbook that executes a shell command to display the contents of the /etc/hosts file on each host. Initially, the playbook might be written like this without capturing the output:

- name: Check /etc/hosts file
  hosts: all
  tasks:
    - shell: cat /etc/hosts
    - debug:
        var:

When you run the playbook, the output might look similar to this:

PLAY [Check /etc/hosts file] *********************************************************

TASK [shell] **************************************************************************
changed: [web1]
changed: [web2]

PLAY RECAP ***************************************************************************
web1                       : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
web2                       : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

To capture the output, you can register the result of the shell command into a variable (for example, result). The revised playbook is shown below:

- name: Check /etc/hosts file
  hosts: all
  tasks:
    - shell: cat /etc/hosts
      register: result

    - debug:
        var: result

When executed, Ansible stores the result of the shell command into the result variable. Running the updated playbook produces debug output that looks like this:

PLAY [Check /etc/hosts file] ******************************************************************

TASK [shell] **********************************************************************************
changed: [web1]
changed: [web2]

PLAY RECAP ************************************************************************************
web1                        : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
web2                        : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Understanding the Registered Variable Content

The content stored in the result variable depends on the module that was executed. When using the shell module, the output is captured as a JSON object. For example, the result variable might contain data like the following:

{
  "ok": {
    "web2": {
      "output": {
        "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
        }
      },
      "changed": true,
      "cmd": "cat /etc/hosts",
      "failed": false,
      "rc": 0,
      "start": "2019-09-12 05:25:34.158877",
      "end": "2019-09-12 05:25:34.161974",
      "delta": "00:00:00.003097",
      "stderr": "",
      "stderr_lines": [],
      "stdout": "127.0.0.1\tlocalhost\n::1\tlocalhost ip6-localhost ip6-loopback\nfe00::0\tip6-localnet\nff00::0\tip6-mcastprefix\nff02::1\tip6-allnodes\nff02::2\tip6-allrouters\n172.20.1.101\tweb2",
      "stdout_lines": [
        "127.0.0.1\tlocalhost",
        "::1\tlocalhost ip6-localhost ip6-loopback",
        "fe00::0\tip6-localnet",
        "ff00::0\tip6-mcastprefix",
        "ff02::1\tip6-allnodes",
        "ff02::2\tip6-allrouters",
        "172.20.1.101\tweb2"
      ]
    }
  }
}

This JSON output includes several key attributes:

  • rc: The return code of the command (0 indicates success).
  • stdout and stdout_lines: The standard output from the command, which in this example is the contents of /etc/hosts.
  • stderr and stderr_lines: Any error messages generated during command execution.
  • Timestamps and delta: Timing details that show when the command started, ended, and the duration of execution.

Note

Registered variables in Ansible are host-scoped. This means the variable is only available for the specific host where the task was executed and can be accessed throughout the remainder of the playbook for that host.

Accessing Specific Elements from the Registered Variable

In many cases, you might only want to display specific parts of the command output. For instance, if you're only interested in the standard output (the file contents of /etc/hosts), you can reference result.stdout in your debug task:

- name: Check /etc/hosts file
  hosts: all
  tasks:
    - shell: cat /etc/hosts
      register: result

    - debug:
        var: result.stdout

Similarly, if you want to check the command's return code, you can reference result.rc:

- name: Check /etc/hosts file
  hosts: all
  tasks:
    - shell: cat /etc/hosts
      register: result

    - debug:
        var: result.rc

Using Registered Variables Across Multiple Plays

Since registered variables are host-scoped, you can also access them in subsequent plays within the same playbook. For example:

- name: Check /etc/hosts file
  hosts: all
  tasks:
    - shell: cat /etc/hosts
      register: result

    - debug:
        var: result.rc

- name: Second Play
  hosts: all
  tasks:
    - debug:
        var: result.rc

This approach makes it possible to carry information from one set of tasks to another throughout your playbook.

Verifying Command Output with Verbose Mode

Another convenient way to view task output is to run your playbook with the -v option. This provides verbose output without the need to add explicit debug statements. For more details, refer to the Ansible Documentation.

That’s it for now. Practice these techniques to further enhance your Ansible playbooks and streamline your automation processes.

Watch Video

Watch video content

Practice Lab

Practice lab

Previous
Variable Scope