Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if a file exists in Ansible?

Tags:

ansible

I have to check whether a file exists in /etc/. If the file exists then I have to skip the task. Here is the code I am using:

- name: checking the file exists
  command: touch file.txt
  when: $(! -s /etc/file.txt)
like image 666
E Dine Sh Avatar asked Feb 26 '16 14:02

E Dine Sh


People also ask

What does STAT do in Ansible?

In Linux, the stat command is a command-line utility that provides detailed information about filesystems or files. Ansible, considered the most diverse and popular automation tool, provides a module for fetching file and file system information as native Linux stat command.

What is Local_action in Ansible?

In an Ansible playbook, when local_action is used, Ansible will run the module work mentioned under it on the controller node. Mostly modules used with local_action are shell and command. As you can do almost all the tasks using these modules on the controller node.

How to check if a directory exists in Ansible?

Using Ansible to check if a directory exists is exactly the same as checking if a file exists. The only difference is that you use the isdir value to confirm the path to the specified directory: - name: Task name debug: msg: "The file or directory exists" when: register_name.stat.exists and register_name.stat.isdir

Which Ansible modules support the same options as the file module?

Many other modules support the same options as the file module - including ansible.builtin.copy, ansible.builtin.template, and ansible.builtin.assemble. For Windows targets, use the ansible.windows.win_file module instead.

How to create directories in Ansible using the stat module?

For more details on how to create directories in Ansible, you can refer this post. The stat module needs the path of the file, directory or symlink to be checked at the minimum. The stat module returns all the details regarding the object specified in the path parameter. We need to store this in a register.

How to return a checksum of a file in Ansible?

Whether to return a checksum of the file. Use file magic and return data about the nature of the file. this uses the 'file' utility found on most Linux/Unix systems. This will add both `mime_type` and 'charset' fields to the return, if possible. In Ansible 2.3 this option changed from 'mime' to 'get_mime' and the default changed to 'Yes'.


8 Answers

You can first check that the destination file exists or not and then make a decision based on the output of its result:

    tasks:
      - name: Check that the somefile.conf exists
        stat:
          path: /etc/file.txt
        register: stat_result

      - name: Create the file, if it doesnt exist already
        file:
          path: /etc/file.txt
          state: touch
        when: not stat_result.stat.exists
like image 78
Arbab Nazar Avatar answered Oct 06 '22 10:10

Arbab Nazar


The stat module will do this as well as obtain a lot of other information for files. From the example documentation:

- stat: path=/path/to/something
  register: p

- debug: msg="Path exists and is a directory"
  when: p.stat.isdir is defined and p.stat.isdir
like image 32
Bruce P Avatar answered Oct 06 '22 10:10

Bruce P


This can be achieved with the stat module to skip the task when file exists.

- hosts: servers
  tasks:
  - name: Ansible check file exists.
    stat:
      path: /etc/issue
    register: p
  - debug:
      msg: "File exists..."
    when: p.stat.exists
  - debug:
      msg: "File not found"
    when: p.stat.exists == False
like image 25
Rajeshkanna Avatar answered Oct 06 '22 08:10

Rajeshkanna


In general you would do this with the stat module. But the command module has the creates option which makes this very simple:

- name: touch file
  command: touch /etc/file.txt
  args:
    creates: /etc/file.txt

I guess your touch command is just an example? Best practice would be to not check anything at all and let ansible do its job - with the correct module. So if you want to ensure the file exists you would use the file module:

- name: make sure file exists
  file:
    path: /etc/file.txt
    state: touch
like image 40
udondan Avatar answered Oct 06 '22 10:10

udondan


Discovered that calling stat is slow and collects a lot of info that is not required for file existence check.
After spending some time searching for solution, i discovered following solution, which works much faster:

- raw: test -e /path/to/something && echo -n true || echo -n false
  register: file_exists

- debug: msg="Path exists"
  when: file_exists.stdout == "true"
like image 32
Vladimir Morozov Avatar answered Oct 06 '22 09:10

Vladimir Morozov


You can use Ansible stat module to register the file, and when module to apply the condition.

- name: Register file
      stat:
        path: "/tmp/test_file"
      register: file_path

- name: Create file if it doesn't exists
      file: 
        path: "/tmp/test_file"
        state: touch
      when: file_path.stat.exists == False
like image 37
Asier Gomez Avatar answered Oct 06 '22 09:10

Asier Gomez


I find it can be annoying and error prone to do a lot of these .stat.exists type checks. For example they require extra care to get check mode (--check) working.

Many answers here suggest

  • get and register
  • apply when register expression is true

However, sometimes this is a code smell so always look for better ways to use Ansible, specifically there are many advantages to using the correct module. e.g.

- name: install ntpdate
  package:
    name: ntpdate

or

- file:
    path: /etc/file.txt
    owner: root
    group: root
    mode: 0644

But when it is not possible use one module, also investigate if you can register and check the result of a previous task. e.g.

# jmeter_version: 4.0 
- name: Download Jmeter archive
  get_url:
    url: "http://archive.apache.org/dist/jmeter/binaries/apache-jmeter-{{ jmeter_version }}.tgz"
    dest: "/opt/jmeter/apache-jmeter-{{ jmeter_version }}.tgz"
    checksum: sha512:eee7d68bd1f7e7b269fabaf8f09821697165518b112a979a25c5f128c4de8ca6ad12d3b20cd9380a2b53ca52762b4c4979e564a8c2ff37196692fbd217f1e343
  register: download_result

- name: Extract apache-jmeter
  unarchive:
    src: "/opt/jmeter/apache-jmeter-{{ jmeter_version }}.tgz"
    dest: "/opt/jmeter/"
    remote_src: yes
    creates: "/opt/jmeter/apache-jmeter-{{ jmeter_version }}"
  when: download_result.state == 'file'

Note the when: but also the creates: so --check doesn't error out

I mention this because often these less-than-ideal practices come in pairs i.e. no apt/yum package so we have to 1) download and 2) unzip

Hope this helps

like image 26
KCD Avatar answered Oct 06 '22 09:10

KCD


Below is the ansible play which i used to remove the file if the file exists on OS end.

 - name: find out /etc/init.d/splunk file exists or not'
      stat:
        path: /etc/init.d/splunk
      register: splunkresult
      tags:
        - always

    - name: 'Remove splunk from init.d file if splunk already running'
      file:
        path: /etc/init.d/splunk
        state: absent
      when: splunkresult.stat.exists == true
      ignore_errors: yes
      tags:
        - always

I have used play condition as like below

when: splunkresult.stat.exists == true --> Remove the file

you can give true/false based on your requirement

when: splunkresult.stat.exists == false
when: splunkresult.stat.exists == true
like image 22
Namasivayam Chinnapillai Avatar answered Oct 06 '22 10:10

Namasivayam Chinnapillai