Ansible - Copy command output to file for multiple hosts

8.5k Views Asked by At

I run a playbook with a single command against multiple Cisco Nexus hosts. For all hosts, I want to store the output of the commands in a single file on the controller.

---
- name: Nxos
  hosts:
    - sw1
    - sw2
  gather_facts: false
  tasks:
    - name: interface counters
      cisco.nxos.nxos_command:
        commands: show interface counters errors non-zero
      register: output

However, with this method below, only 1 host's output is saved and not the others.

  - name: copy output to file
    copy: content="{{ output.stdout[0] }}" dest="output.txt"

Whereas, if I use the below method, sometimes the output is stored for all hosts while other times it only stores output for a random number of hosts

  - name: Copy output to file
    local_action:
      module: lineinfile
      path: output.txt
      line: "###{{ inventory_hostname }}### \n\n {{ output.stdout[0] }}"
      create: yes

Any idea what could be wrong or what the best way to store the output be?

Thanks

2

There are 2 best solutions below

0
larsks On BEST ANSWER

If you're always writing to a file named output.txt, then of course you only see output for a single host -- for each host, Ansible re-writes the file with new data. There's no magic that tells Ansible it should be appending to the file or something.

The easiest solution is write output to files named after each host, like this:

    - name: copy output to file
      copy:
        content: "{{ output.stdout[0] }}
        dest: "output-{{ inventory_hostname }}.txt"

If you want, you could add a task at the end of your playbook that would concatenate all those files together.

2
Vladimir Botka On

Use delegate_to: localhost instead of local_action and run the task only once. In the content, iterate special variable ansible_play_hosts_all and select the registered output from the hostvars. For example, the playbook below

- hosts: sw1,sw2
  gather_facts: false
  tasks:
    - command: "echo {{ inventory_hostname }}"
      register: output
    - name: Copy output to file
      copy:
        dest: output.txt
        content: |-
          {% for host in ansible_play_hosts_all %}
          {{ '###' }}{{ host }}{{ '###' }}
          {{ hostvars[host]['output']['stdout'] }}
          {% endfor %}
      delegate_to: localhost
      run_once: true

gives

shell> cat output.txt 
###sw1###
sw1
###sw2###
sw2