Ansible "lineinfile": add new line (with PATH=) or append to existing line (with PATH=)
Solution 1
You are using the backrefs: true
flag, which prevents lineinfile from changing the file if the line does not already exist. From the docs:
Used with state=present. If set, line can contain backreferences (both positional and named) that will get populated if the regexp matches. This flag changes the operation of the module slightly; insertbefore and insertafter will be ignored, and if the regexp doesn't match anywhere in the file, the file will be left unchanged. If the regexp does match, the last matching line will be replaced by the expanded line parameter.
Since you need to create the line if it does not exist, you should use:
- name: Check whether /etc/environment contains PATH
command: grep -Fxq "PATH=" /etc/environment
register: checkpath
ignore_errors: True
changed_when: False
//updatePath.yml
- name: Add path to /etc/environment
lineinfile:
dest=/etc/environment
state=present
regexp='^PATH='
line='PATH={{ my_extra_path }}'
when: not checkpath.rc == 0
- name: update /etc/environment
lineinfile:
dest=/etc/environment
state=present
backrefs=yes
regexp='PATH=({{ my_path }}:?)?({{ my_extra_path }}:?)?(.*)'
line='PATH={{ my_extra_path }}:{{ my_extra_path }}:\3'
when: checkpath.rc == 0
Solution 2
Same idea as here : https://stackoverflow.com/a/40890850/7231194 or here : https://stackoverflow.com/a/40891927/7231194
Steps are:
- Try to replace the line.
- If replace mod change it. Cool, it's over !
- If replace mod doesn't change, add the line
Example
# Vars
- name: Set parameters
set_fact:
my_path: "/usr/bin:/usr/sbin"
my_extra_path: "/usr/extra/path"
# Tasks
- name: Try to replace the line if it exists
replace:
dest : /dir/file
replace : 'PATH={{ my_extra_path }}'
regexp : '^PATH=.*'
backup : yes
register : tryToReplace
# If the line not is here, I add it
- name: Add line
lineinfile:
state : present
dest : /dir/file
line : '{{ my_extra_path }}'
regexp : ''
insertafter: EOF
when: tryToReplace.changed == false
Dominik
Founder of azine.me: the one and only peer-to-peer IT contractor referral platform. Entrepreneur, Software Engineer, Programmer and Architect, mainly using Java, PHP & JavaScript
Updated on July 31, 2022Comments
-
Dominik almost 2 years
I am trying to replace or append a path part to the path definition in /etc/environment on a linux box.
Here's what I have:
//all.yml my_path: "/usr/bin:/usr/sbin" my_extra_path: "/usr/extra/path"
In my role-file:
//updatePath.yml - name: update /etc/environment lineinfile: dest=/etc/environment state=present backrefs=yes regexp='PATH=({{ my_path }}:?)?({{ my_extra_path }}:?)?(.*)' line='PATH={{ my_extra_path }}:{{ my_extra_path }}:\3'
Now when I run the role, it works fine updating an existing PATH-line, but not creating duplicates within the line or even duplicate lines. So far so good.
When there is no line with "PATH=" present, I would expect it to add a new one. But it doesn't.
Is my expectation wrong or where lies the problem?
-
Dominik over 7 yearsNo, removing the
backrefs: true
does not work. It creates duplicates if you re-run the ansible role and also it does not add to an existing path, but replace it. To be able to add to the path I need thebackrefs: true
. See the\3
at the end ofline=
-
MillerGeek over 7 yearsUpdated my answer to conditionally create the line if it does not exist, but otherwise update the line with backrefs. Backrefs is currently incompatible with creating a line which does not exist, so you need multiple tasks.