Ansible:使用正则表达式和反向引用的 lineinfile 模块

问题描述 投票:0回答:3

我试图确保一行以 'audit=1"' 结尾。之前的状态是:

GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=vg00/lv_root rhgb 安静”

之后的状态应该是:

GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=vg00/lv_root rhgb 安静 审核=1”

使用 Ansible lineinfile 模块,如果缺少该语句,我可以添加该语句,但即使存在,重复运行也会继续附加“audit=1”。我一直在使用正则表达式和否定前瞻断言,但无法得到语法正确。

这是我的示例游戏:

  - name: grub - adjust
    lineinfile:
      path: /home/vwadmin/grub-test
      regexp: '(GRUB_CMDLINE_LINUX=.*)"(?!audit=1")'
      line: '\1 audit=1"'
      backrefs: yes
      state: present

编辑:使用和平主义者的建议我有一个可行的解决方案。确认添加我的audit=1语句(如果缺失),如果存在则不执行任何操作。

  - name: grub - check
    shell: grep -c 'audit' /etc/default/grub
    register: grub_file
    ignore_errors: true

  - name: grub - adjust
    lineinfile:
      path: /etc/default/grub
      regexp: '(GRUB_CMDLINE_LINUX=.*)"'
      line: '\1 audit=1"'
      backrefs: yes
      state: present
    when: grub_file.stdout == "0"

注意:我情不自禁地感觉到,如果没有预先步骤,我就无法让它工作,并且它不能与 check_mode 一起正常工作的原因是,在这种情况下,负向前瞻没有正确定义。据我了解,当否定前瞻成功时,正则表达式匹配应该失败,这应该导致模块不采取行动。看看 GG 上的另一个例子,我想知道根本问题是否是第一组比赛中 .* 通配符的贪婪本质。 /耸肩

ansible
3个回答
2
投票

lineinfile 正在执行其工作,即添加

line
中给出的任何内容,并且行由您的
regexp
标识。因此,无论您的设置已有什么值,它都会被新的
line
覆盖。

您可以使用两种方法:

  1. check_mode
    failed_when
    一起使用。
  2. 使用
    shell
    模块预先
    grep
    内容。

Check_Mode(虽然我无法让它工作,但其他地方都推荐它):

- name: grub - adjust
  lineinfile: 
      name: /home/vwadmin/grub-test
      regexp: '(GRUB_CMDLINE_LINUX=.*)'
      line: '\1 audit=1"'
      backrefs: yes
      state: present
   check_mode: yes
   register: presence
   failed_when: presence.changed

使用grep(这个对我来说效果很好)

- name: grub - adjust
  shell: grep -c 'audit' /home/vwadmin/grub-test 
  register: file
  ignore_errors: true

- name: Present
  debug: msg="audit is present"
  when: file.stdout != "0"

- name: Not Present
  debug: msg="audit is not present"
  when: file.stdout == "0"

0
投票

我想对

console
内核选项做类似的事情,最后得到了这个:

- name: "Ensure console kernel options are set"
  lineinfile:
    path: /etc/default/grub
    regexp: ^GRUB_CMDLINE_LINUX=\"(?P<defaults>.*?)\s*(?P<console> console=.*)?\"$
    line: GRUB_CMDLINE_LINUX="\g<defaults> {{ kernel_console }}"
    backrefs: yes
  register: grub_changed

- name: "Rebuild grub"
  command: grub2-mkconfig –o /boot/grub2/grub.cfg >/dev/null
  when:
    - grub_changed.changed

正则表达式的关键部分是

(?P<defaults>.*?)
:最后一个问号 - 这使得匹配不那么贪婪,允许选择可选的
 console=.*
,而无需不断地将另一个
console
附加到
 中的行尾line
就像你的
audit
一样。主要问题是它假设它始终是行中的最后一个(一组)选项,并且如果没有定义
console
,我总是以空格结束。但它有效!


0
投票

根据你原来的方法,我知道正则表达式,刚刚向我认识的 Ansible 用户抛出了类似以下内容(也结合了其他答案中的信息),该用户测试了它并提供了来自 ansible-lint 的反馈:

  - name: GRUB - adjust
    lineinfile:
      path: /etc/default/grub
      regexp: '^(GRUB_CMDLINE_LINUX="(?!.*\baudit=1\b)[^"]*)"$'
      line: '\1 audit=1"'
      backrefs: true
    register: grub_changed

  - name: GRUB - rebuild
    command: update-grub
    when: grub_changed.changed
© www.soinside.com 2019 - 2024. All rights reserved.