How can I get the output of Ansible ad-hoc command in JSON, CSV or other format?
Asked Answered
B

4

8

What is the way to get the output of Ansible ad-hoc command in JSON, CSV or other format?

Burks answered 4/5, 2018 at 19:27 Comment(1)
The following Ansible ad-hoc command runs a shell command on each host, outputs JSON, and processes JSON using jq to create a Markdown report with a section for every host and a preformatted output of the command from that host. ANSIBLE_LOAD_CALLBACK_PLUGINS=1 \ ANSIBLE_STDOUT_CALLBACK=json \ ansible -i ec2.py \ 'all' \ --become --become-method=sudo \ -m shell -a "crontab -uroot -l | grep -v '^ *$'" \ | jq -r --arg TITLE "Root crontab" \ '.plays[].tasks[].hosts | to_entries | .[] | "# ($TITLE) on (.key)", (.value.stdout_lines[]|" (.)"), ""'Mauri
A
10

You could also do it through the environment variables if you do not want to modify the .cfg file, for example:

ANSIBLE_LOAD_CALLBACK_PLUGINS=true \
ANSIBLE_STDOUT_CALLBACK=json \
ansible all \
  -a "df -h /tmp"

More info on Ansible environment variables here: https://docs.ansible.com/ansible/latest/reference_appendices/config.html#environment-variables.

Arcograph answered 30/5, 2020 at 23:59 Comment(0)
C
5

In ansible.cfg add:

[defaults]
stdout_callback = json

See documentation

Instead of this:

ok: [localhost] => {
    "msg": "test"
}

You will have:

{
    "plays": [
        {
            "play": {
                "id": "720000f8-9450-586c-9a68-000000000005", 
                "name": "Json Test"
            }, 
            "tasks": [
                {
                    "hosts": {
                        "localhost": {
                            "_ansible_no_log": false, 
                            "_ansible_verbose_always": true, 
                            "changed": false, 
                            "msg": "test"
                        }
                    }, 
                    "task": {
                        "id": "720000f8-9450-586c-9a68-000000000007", 
                        "name": "Debug"
                    }
                }
            ]
        }
    ], 
    "stats": {
        "localhost": {
            "changed": 0, 
            "failures": 0, 
            "ok": 1, 
            "skipped": 0, 
            "unreachable": 0
        }
    }
}

For the following playbook:

---
- name: Json Test
  hosts: localhost
  gather_facts: False

  vars: 
    test: test


  tasks:
    - name: Debug
      debug:
        msg: "{{ test  }}"
Coexist answered 4/5, 2018 at 20:42 Comment(2)
As mentioned by @Clintm (below), you will also need to add the bin_ansible_callbacks = True directive to ~/.ansible.cfg.Miamiami
Thanks for commenting!Coexist
C
2

You need to use at least Ansible 2.5

and then set this in your ansible config:

stdout_callback = json
bin_ansible_callbacks = True

A quick note (complaint?) about ansible config... config files are not additive. If you have multiple config files (e.g. /etc/ansible/ansible.cfg and ~/.ansible.cfg) it will only take values from ~/.ansible.

Here's the config file order:

https://docs.ansible.com/ansible/latest/reference_appendices/config.html#the-configuration-file

Here's the bug:

https://github.com/ansible/ansible/issues/17914

Also here's the full callback plugin list:

https://docs.ansible.com/ansible/2.6/plugins/callback.html#plugin-list

Cioban answered 11/10, 2018 at 19:59 Comment(1)
This worked for me. I was missing the bin_ansible_callbacks = True directive in ~/.ansible.cfg. Having added that, I get JSON output from ansible(1) ad-hoc commands. Thank you.Miamiami
M
0

The following Ansible ad-hoc command runs a shell command on each host, outputs JSON, and processes JSON using jq to create a Markdown report with a section for every host, including a title showing the hostname and a body showing the preformatted output of the command from that host. Each section's title is $TITLE on $host, where TITLE is passed as an argument to jq and host is the hostname.

ANSIBLE_LOAD_CALLBACK_PLUGINS=1 \
ANSIBLE_STDOUT_CALLBACK=json \
ansible \
 'all' \
--become --become-method=sudo \
-m shell \
-a "crontab -uroot -l | grep -v '^ *$'" \
| jq -r \
--arg TITLE "Root crontab" \
  '.plays[].tasks[].hosts|to_entries|.[]| 
   "# \($TITLE) on \(.key)", ((.value.stdout_lines//[])[]|"    \(.)"), ""'
Mauri answered 22/7, 2024 at 22:23 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.