本文介绍了Ansible lineinfile regexp 来管理/etc/exports的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试通过 Ansible 管理/etc/exports.

I've been hitting a wall trying to get /etc/exports managed via Ansible.

我有一个角色可以在 VM 上安装一个软件,然后我想在 NFS 服务器上为该特定 VM 添加一个条目 ot/etc/exports,以便它能够访问 NFS 共享需要.

I've got a role that installs a piece of software on a VM, and I want to then add an entry ot /etc/exports on the NFS server, for that specific VM, so it's able to access the NFS shares needed.

Lineinfile 听起来像是要走的路,但到目前为止我不知道如何正确编写它.

Lineinfile sounds like the way to go, but sofar I can't figure out how to properly write this.

我希望:

  • 如果主机在队列中,无论在哪里都不要修改
  • 如果没有 NFS 共享行,请添加 NFS 共享和主机
  • 将主机添加到共享中,以防它不在那里.

我的添加到/etc/exports"的最新一期认为应该有效,但没有,是:

The latest installment of my 'add to /etc/exports' that thought should work, but doesn't, is:

- name: Add hosts to mountpoint line
  ansible.builtin.lineinfile:
    path: /etc/exports
    line: '\1 {{ host_ip }}(root_squash,no_subtree_check)'
    regex: '^((?!{{ volume_mountpoint }}.*{{ host_ip }}\(root_squash,no_subtree_check\).*).*)$'
    backrefs: yes

但我仍然收到各种奇怪的副作用.我以前使用过反向引用等,但不知何故,这个总是让我绊倒.

but i'm still getting all kinds of weird side effects. I've used backreferences etc before, but somehow this one keeps tripping me up.

任何人都看到了什么是错的?

Anyone who sees what's gong wrong?

典型的/etc/exports 条目:

Typical /etc/exports entry:

/srv/files    172.16.0.14(rw,no_root_squash,no_subtree_check)

推荐答案

不可能在一个步骤中使用反向引用修改一行或在缺少时添加该行.要修改现有安装点,需要反向引用.例如,给定用于测试的文件

It's not possible in one step to modify a line using backreferences or add the line if missing. To modify the existing mount point the back-references are needed. For example, given the files for testing

shell> cat etc/export1
/srv/files    172.16.0.14(rw,no_root_squash,no_subtree_check)

shell> cat etc/export2
/srv/files    172.16.0.15(rw,no_root_squash,no_subtree_check)

shell> cat etc/export3
/srv/download    172.16.0.14(rw,no_root_squash,no_subtree_check)

任务

  tasks:
    - lineinfile:
        path: "etc/{{ item }}"
        regex: '^{{ mount }}(\s+)({{ ipr }})*({{ optionsr }})*(\s*)(.*)$'
        line: '{{ mount }}\g<1>{{ ip }}{{ options }} \g<5>'
        backrefs: true
      vars:
        mount: /srv/files
        ipr: '172\.16\.0\.14'
        ip: '172.16.0.14'
        optionsr: '\(.*?\)'
        options: '(root_squash,no_subtree_check)'
      loop:
        - export1
        - export2
        - export3

给予

--- before: etc/export1 (content)
+++ after: etc/export1 (content)
@@ -1 +1 @@
-/srv/files    172.16.0.14(rw,no_root_squash,no_subtree_check)
+/srv/files    172.16.0.14(root_squash,no_subtree_check) 

changed: [localhost] => (item=export1)
--- before: etc/export2 (content)
+++ after: etc/export2 (content)
@@ -1 +1 @@
-/srv/files    172.16.0.15(rw,no_root_squash,no_subtree_check)
+/srv/files    172.16.0.14(root_squash,no_subtree_check) 172.16.0.15(rw,no_root_squash,no_subtree_check)

changed: [localhost] => (item=export2)
ok: [localhost] => (item=export3)

前两个文件没问题.问题是第三个文件.该行尚未添加到文件中.引用自 backrefs

The first two files are all right. The problem is the third file. The line hasn't been added to the file. Quoting from backrefs

...如果正则表达式与文件中的任何地方都不匹配,文件将保持不变."

解释很简单.如果 regex 不匹配,则没有组.如果没有组,则无法创建.

The explanation is simple. There are no groups if the regex doesn't match. If there are no groups the line can't be created.

另一方面,引用自 正则表达式

"...如果正则表达式不匹配,将在文件中添加该行..."

因此,如果 regexp 不匹配,则不可能要求 lineinfile 添加一行,同时如果 em>regexp 匹配.如果 regexp 匹配,则需要反向引用.如果您使用反向引用,则无法添加缺失的行.

As a result, it's not possible to ask lineinfile to add a line if the regexp does not match and, at the same time, to do nothing if the regexp is matched. If the regexp is matched you need back-references. If you use back-references you can't add a missing line.

为了解决这个问题,读取文件的内容并创建字典

To solve this problem read the content of the files and create a dictionary

    - command: "cat etc/{{ item }}"
      register: result
      loop: [export1, export2, export3]
    - set_fact:
        content: "{{ dict(_files|zip(_lines)) }}"
      vars:
        _lines: "{{ result.results|map(attribute='stdout_lines')|list }}"
        _files: "{{ result.results|map(attribute='item')|list }}"

给予

  content:
    export1:
    - /srv/files    172.16.0.14(rw,no_root_squash,no_subtree_check)
    export2:
    - /srv/files    172.16.0.15(rw,no_root_squash,no_subtree_check)
    export3:
    - /srv/download    172.16.0.14(rw,no_root_squash,no_subtree_check)

现在仅在缺少时添加该行,即如果挂载点已经存在则不要替换该行

Now add the line only if missing, i.e. do not replace the line if the mount point is already there

   - lineinfile:
        path: "etc/{{ item }}"
        line: '{{ mount }} {{ ip }}{{ options }}'
      vars:
        mount: /srv/files
        ip: '172.16.0.14'
        options: '(root_squash,no_subtree_check)'
      loop: "{{ content|list }}"
      when: content[item]|select('search', mount)|length == 0

给予

skipping: [localhost] => (item=export1) 
skipping: [localhost] => (item=export2) 
--- before: etc/export3 (content)
+++ after: etc/export3 (content)
@@ -1 +1,2 @@
 /srv/download    172.16.0.14(rw,no_root_squash,no_subtree_check)
+/srv/files 172.16.0.14(root_squash,no_subtree_check)

这篇关于Ansible lineinfile regexp 来管理/etc/exports的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-25 02:35