Ansible How to store multiple "register" in one file with one playbook

Viewed 41

Ansible store only the first output in a file

Example I have 3 hosts inside the inventory

My playbook ask for memory info. with

- name: Check memory
  hosts: all
  tasks:
    - name: Check Memory
      shell: free
      register: memory_output
    - name: save                 
      lineinfile:
        path: "mypc/test.log"
        line: "--{{ memory_output.stdout }}% "
        create: yes
      delegate_to: localhost

output write in file sometimes all the hosts memory,sometimes only the first,sometimes only the last

How i append every result from every hosts in one file. Sometimes it export all the results but not every time

2 Answers

For example, given the inventory

shell> cat hosts
test_11
test_12
test_13

declare the below variable and put it into the vars

vmstat: "{{ out.stdout|community.general.jc('vmstat') }}"

Get the free memory

    - command: vmstat
      register: out
    - set_fact:
        free_mem: "{{ vmstat.1.free_mem }}"
    - debug:
        var: free_mem

gives (abridged)

ok: [test_11] => 
  free_mem: '3434124'
ok: [test_12] => 
  free_mem: '3496908'
ok: [test_13] => 
  free_mem: '3434992'

Q: "How to store multiple 'register' in one file with one playbook."

A: Write it to the log

    - lineinfile:
        create: true
        path: /tmp/test.log
        line: >-
          {{ '%Y-%m-%d %H:%M:%S'|strftime() }}
          {{ item }}
          {{ hostvars[item].free_mem }}
      loop: "{{ ansible_play_hosts }}"
      delegate_to: localhost
      run_once: true

gives

shell> cat /tmp/test.log 
2022-09-12 13:39:48 test_11 3434124
2022-09-12 13:39:49 test_12 3496908
2022-09-12 13:39:49 test_13 3434992

Example of a complete playbook for testing

- hosts: test_11,test_12,test_13
  vars:
    vmstat: "{{ out.stdout|community.general.jc('vmstat') }}"
  tasks:
    - command: vmstat
      register: out
    - set_fact:
        free_mem: "{{ vmstat.1.free_mem }}"
    - debug:
        var: free_mem
    - lineinfile:
        create: true
        path: /tmp/test.log
        line: >-
          {{ '%Y-%m-%d %H:%M:%S'|strftime() }}
          {{ item }}
          {{ hostvars[item].free_mem }}
      loop: "{{ ansible_play_hosts }}"
      delegate_to: localhost
      run_once: true

Here's the simplest example. Assuming that you are running ansible in controller machine and you have to append the output of executing tasks in remote machines. The host list will obviously be different for you and will have all the remote machines.


- hosts: localhost
  tasks:

 ## Playbook to copy the file from controller machine to remote machine

    - name: Copy the file from controller machine to remote machine
      copy:
        src: /tmp/tmpdir/output.txt
        dest: /tmp/tmpdir/output.txt 

## Playbook to store the shell output to a variable 

    - name: Store the output of the shell command to a variable
      shell: "echo '\nHello World'"
      register: output

    - name: Print the output of the shell command
      debug:
        msg: "{{ output.stdout }}"

## Playbook to append output to a file
  
    - name: Append output to a file
      lineinfile:
        path: /tmp/tmpdir/output.txt
        line: "{{ output.stdout }}"
        create: yes        

## Playbook to copy the file from remote machine to controller machine

    - name: Copy the file from remote machine to controller machine
      fetch:
        src: /tmp/tmpdir/output.txt
        dest: /tmp/tmpdir/output.txt
        flat: yes
  • After running it the third time
╰─ ansible-playbook test.yaml 
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] *******************************************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************************
ok: [localhost]

TASK [Copy the file from controller machine to remote machine] *********************************************************************************************
ok: [localhost]

TASK [Store the output of the shell command to a variable] *************************************************************************************************
changed: [localhost]

TASK [Print the output of the shell command] ***************************************************************************************************************
ok: [localhost] => {
    "msg": "\nHello World"
}

TASK [Append output to a file] *****************************************************************************************************************************
changed: [localhost]

TASK [Copy the file from remote machine to controller machine] *********************************************************************************************
ok: [localhost]

PLAY RECAP *************************************************************************************************************************************************
localhost                  : ok=6    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   


╰─ cat output.txt
Hello World

Hello World

Hello World

So on every machine you run the controller machine will get the latest file output. We will copy the file to remote, add contents to the file and then copy it back to controller. Continue the same until all the hosts have been completed.

If you want to take the result from selective servers then the last task can be replaced by following. Replace the hostnames with required values

## Playbook to copy the file from remote machine to controller machine if the hostname maches localhost1 or localhost2

    - name: Copy the file from remote machine to controller machine if the hostname maches localhost1 or localhost2
      fetch:
        src: /tmp/tmpdir/output.txt
        dest: /tmp/tmpdir/output.txt
        flat: yes
        fail_on_missing: yes
      when: inventory_hostname == 'localhost1' or inventory_hostname == 'localhost2'
Related