67

How would I save a registered Variable to a file? I took this from the tutorial:

- hosts: web_servers

  tasks:

     - shell: /usr/bin/foo
       register: foo_result
       ignore_errors: True

     - shell: /usr/bin/bar
       when: foo_result.rc == 5

How would I save foo_result variable to a file e.g. foo_result.log using ansible?

Maximilian Kindshofer
  • 2,753
  • 3
  • 22
  • 37
  • I am wondering if you managed to find a better solution because I do not see any solution that also take care of generating a temporary file. Having to hardcode the filename would be a problem. – sorin Apr 15 '16 at 12:01
  • You can use Variables in your dest path, too eg.: `-local_action: copy content={{var}} dest=/path/to/{{var}}.log`, but I dind't found a better solution yet / or I didn't need an other. – Maximilian Kindshofer Apr 15 '16 at 12:07
  • 2
    Possible duplicate of [Write variable to a file in Ansible](http://stackoverflow.com/questions/26638180/write-variable-to-a-file-in-ansible) – techraf Dec 23 '16 at 00:03

5 Answers5

100

Thanks to tmoschou for adding this comment to an outdated accepted answer:

As of Ansible 2.10, The documentation for ansible.builtin.copy says: 

If you need variable interpolation in copied files, use the
ansible.builtin.template module. Using a variable in the content field will
result in unpredictable output.

For more details see this and an explanation


Original answer:

You can use the copy module, with the parameter content=.

I gave the exact same answer here: Write variable to a file in Ansible

In your case, it looks like you want this variable written to a local logfile, so you could combine it with the local_action notation:

- local_action: copy content={{ foo_result }} dest=/path/to/destination/file
Ramon de la Fuente
  • 8,044
  • 3
  • 32
  • 31
  • Exactly what I was looking for. Somehow I didn't stumbled across the previouse question. Thanx for answering again – Maximilian Kindshofer Nov 04 '14 at 13:03
  • N.P. I was actually pretty happy to find the copy module supporting this, so "how do I save to file" questions tend to catch my eye :-) – Ramon de la Fuente Nov 04 '14 at 13:05
  • 1
    For some reason this doesn't work for me. I get: `FAILED! => {"msg": "Failed to get information on remote file (./the-path-to-a-local-file): sudo: a password is required\n"}`. Why does ansible think I'm referring to a remote file? – Dave Dec 19 '19 at 06:30
  • 1
    As of Ansible 2.10, The documentation for `ansible.builtin.copy` says: _If you need variable interpolation in copied files, use the `ansible.builtin.template` module. Using a variable in the `content` field will result in unpredictable output._ For more details see https://github.com/ansible/ansible/issues/50580 and an explanation at https://github.com/ansible/ansible/issues/34595#issuecomment-356091161 – tmoschou Jan 06 '21 at 01:39
  • 2
    The edit on this answer to suggest using templates is poor as it does not provide an example of how to use templates to fix the original problem – PJConnol May 10 '22 at 22:09
21

More readable way of achieving this (not a fan of single line ansible tasks)

- local_action: 
    module: copy 
    content: "{{ foo_result }}"
    dest: /path/to/destination/file
ascendants
  • 2,123
  • 3
  • 11
  • 22
bottaio
  • 4,963
  • 3
  • 19
  • 43
16

I am using Ansible 1.9.4 and this is what worked for me -

- local_action: copy content="{{ foo_result.stdout }}" dest="/path/to/destination/file"
Umesh Tyagi
  • 161
  • 1
  • 3
9

A local action will run once for each remote host (in parallel). If you want a unique file per host, make sure to put the inventory_hostname as part of the file name.

- local_action: copy content={{ foo_result }} dest=/path/to/destination/{{ inventory_hostname }}file

If you instead want a single file with all host's information, one way is to have a serial task (don't want to append in parallel) and then append to the file with a module (lineinfile is capable, or could pipe with a shell command)

- hosts: web_servers
  serial: 1
  tasks:
  - local_action: lineinfile line={{ foo_result }} path=/path/to/destination/file

Alternatively, you can add a second play/role/task to the playbook which runs against only local host. Then access the variable from each of the hosts where the registration command ran inside a template Access Other Hosts Variables Docs Template Module Docs

Chad Autry
  • 131
  • 1
  • 6
1
---
- hosts: all
  tasks:
  - name: Gather Version
    debug:
     msg: "The server Operating system is {{ ansible_distribution }} {{ ansible_distribution_major_version }}"
  - name: Write  Version
    local_action: shell echo "This is  {{ ansible_distribution }} {{ ansible_distribution_major_version }}" >> /tmp/output
Mohd Aftab
  • 19
  • 1