How to use the Ansible lineinfile module

Ansible lineinfile module can be used to insert a line, modify an existing line, remove an existing line or to replace a line.

Inserting a line

First, we will see how to write a line to a file, if it is not present.

We can set the path of the file to be modified using the path(>Ansible 2.3)/dest parameter. And we will set the line to be inserted using the line parameter.

The following example will write the line ‘Inserting a line in a file’  to the file ‘remote_server.txt‘. The new line will be added to the EOF. If the line already exists, then it won’t be added.

The new line will be added to the EOF. If the line already exists, then it won’t be added.

We have also set the create parameter, which says if the file is not present then create a new file. The default value for the state is present. But I am adding it anyway for clarity.

The default value for the state is present. But I am adding it anyway for clarity.

- hosts: loc
  tasks:
    - name: Ansible insert lineinfile example
      lineinfile:
        dest: /home/mdtutorials2/remote_server.txt
        line: Inserting a line in a file.
        state: present
        create: yes

Issue1:

If you get the following error,

lineinfile unsupported parameter for module: path

It is probably due to the issue with path parameter. Till ansible 2.3 this parameter was ‘dest‘. So if your ansible version is less than 2.3, then change the parameter to ‘dest‘. It should solve the issue.

Issue 2:

If the destination file does not exist, then Ansible would throw an error like below. You can either make sure the file exists in the remote file or you can set the ‘create‘ parameter to yes to solve this issue.

          Destination /home/mdtutorials2/hello.txt does not exist

Inserting a new line after/before a pattern

We don’t always want the line to be inserted to the EOF. The lineinfile module gives the option to insert the line after a pattern or before a pattern. We can use the insertafter and insertbefore parameters respectively for this.

In the below example, I want to insert the line before the ‘[defaults]’ line in ansible.cfg file. I have escaped the ‘[‘ and ‘]’ since they are special regex characters.

- name: Ansible lineinfile insert after example
  lineinfile:
    dest: /etc/ansible/ansible.cfg
    line: 'inventory = /home/fedora/inventory.ini'
    insertafter: '\[defaults\]'

If you need to insert a line before a pattern, you can use the insertbefore parameter. The following example will insert the line before the pattern ‘#library’ in ansible.cfg.

- name: Ansible lineinfile insertbefore example
  lineinfile:
    dest: /etc/ansible/ansible.cfg
    line: 'inventory = /home/mdtutorials/inventory.ini'
    insertbefore: '#library'

Removing a line

You can set the state parameter to absent, to remove the lines specified. All the occurrences of that line will be removed.

- hosts: loc
  tasks:
    - name: Ansible lineinfile remove line example
      lineinfile:
        dest: /home/mdtutorials2/remote_server.txt
        line: Removed lines.
        state: absent

Removing a line using Ansible regexp

You can also specify a regexp to remove a line. So you can say remove all lines that start with the word ‘hello’ etc.

We give the regular expression using lineinfile regexp parameter. The following example will remove all lines starting with DevOps.

- hosts: loc
  tasks:
    - name: Ansible lineinfile regexp example
      lineinfile:
        dest: /home/mdtutorials2/remote_server.txt
        regexp: '^DevOps'
        state: absent

Replacing/ Modifying a line using Regex

To modify a line we need to use the Ansible backrefs parameter along with the regexp parameter. This should be used with state=present.

If the regexp does not match any line, then the file is not changed. If the regexp matches a line/multiple lines, then the last matched line will be replaced. Also, the grouped elements in regexp are populated and can be used for modification.

In the below example we are commenting a line. The full line is captured line by placing them inside the parenthesis to ‘\1’. The ‘#\1’ replaces the line with ‘#’ followed by what was captured.

You can have multiple captures and call them by using ‘\1’, ‘\2’, ‘\3’ etc. If you need to learn more information on grouping, refer regular-expression.info.

Commenting a line with Ansible lineinfile backrefs

- name: Ansible lineinfile regexp replace example
  lineinfile:
    dest: /etc/ansible/ansible.cfg
    regexp: '(inventory = /home/fedora/inventory.ini.*)'
    line: '#\1'
    backrefs: yes

Uncommenting the line with lineinfile regexp

- name: Ansible lineinfile backrefs example
  lineinfile:
    dest: /etc/ansible/ansible.cfg
    regexp: '#(inventory = /home/fedora/inventory.ini.*)'
    line: '\1'
    backrefs: yes

We can uncomment the same line with small modifications. Here I am placing the commented line with the ‘#’ outside the grouping. So now only the portion after ‘#’ is captured in \1. And after running the script, you can see the line is uncommented.

Lineinfile multiple lines

This section is for replacing multiple lineinfile tasks with a single task and with_items. If your intention is to add multiple lines to a file, you should use the blockinfile module.

You can use with_items to loop through a list of hashes. You can specify the dest, line, regexp etc. for each task in the list. Basically, you can use it instead of writing multiple tasks.

The following example will change two files: ansible.cfg and remote_server.txt.

- hosts: loc
  tasks:
  - name: Ansible lineinfile multiple lines with_items example
    lineinfile:
      dest: "{{ item.dest }}"
      regexp: "{{ item.regexp }}"
      line: "{{ item.line }}"
      backrefs: yes
    with_items:
      - {dest: '/etc/ansible/ansible.cfg', regexp: 'config file for ansible', line: 'line changed'}
      - {dest: '/home/dinoopblogger/remote_server.txt', regexp: 'hello', line: 'world'}