The Ansible lineinfile module could be the savior of your day when you want to work with files and especially modify their content on the fly, such as adding a new line in the file or updating a line in the file or replacing a line in the file when certain text is found and much more.
LineInfile has a varied set of examples and provides many parameters to do your job easily. In this post, we will see the ansible lineinfile module in action with examples.
<img src
=”https://www.middlewareinventory.com/wp-content/uploads/2019/03/photo-1461360228754-6e81c478b882-1.jpeg” alt=”Ansible lineinfile examples” /> The
Ansible lineinfile module The Ansible lineinfile module
is useful when you want to add, delete, and modify a single line in a file. You can also use conditions to match the line before modifying or removing using regular expressions. You can reuse and modify the matching line using the reverse reference parameter.
consider that you have any of the following requirements
Add a
- line when it is not already present.
- Change the port number
- SSL is enabled
- Add a new entry in
- package version when the installed version matches the regular expression
- Remove a user name from the /etc/passwd file using regex
in the configuration file Disable SSL when
the /etc/hosts file Update the
I hope this sets the context. Before continuing with the examples Something to highlight.
Ansible Lineinfile can only be used to work on a single line in a file. If you want to replace multiple lines, try replacing the module or use blockinfile if you want to insert/update/delete a block of lines in a file.
If you want to explore more about the Ansible Replace module, you can check out this post.
Ansible
Replacement Line on File – Ansible Replacement Examples | Devops Junction
Ansible lineinfile Examples We’ve gathered several examples of
ansible lineinfile
here. These are examples we’ve covered in this post. You can choose to read all or any specific example.
Validate if a line is present
- without any modification Validate
- and add if it does not exist
- If you encounter ansible lineinfile
- file if found – All instances Insert before a
- Insert after the matching line using the parameter
- insertafter Validate that changes are correct before saving
if a line is present in the file
Replace a line in a file
Delete a line from the
matching line using the insertbefore parameter
Example 1: Validate if a line is present in the file without any modification This is only to validate
whether a line is present
in the file or not. It will not modify the file regardless of the result. This is like running the quick find command
The example given below is to find out whether or not the string “LogLevel debug” is in the httpd.conf file of the remote Apache web server.
As mentioned above. No action would be taken at all
In this example, we are going to check if LogLevel is Debug and print the message If it is there or not and we will not take any action. This is being done with the help of checkmode=yes
– – name: Examples of hosts lineinfile: web tasks: – name: “Example1: Validate if a string or line is present in the file” becomes: yes become_user: root tags: example1 lineinfile: path: /etc/httpd/conf/httpd.conf line: “LogLevel debug” Status: present backup: Yes check_mode: Yes Log: example1out
Although this playbook would report that there is a change made by marking it as changed = 1, but this would not make any modifications to the file since we run the task
in check mode. Here is the
Quick ad-hoc command to check what the actual LogLevel is in the remote
httpd.conf file $ ansible web -m shell -a “grep -i LogLevel /etc/httpd/conf/httpd.conf” -i ansible_hosts mwiweb02 | CHANGED | rc=0 >> #LogLevel: Controls the number of messages logged in the error_log. LogLevel warn
It is recommended to always have the backup: yes parameter in your playbook when you are using the lineinfile. This would ensure that the file is backed up before any changes are made. This would help in case you want to back off.
Example 2: Validate
if a string or line is present in the file and add if it does not exist In the same playbook
, we just saw that if we removed the verification mode it would be a valid playbook that searches for a line and adds it when no matches are found
.
But there is a problem here the line you are mentioning to be added would be added only at the end of File or Last line. This can be controlled with insert_before and insert_before policies that will be discussed later in this article.
Now the playbook
– – name: Examples of hosts lineinfile: web tasks: – name: “Example2: Add the line if it does not exist” becomes: yes become_user: root tags: example2 lineinfile: path: /etc/httpd/conf/httpd.conf line: “LogLevel debug” status: present backup: yes register: example2out The result of this would
result in an invalid configuration file, as the entry would be appended to the end of the file.
$ ansible web -m shell -a “grep -in LogLevel /etc/httpd/conf/httpd.conf” mwiweb02 | CHANGED | rc=0 >> 185:# LogLevel: Controls the number of messages logged in the error_log. 189:LogLevel warn 354:LogLevel debug
That can be controlled with Insert after and insert before which will later in this post
.
Example3: Replace a line in a file with ansible
lineinfile.
In example2 we have seen how to add a new line with the lineinfile module. Now let’s see how to replace a line when a certain line is found.
Although you can use the ansible replacement module to replace. The Lineinfile module can also be used to replace a line.
Now, in this example, we are going to change the LogLevel debug to LogLevel Debug with a capital D
We are going to use Ansible Lineinfile with regular expressions to find a line and the line element would contain the line argument that would contain the line to replace with
Look at the following Playbook and you can easily understand it.
– – name: Examples of hosts lineinfile: web tasks: – name: “Example1: Validate if a string or line is present in the file” becomes: yes become_user: root tags: example1 lineinfile: path: /etc/httpd/conf/httpd.conf # The string to find regexp: “LogLevel warn” # The string to replace line: “LogLevel debug” Status: Current backup: Yes Record: example1out
The result of the file would be something like this
$ ansible web -m shell -a “grep -in LogLevel /etc/httpd/conf/httpd.conf” -i ansible_hosts mwiweb02 | CHANGED | rc=0 >> 185:# LogLevel: Controls the number of messages logged in the error_log. 189:Debugging
LogLevel
Would you replace all matching lines? What
if there is more than
one match if there is more than one match in the file? Ansible Lineinfile would replace only the last line that matches or is found.
If you want to replace all occurrences, you should consider using the replacement module and not lineinfile.
Example 4: Delete a line from the file, if found ( All instances )
Now I want to remove the Line LogLevel debugging that we have
added earlier, as it is in the wrong place and we also already have the LogLevel warning present in the same file.
Here is the ansible playbook to remove the line from the file and we can use some regular expressions here to find both debug and Debug
– – name: Examples of lineinfile hosts: web tasks: – name: “Example1: Validate if a string or line is present in the file” becomes: yes become_user: root tags: example1 lineinfile: path: /etc/httpd/conf/httpd.conf # String to search regexp: “LogLevel [Dd]ebug” # The status is set to Away to delete if the search line is found Status: Backup away: Yes Register: example1out
Here we are setting the status parameter to away, which will be deleted if the search is successful. The line parameter is not used because it is not needed
As mentioned above, this would remove all matching lines from the file, in other words, the entire appearance
of a search line.
Example5: Insert After a matching line using the insertafter parameter
Since we’ve taken the Apache httpd.conf file as our base file in this post, let’s take some requirements that we used to do often in Apache, which is to add a new listener.
$ ansible web -m shell -a “grep -in Listen /etc/httpd/conf/httpd.conf” -i ansible_hosts mwiweb02 | CHANGED | rc=0 >> 34:# Listen: Allows you to bind Apache to specific IP addresses and/or 38:# Change this to Listen on specific IP addresses as shown below to 41:#Listen 12.34.56.78:80 42:Listen 80
here 42 is the line number and you can see that we only have one Listen statement/directive as of now. Now, to make Apache Listen to 443 we need to add Listen 443 just below the Listen 80 Let’s see how to insert after some line using the insertafter parameter.
Here’s the playbook.
– – name: Examples of hosts lineinfile: web tasks: – name: “Example1: Validate if a string or line is present in the file” becomes: yes become_user: root tags: lineinfileexample lineinfile: path: /etc/httpd/conf/httpd.conf insertafter: “^Listen [0-9]+” line: “Listen 443” firstmatch: yes status: present register: lineinfileexample
Here you may notice that there is no REGEX parameter. we don’t need this since the insertafter parameter itself can have the search string with the command Regular Expression syntax
$ ansible web -m shell -a “grep -in Listen /etc/httpd/conf/httpd.conf” -i ansible_hosts mwiweb02 | CHANGED | rc=0 >> 34:# Listen: Allows you to bind Apache to specific IP addresses and/or 38:# Change this to Listen on specific IP addresses as shown below to 41:#Listen 12.34.56.78:80 42:Listen 80 43:Listen 443
If you look at the line numbers in the output, you can see that Listen 443 has been added just below Listen 80
When there are multiple entries the search line is present in the file. The last matching line would be considered.
Example6: Insert before a matching line using the insertbefore parameter
To test the insert before parameter, let’s take the same httpd.conf file as the base file and this time let’s update the ServerAdmin email ID from the default ServerAdmin [email protected] to Server Admin [email protected]
Before any modification
aksarav@middlewareinventory:/apps/vagrant/webinfra$ ansible web -m shell -a “grep -in ServerAdmin /etc/httpd/conf/httpd.conf” -i ansible_hosts mwiweb02 | CHANGED | rc=0 >> 83:# ServerAdmin: Your address, where problems with the server should be 87:ServerAdmin root@localhost
But we need to disable/comment out the existing ServerAdmin line and add a new entry, Here is the playbook to perform both tasks.
– – name: Examples of lineinfile hosts: Web tasks: – name: “Example6: Comment out the existing ServerAdmin line” become: yes become_user: root tags: lineinfileexample6_1 lineinfile: path: /etc/httpd/conf/httpd.conf regexp: ‘(^ServerAdmin .*)’ line: ‘# \1’ backrefs: yes state: present register: lineinfileexample6_1 – name: “Example6: Add a new ServerAdmin before the commented line” become: yes become_user: root tags: lineinfileexample6_2 lineinfile: path: /etc/httpd/conf/httpd.conf insertbefore: ‘# ServerAdmin .*’ line: “ServerAdmin [email protected]” state: present register: lineinfileexample6_2
The expected result would be something like this
. aksarav@middlewareinventory:/apps/vagrant/webinfra$ ansible web -m shell -a “grep -in ServerAdmin /etc/httpd/conf/httpd.conf” -i ansible_hosts mwiweb02 | CHANGED | rc=0 >> 83:# ServerAdmin: Your address, where problems with the server should be 87:ServerAdmin aksarav@middlewareinventory.com 88:# ServerAdmin root@localhost
You can see that line number 88 is commented out now, I was the oldest server administrator and line number 87 is our new ServerAdmin
Example 7: Validate changes before saving/committing
This is a nice feature of Ansible lineinfile that will allow you to run a shell command to validate if the modified file is really okay or if there is something wrong. Since our base file is an httpd.conf configuration file, it has a certain syntax and if we don’t adhere to it, we will leave the entire website/infrastructure at stake.
So let’s validate it before saving the file.
The Apache HTTPD server has a command to perform syntax checking on the httpd.conf file that is httpd -t
when invoked and without syntax issues. It would print the OK syntax message as given below and return a Zero Return Code, which is all Ansible cares about. Ansible relies on the return code of the validation command.
[aksarav@mwiweb02 ~]$ httpd -t OK syntax If it
is NONZERO, the changes will not be committed and the task will fail
.
Here is the playbook for updating the Apache ServerName directive
. – – name: Examples of lineinfile hosts: web tasks: – name: “Example7: Update the ServerName” become: yes become_user: root lineinfile: path: /etc/httpd/conf/httpd.conf insertafter: ‘#ServerName www.example.com:80’ line: “ServerName www.middlewareinventory.com:80” status: present # Command to validate the configuration and %s is a working copy of the validate file: “httpd -t -f %s”
Here the %s is the working copy of the actual file. Ansible would always copy the file and keep it as a working copy and make the changes and finally copy it to the Intended location and replace the original file.
Quick Ad Hoc command to validate
$ansible web -m shell -a “grep -in ServerName /etc/httpd/conf/httpd.conf” -i ansible_hosts mwiweb02 | CHANGED | rc=0 >> 92:# ServerName provides the name and port that the server uses to identify itself. 98:#ServerName www.example.com:80 99:ServerName www.middlewareinventory.com:80
You can see that the ServerName directive has been added
.
We have reached the end of the article. Hope
it
helps
Rate this article [reviews]
Best regards Sarav AK