Commenting out a line with Ansible lineinfile modu

2020-06-08 19:10发布

问题:

I find it hard to believe there isn't anything that covers this use case but my search has proved fruitless.

I have a line in /etc/fstab to mount a drive that's no longer available:

//archive/Pipeline /pipeline/Archives cifs ro,credentials=/home/username/.config/cifs 0   0

What I want is to change it to

#//archive/Pipeline /pipeline/Archives cifs ro,credentials=/home/username/.config/cifs 0   0

I was using this

---
- hosts: slurm
  remote_user: root

  tasks:
    - name: Comment out pipeline archive in fstab
      lineinfile:
        dest: /etc/fstab
        regexp: '^//archive/pipeline'
        line: '#//archive/pipeline'
        state: present
      tags: update-fstab

expecting it to just insert the comment symbol (#), but instead it replaced the whole line and I ended up with

#//archive/Pipeline

is there a way to glob-capture the rest of the line or just insert the single comment char?

 regexp: '^//archive/pipeline *'
 line: '#//archive/pipeline *'

or

 regexp: '^//archive/pipeline *'
 line: '#//archive/pipeline $1'

I am trying to wrap my head around lineinfile and from what I"ve read it looks like insertafter is what I'm looking for, but "insert after" isn't what I want?

回答1:

You can use the replace module for your case:

---
- hosts: slurm
  remote_user: root

  tasks:
    - name: Comment out pipeline archive in fstab
      replace:
        dest: /etc/fstab
        regexp: '^//archive/pipeline'
        replace: '#//archive/pipeline'
      tags: update-fstab

It will replace all occurrences of the string that matches regexp.

lineinfile on the other hand, works only on one line (even if multiple matching are find in a file). It ensures a particular line is absent or present with a defined content.



回答2:

Use backrefs=yes:

Used with state=present. If set, line can contain backreferences (both positional and named) that will get populated if the regexp matches.

Like this:

- name: Comment out pipeline archive in fstab
  lineinfile:
    dest: /etc/fstab
    regexp: '(?i)^(//archive/pipeline.*)'
    line: '# \1'
    backrefs: yes
    state: present

Also note that I use (?i) option for regexp, because your search expression will never match Pipeline with capital P in the example fstab.



回答3:

This is one of the many reasons lineinfile is an antipattern. In many cases, a template is the best solution. In this case, the mount module was designed for this.

- name: Remove the pipeline archive
  mount: name="/archive/pipeline" state=absent

But "ah!" you say, you "want to preserve that the mount was in fstab at one time". You've done one better by using mount, you've preserved it in ansible.