我正在寻找一种在保留本地修改的同时修改配置文件的方法。配置文件的格式类似于:
entry1: This is a local
entry2: modification.
entry3:
该文件由应由 Ansible 设置的可变数量的键(entry1、entry2、entry3 以及可能后来的 entry4 等 - 它可能上升到 100,将来甚至可能上升到 2000 左右)组成,后跟其他程序将添加到配置文件中的其他选项。
我希望 Ansible 能够向文件添加新密钥,同时保留任何现有的本地修改。
最自然的拟合似乎是 lineinfile - 但不幸的是,它只能让我选择保留本地修改(使用 backref=yes)或添加新键(backref=yes 不会添加新行)。
有什么好方法可以完成我需要的吗?
我可以在启用 lineinfile 和 backref 的情况下修改现有条目:
- lineinfile:
path: myfile.conf
regexp: "^{{ item }}: (.*)"
backref: yes
line: "{{ item }}: \1"
with_items:
- entry1
- entry2
- entry3
- entry4
但这不会将 entry4 添加到我的文件中。
或者我可以使用 backref: no
- lineinfile:
path: myfile.conf
regexp: "^{{ item }}: (.*)"
backref: no
line: "{{ item }}:"
with_items:
- entry1
- entry2
- entry3
- entry4
但这会破坏 entry1、entry2 和 entry3 的本地修改。
或者我可以更改正则表达式:
- lineinfile:
path: myfile.conf
regexp: "^"
backref: no
line: "{{ item }}:"
with_items:
- entry1
- entry2
- entry3
- entry4
但这当然会在每次运行时添加每个键。
我还研究过使用模板(但还没有找到一种简单的方法来使用它来操作现有文件)。
当然,我可以编写自己的 Python 模块,但必须有更简单的方法来做到这一点?
如果你正在修改众所周知的配置文件,你可以使用 Augeas,这个 ansible augeas 插件:https ://github.com/paluh/ansible-augeas
这是如何使用 augeas 的一个示例:
另一种选择是使用 lineinfile 命令来确保您想要的行在文件中可用:http: //docs.ansible.com/ansible/latest/lineinfile_module.html
例子:
我找到了一种方法来做到这一点。诀窍是首先使用 grep 仅查找丢失的条目。
如果文件不存在,grep 会出错,所以我首先创建文件:
copy: dest: myfile.conf content: "" force: no # set mode, owner, group to taste
现在使用 grep 仅查找丢失的项目。如果条目已经存在,Grep 将返回 0,否则返回 1。通常,返回码 1 表示 Ansible 失败。failed_when: True 改变了这一点。由于这只是检索信息而不更改任何内容,因此它永远不应报告为“已更改”,因此还需要设置 changed_when。
command: 'grep "^{{ item }}" myfile.conf' with_items: - entry1 - entry2 - entry3 - entry4 failed_when: False changed_when: False register: grep_output
Grep 会将输出生成到已注册的变量 grep_output 中。在循环中使用时,grep_output 将包含一个名为 results 的数组,其中包含循环中每个项目的一个哈希值。在该数组中,我们找到了我们需要的所有信息:返回码(称为 rc)和循环中的原始项(称为项)。
现在我们可以通过检查 rc 来只添加缺失的条目。我不确定这里是否需要正则表达式。
lineinfile: path: myfile.conf regexp: "^{{ item.item }} *(.*)" insertafter: EOF line: '{{ item.item }}' state: present when: "item.rc > 0" with_items: "{{ grep_output.results }}"