cancel
Showing results for 
Search instead for 
Did you mean: 
carbajgu
Mission Specialist
Mission Specialist
  • 445 Views

ansible / debug / serialized output / hard to read

Jump to solution

Hello community!

Question, it is a little hard for me to read the ansible-navigator output. Looks like variables are serialized and the whole text is printed in a single line with \n. Worse when it is a json/code output. Is there a best practice for avoid this behavior? Maybe a filter that beautify the var? {{x|beautify}}

For example:

- hosts: servera.lab.example.com
  become: yes
  tasks:
    - command:
        cmd: head /etc/passwd
      register: x
     - debug:
      msg: "{{x['stdout']}}"
# var: x['stdout']

this returns:

ok: [servera.lab.example.com] => {
"msg": "root:x:0:0:root:/root:/bin/bash\nbin:x:1:1:bin:/bin:/sbin/nologin\ndaemon:x:2:2:daemon:/sbin:/sbin/nologin\nadm:x:3:4:adm:/var/adm:/sbin/nologin\nlp:x:4:7:lp:/var/spool/lpd:/sbin/nologin\nsync:x:5:0:sync:/sbin:/bin/sync\nshutdown:x:6:0:shutdown:/sbin:/sbin/shutdown\nhalt:x:7:0:halt:/sbin:/sbin/halt\nmail:x:8:12:mail:/var/spool/mail:/sbin/nologin\noperator:x:11:0:operator:/root:/sbin/nologin"
}

this does not happen in the core version:

[adouser@adoocp ansible]$ ansible servera.lab.example.com -a 'head /etc/passwd'
servera.lab.example.com | CHANGED | rc=0 >>
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
[adouser@adoocp ansible]$

Labels (1)
Tags (2)
3 Solutions

Accepted Solutions
bonnevil
Starfighter Starfighter
Starfighter
  • 359 Views

Well, first off, you're comparing the ansible ad-hoc command to ansible-navigator.  Really, a better comparison would be between ansible-playbook and ansible-navigator (with -m stdout) because they have similar output modes.

You're looking at the raw JSON content of the x['stdout'] variable.  If you parsed just the contents of the variable through a JSON processor, you'd get what you're expecting.  But the CLI tools don't present those contents that way, which in theory should make it easier for you to figure out how to parse those contents with Jinja2 templates and JSON filters in your play.

For ansible, if you'd had two hosts you might have gotten something like this:

a.lab.example.com | CHANGED | rc=0 >>
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
b.lab.example.com | CHANGED | rc=0 >>
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin

...which is human-readable, mostly, but hard to tease the hosts apart.  It's definitely not raw JSON.

If you're just trying to simply view the content in the output and you don't care about some extra characters, then try using x['stdout_lines'] instead.  It'll break stdout into a list of lines, but the way the command displays the JSON output in stdout mode might be more legible as a side-effect.

For ansible-playbook or ansible-navigator -m stdout with the playbook like this:

- name: Pretty output
  hosts: all
  become: false
  gather_facts: false

  tasks:
    - name: Register a variable with the results
      ansible.builtin.command:
        cmd: head /etc/passwd
      register: x

    - name: Print the contents of the variable
      ansible.builtin.debug:
      var: x['stdout_lines']


Then you'd get output like this instead:

TASK [Print the contents of the variable] **************************************
ok: [a.lab.example.com] => {
    "x['stdout_lines']": [
        "root:x:0:0:root:/root:/bin/bash",
        "bin:x:1:1:bin:/bin:/sbin/nologin",
        "daemon:x:2:2:daemon:/sbin:/sbin/nologin",
        "adm:x:3:4:adm:/var/adm:/sbin/nologin",
        "lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin",
        "sync:x:5:0:sync:/sbin:/bin/sync",
        "shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown",
        "halt:x:7:0:halt:/sbin:/sbin/halt",
        "mail:x:8:12:mail:/var/spool/mail:/sbin/nologin",
        "operator:x:11:0:operator:/root:/sbin/nologin"
    ]
}
ok: [b.lab.example.com] => {
    "x['stdout_lines']": [
        "root:x:0:0:root:/root:/bin/bash",
        "bin:x:1:1:bin:/bin:/sbin/nologin",
        "daemon:x:2:2:daemon:/sbin:/sbin/nologin",
        "adm:x:3:4:adm:/var/adm:/sbin/nologin",
        "lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin",
        "sync:x:5:0:sync:/sbin:/bin/sync",
        "shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown",
        "halt:x:7:0:halt:/sbin:/sbin/halt",
        "mail:x:8:12:mail:/var/spool/mail:/sbin/nologin",
        "operator:x:11:0:operator:/root:/sbin/nologin"
    ]
}

If you're planning to have the playbook parse this output in some way, then that depends on what you want to do with the data.

View solution in original post

bonnevil
Starfighter Starfighter
Starfighter
  • 358 Views

Here's another option for you: use ansible-navigator in interactive mode rather than stdout mode: ansible-navigator run playbook.yml -m interactive

In that case, navigate the TUI and look at the output of the play.  It looks more readable in that mode.  I'm going to try to include some screenshots here:

Run the playbook.  You get the results of the only play in the playbook as item 0:

Screenshot From 2025-07-23 16-00-38.png Press 0 to get the results of each task in that play for each host:

Screenshot From 2025-07-23 16-00-58.png

Press 2 to get the results of the servera "Print the contents of the variable" task:

Screenshot From 2025-07-23 16-01-19.png

That might also be a reasonable way to see what you want with ansible-navigator.  This example used the variable x['stdout'] instead of x['stdout_lines'], by the way.

View solution in original post

bonnevil
Starfighter Starfighter
Starfighter
  • 356 Views

As a side note, as a style thing that first ansible.builtin.command task doesn't change anything ever by running head.  So I'd probably change that task to 

    - name: Register a variable with the results
      ansible.builtin.command:
        cmd: head /etc/passwd
      register: x
      changed_when: false

to suppress the "changed" notices that aren't real.

View solution in original post

3 Replies
bonnevil
Starfighter Starfighter
Starfighter
  • 360 Views

Well, first off, you're comparing the ansible ad-hoc command to ansible-navigator.  Really, a better comparison would be between ansible-playbook and ansible-navigator (with -m stdout) because they have similar output modes.

You're looking at the raw JSON content of the x['stdout'] variable.  If you parsed just the contents of the variable through a JSON processor, you'd get what you're expecting.  But the CLI tools don't present those contents that way, which in theory should make it easier for you to figure out how to parse those contents with Jinja2 templates and JSON filters in your play.

For ansible, if you'd had two hosts you might have gotten something like this:

a.lab.example.com | CHANGED | rc=0 >>
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
b.lab.example.com | CHANGED | rc=0 >>
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin

...which is human-readable, mostly, but hard to tease the hosts apart.  It's definitely not raw JSON.

If you're just trying to simply view the content in the output and you don't care about some extra characters, then try using x['stdout_lines'] instead.  It'll break stdout into a list of lines, but the way the command displays the JSON output in stdout mode might be more legible as a side-effect.

For ansible-playbook or ansible-navigator -m stdout with the playbook like this:

- name: Pretty output
  hosts: all
  become: false
  gather_facts: false

  tasks:
    - name: Register a variable with the results
      ansible.builtin.command:
        cmd: head /etc/passwd
      register: x

    - name: Print the contents of the variable
      ansible.builtin.debug:
      var: x['stdout_lines']


Then you'd get output like this instead:

TASK [Print the contents of the variable] **************************************
ok: [a.lab.example.com] => {
    "x['stdout_lines']": [
        "root:x:0:0:root:/root:/bin/bash",
        "bin:x:1:1:bin:/bin:/sbin/nologin",
        "daemon:x:2:2:daemon:/sbin:/sbin/nologin",
        "adm:x:3:4:adm:/var/adm:/sbin/nologin",
        "lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin",
        "sync:x:5:0:sync:/sbin:/bin/sync",
        "shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown",
        "halt:x:7:0:halt:/sbin:/sbin/halt",
        "mail:x:8:12:mail:/var/spool/mail:/sbin/nologin",
        "operator:x:11:0:operator:/root:/sbin/nologin"
    ]
}
ok: [b.lab.example.com] => {
    "x['stdout_lines']": [
        "root:x:0:0:root:/root:/bin/bash",
        "bin:x:1:1:bin:/bin:/sbin/nologin",
        "daemon:x:2:2:daemon:/sbin:/sbin/nologin",
        "adm:x:3:4:adm:/var/adm:/sbin/nologin",
        "lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin",
        "sync:x:5:0:sync:/sbin:/bin/sync",
        "shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown",
        "halt:x:7:0:halt:/sbin:/sbin/halt",
        "mail:x:8:12:mail:/var/spool/mail:/sbin/nologin",
        "operator:x:11:0:operator:/root:/sbin/nologin"
    ]
}

If you're planning to have the playbook parse this output in some way, then that depends on what you want to do with the data.

bonnevil
Starfighter Starfighter
Starfighter
  • 359 Views

Here's another option for you: use ansible-navigator in interactive mode rather than stdout mode: ansible-navigator run playbook.yml -m interactive

In that case, navigate the TUI and look at the output of the play.  It looks more readable in that mode.  I'm going to try to include some screenshots here:

Run the playbook.  You get the results of the only play in the playbook as item 0:

Screenshot From 2025-07-23 16-00-38.png Press 0 to get the results of each task in that play for each host:

Screenshot From 2025-07-23 16-00-58.png

Press 2 to get the results of the servera "Print the contents of the variable" task:

Screenshot From 2025-07-23 16-01-19.png

That might also be a reasonable way to see what you want with ansible-navigator.  This example used the variable x['stdout'] instead of x['stdout_lines'], by the way.

bonnevil
Starfighter Starfighter
Starfighter
  • 357 Views

As a side note, as a style thing that first ansible.builtin.command task doesn't change anything ever by running head.  So I'd probably change that task to 

    - name: Register a variable with the results
      ansible.builtin.command:
        cmd: head /etc/passwd
      register: x
      changed_when: false

to suppress the "changed" notices that aren't real.

Join the discussion
You must log in to join this conversation.