Reputation: 8624
What is the easiest way to create an empty file using Ansible? I know I can save an empty file into the files
directory and then copy it to the remote host, but I find that somewhat unsatisfactory.
Another way is to touch a file on the remote host:
- name: create fake 'nologin' shell
file: path=/etc/nologin state=touch owner=root group=sys mode=0555
But then the file gets touched every time, showing up as a yellow line in the log, which is also unsatisfactory...
Is there any better solution to this simple problem?
Upvotes: 157
Views: 172480
Reputation: 579
Another option, using the command module:
- name: Touch file only when it does not exists
command: touch /path/to/file
args:
creates: /path/to/file
The creates
argument ensures that this action is not performed if the file exists (therefore is idempotent).
Upvotes: 31
Reputation: 179984
Something like this (using the stat
module first to gather data about it and then filtering using a conditional) should work:
- stat:
path: /etc/nologin
register: p
- name: create fake 'nologin' shell
file:
path: /etc/nologin
state: touch
owner: root
group: sys
mode: 0555
when: p.stat.exists is defined and not p.stat.exists
You might alternatively be able to leverage the changed_when
functionality.
Upvotes: 42
Reputation: 4728
The documentation of the file module says:
If
state=file
, the file will NOT be created if it does not exist, see the copy or template module if you want that behavior.
So we use the copy module, using force: false
to create a new empty file only when the file does not yet exist (if the file exists, its content is preserved).
- name: ensure file exists
copy:
content: ""
dest: /etc/nologin
force: false
group: sys
owner: root
mode: 0555
This is a declarative and elegant solution.
Upvotes: 263
Reputation: 667
Ansible file
module provide a way to touch file without modifying its time.
- name: touch a file, but do not change access time, making this task idempotent
file:
path: /etc/foo.conf
state: touch
mode: u+rw,g-wx,o-rwx
modification_time: preserve
access_time: preserve
Reference: https://docs.ansible.com/ansible/latest/modules/file_module.html
Upvotes: 37
Reputation: 21
A combination of two answers, with a twist. The code will be detected as changed, when the file is created or the permission updated.
- name: Touch again the same file, but dont change times this makes the task idempotent
file:
path: /etc/foo.conf
state: touch
mode: 0644
modification_time: preserve
access_time: preserve
changed_when: >
p.diff.before.state == "absent" or
p.diff.before.mode|default("0644") != "0644"
and a version that also corrects the owner and group and detects it as changed when it does correct these:
- name: Touch again the same file, but dont change times this makes the task idempotent
file:
path: /etc/foo.conf
state: touch
state: touch
mode: 0644
owner: root
group: root
modification_time: preserve
access_time: preserve
register: p
changed_when: >
p.diff.before.state == "absent" or
p.diff.before.mode|default("0644") != "0644" or
p.diff.before.owner|default(0) != 0 or
p.diff.before.group|default(0) != 0
Upvotes: 2
Reputation: 11
Changed if file not exists. Create empty file.
- name: create fake 'nologin' shell
file:
path: /etc/nologin
state: touch
register: p
changed_when: p.diff.before.state == "absent"
Upvotes: 1
Reputation: 1
In order to create a file in the remote machine with the ad-hoc command
ansible client -m file -a"dest=/tmp/file state=touch"
Please correct me if I am wrong
Upvotes: 0
Reputation: 1668
Turns out I don't have enough reputation to put this as a comment, which would be a more appropriate place for this:
Re. AllBlackt's answer, if you prefer Ansible's multiline format you need to adjust the quoting for state
(I spent a few minutes working this out, so hopefully this speeds someone else up),
- stat:
path: "/etc/nologin"
register: p
- name: create fake 'nologin' shell
file:
path: "/etc/nologin"
owner: root
group: sys
mode: 0555
state: '{{ "file" if p.stat.exists else "touch" }}'
Upvotes: 3
Reputation: 352
file: path=/etc/nologin state=touch
Full equivalent of touch (new in 1.4+) - use stat if you don't want to change file timestamp.
Upvotes: 11
Reputation: 720
Building on the accepted answer, if you want the file to be checked for permissions on every run, and these changed accordingly if the file exists, or just create the file if it doesn't exist, you can use the following:
- stat: path=/etc/nologin
register: p
- name: create fake 'nologin' shell
file: path=/etc/nologin
owner=root
group=sys
mode=0555
state={{ "file" if p.stat.exists else "touch"}}
Upvotes: 16