3

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
  • 141
  • 1
  • 3
  • 14

2 Answers2

5

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
MillerGeek
  • 3,057
  • 20
  • 23
  • No, 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 the `backrefs: true`. See the `\3` at the end of `line=` – Dominik Oct 03 '16 at 15:41
  • Updated 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. – MillerGeek Oct 03 '16 at 16:00
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
Community
  • 1
  • 1
Je.Go
  • 81
  • 1
  • 7