The replace module in Ansible is used to search for a specified pattern in a file and replace it with a given string. This is particularly useful for making changes to configuration files, scripts, or any text-based file on remote hosts.
In this guide, we’ll explore the Ansible replace module in depth with several practical examples to demonstrate its versatility.
Table of Contents
Basic Usage
To use the replace module, you define a task in your playbook specifying the file path, the pattern to search for, and the replacement string. Here’s a basic example:
- name: Replace a string in a file
ansible.builtin.replace:
path: /etc/myconfig.conf
regexp: 'old_value'
replace: 'new_value'
backup: yes
This task searches for the string old_value in the file /etc/myconfig.conf and replaces it with new_value.
Here is a brief explanation of each parameter.
- path: The path to the file to be modified.
- regexp: The regular expression to search for within the file.
- replace: The replacement string.
- backup: Whether to create a backup of the file before making changes.
- validate: A validation command to run before making any changes.
Example 1: Updating Configuration Settings
Let’s say you have a configuration file /etc/myapp/config.ini with a setting that needs to be updated:
[database]
host = localhost
port = 3306
You want to change the host value to dbserver.example.com. Here’s how you can do it with the playbook:
- name: Update database host in configuration file
hosts: all
become: yes
tasks:
- name: Update database host in configuration file
ansible.builtin.replace:
path: /etc/myapp/config.ini
regexp: '^host = .*'
replace: 'host = dbserver.example.com'
Example 2: Backing Up Files Before Replacement
It’s often a good practice to create a backup of a file before making changes. The replace module supports this with the backup option:
Here is an example playbook for backing up a file before replacement.
- name: Update configuration with backup
hosts: all
become: yes
tasks:
- name: Update configuration with backup
ansible.builtin.replace:
path: /etc/myapp/config.ini
regexp: '^host = .*'
replace: 'host = dbserver.example.com'
backup: yes
This playbook replaces any line in /etc/myapp/config.ini that starts with host = with host = dbserver.example.com, and backs up the original file before making the change.
Example 3: Conditional Replacement Based on Validation
You can perform a replacement only if a certain condition is met by using the validate parameter. This is useful when you need to ensure that the file maintains a certain state after modification.
Suppose you want to update the server_name in an Nginx configuration file only if the file is valid after the change:
- name: Update server name in Nginx config
hosts: all
become: yes
tasks:
- name: Update server name in Nginx config
ansible.builtin.replace:
path: /etc/nginx/sites-available/default
regexp: 'server_name .*;'
replace: 'server_name newsite.example.com;'
backup: yes
validate: 'nginx -t -c %s'
This task will replace server_name with newsite.example.com and validate the Nginx configuration before applying the changes.
Example 4: Using Regular Expressions with Capture Groups
Regular expressions with capture groups can be used to retain parts of the original text while making replacements. This is particularly useful when you need to change only a portion of a matched pattern.
Suppose you have a file with entries like this:
user1 = oldpassword123
user2 = oldpassword456
And you want to update the passwords but keep the usernames:
- name: Update user passwords in config file
hosts: all
become: yes
tasks:
- name: Update user passwords in config file
ansible.builtin.replace:
path: /etc/users.conf
regexp: '^(user[0-9]+ = )oldpassword[0-9]+$'
replace: '\1newpassword789'
This playbook updates the /etc/users.conf file by replacing passwords in lines that start with user followed by a number and oldpassword with newpassword789, preserving the user prefix and number.
Example 5: Replacing Multiple Lines Using Multi-line Mode
Sometimes you need to replace or update multiple lines of text. The replace module supports multi-line replacement using the regexp parameter.
Assume you have a block of configuration that needs to be updated:
- name: Replace a multi-line block in a configuration file
hosts: all
become: yes
tasks:
- name: Replace a multi-line block in a configuration file
ansible.builtin.replace:
path: /etc/myapp/config.conf
regexp: |
section {
option1 = value1
option2 = value2
}
replace: |
section {
option1 = newvalue1
option2 = newvalue2
}
This task will replace the entire block matching the multi-line pattern.
Example 6: Replacing Text in Multiple Files
You can use the replace module in combination with the find module to replace text in multiple files. This is useful when you need to make the same change across several files in a directory.
- name: Replace text in multiple files
hosts: all
become: yes
tasks:
- name: Find all .conf files in a directory
ansible.builtin.find:
paths: /etc/myapp/
patterns: '*.conf'
register: conf_files
- name: Replace text in all found .conf files
ansible.builtin.replace:
path: "{{ item.path }}"
regexp: 'oldsetting'
replace: 'newsetting'
loop: "{{ conf_files.files }}"
This playbook uses the find module to find all .conf files in the specified directory and then uses the loop to apply the replacement to each file.
Example 7: Replacing Regular Expressions
In some cases, you may need to perform replacements based on more complex patterns using regular expressions (regex). The replace module supports regex, allowing you to specify sophisticated patterns for matching and replacing content.
Suppose you have a configuration file where URLs need to be updated, and the old URLs follow a pattern of http://example.com/resource/*. The new URLs should follow the pattern https://newdomain.com/resource/*. The wildcard * represents any subpath.
Here’s how you can use the replace module to update these URLs using regex:
- name: Replace old URLs with new URLs using regex
hosts: all
become: yes
tasks:
- name: Replace old URLs with new URLs using regex
ansible.builtin.replace:
path: /etc/app/config.conf
regexp: 'http://example\.com/resource/(.*)'
replace: 'https://newdomain.com/resource/\1'
In this example:
- regexp: The regex pattern http://example\.com/resource/(.*) matches the old URLs. The \. escapes the dot, and (.*) captures the subpath.
- replace: The https://newdomain.com/resource/\1 replaces the matched pattern, where \1 refers to the captured subpath from the regex.
Example 8: Replacing with Case Insensitivity
Sometimes, the text you want to replace may vary in case. The replace module allows for case-insensitive replacements using the ignorecase parameter. This is useful when you want to ensure that all variations of a word or phrase, regardless of case, are replaced.
Suppose you have a document where the word “Server” needs to be standardized to “server” throughout the document, regardless of how it is capitalized (e.g., “Server,” “server,” “SERVER”).
Here’s how to replace all variations of “Server” with “server”:
- name: Replace all variations of 'Server' with 'server'
hosts: all
become: yes
tasks:
- name: Replace all variations of 'Server' with 'server'
ansible.builtin.replace:
path: /etc/app/document.txt
regexp: 'Server'
replace: 'server'
ignorecase: yes
In this example:
- regexp: The pattern Server is matched in a case-insensitive manner.
- replace: All matched instances are replaced with the lowercase server.
- ignorecase: This parameter is set to yes to ignore case during the search and replace.
This task ensures that all instances of the word “Server” are standardized to “server,” regardless of their original casing in the file.
Conclusion
The replace module in Ansible is a versatile tool for modifying file contents on remote systems. By understanding its parameters and capabilities, you can perform a wide range of text replacements in your automation tasks.