0

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

Vladimir Botka
  • 58,131
  • 4
  • 32
  • 63
jays7110
  • 11
  • 2
  • 5

2 Answers2

2

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.

larsks
  • 277,717
  • 41
  • 399
  • 399
1

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
Vladimir Botka
  • 58,131
  • 4
  • 32
  • 63
  • Thanks, @Vladimir Borka. Using your proposed solution works for me. However, how can I display the output in a more human readable format rather than a one liner. I used to add stdout[0] to the copy task, and it displayed the output as it would in the Cisco CLI. But adding stdout[0] to the proposed variables isn't accepted. how should I format the task so it is displayed correctly. Thanks again – jays7110 Feb 06 '22 at 21:40
  • 1
    Hi. Please read [what comments are for](https://meta.stackexchange.com/questions/19756/how-do-comments-work). New questions go inside a new question, not in comments. Thanks. – Zeitounator Feb 07 '22 at 07:02