全部,
我一整天都在试图解决一些问题,我无法使用 shell 模块和 sed,但无法使用更原生的方式(例如替换或 lineinfile)来完成它。这就是我正在尝试做的:
我有一个文件,其中有几行,有些行以不同的字符串开头,但其他行以相同的字符串开头,这是我想要编辑的字符串,然后所有行在某个点都有一个特定的字符串,我想编辑这个字符串仅在以该特定字符串开头的行上。
这是一个更直观的例子:
顺便说一句,该文件是 /etc/fstab,看起来像这样
Aaaaa:/mount1 /mountpoint1 nfs mount-options 0 0
Aaaaa:/mount2 /mountpoint4 nfs mount-options 0 0
Bbbbbn:/mount1 /mountpoin9 nfs mount-options 0 0
正如您在本示例中看到的,我想要更改的安装选项是相同的,但是我只想编辑以 aaaa 开头的行中的选项。
有任何线索如何使用像replace或lineinfile这样的模块而不是使用shell的sed来做到这一点吗?
谢谢
更新: 让我澄清一下,aaaaa: 直到 nfs mount-options 0 0 之后的内容可以是任何内容,因为服务器上的挂载文件夹和挂载点可以是任何内容。 这也是我使用 shell 模块让它工作的方法,仍然在寻找更原生的模块而不是 shell:
- name: Inserting new mounting options
shell: sed -i '/^aaaaa/ s/mount-options/new-mount-options/g' /etc/fstab
在上面的示例中,我成功定位以 aaaaa 开头的行,并将挂载选项替换为不同的行,同时保留末尾的 0 0。
模块替换更适合用例。请参阅下面的示例。例如,让我们
dump fsck
设置为 1 1
,其中行以 Aaaaa
fstype
设置为 ext4
,其中行以 Bbbbbn
下面的任务
- replace:
path: /scratch/fstab
regexp: "{{ item.regexp }}"
replace: "{{ item.replace }}"
loop:
- regexp: '^Aaaaa(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)(.*)$'
replace: 'Aaaaa\1 \2 \3 \4 1 1'
- regexp: '^Bbbbbn(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)(.*)$'
replace: 'Bbbbbn\1 \2 ext4 \4 \5 \6'
给予
shell> cat fstab
Aaaaa:/mount1 /mountpoint1 nfs mount-options 1 1
Aaaaa:/mount2 /mountpoint4 nfs mount-options 1 1
Bbbbbn:/mount1 /mountpoin9 ext4 mount-options 0 0
注意:正则表达式很麻烦。我无法开始工作在 Python 正则表达式中捕获重复子模式。
更新
如果您可以安装jc,请以系统方式更新fstab。例如,给定用于测试的文件
shell> cat /tmp/fstab
Aaaaa:/mount1 /mountpoint1 nfs mount-options 0 0
Aaaaa:/mount2 /mountpoint4 nfs mount-options 0 0
Bbbbbn:/mount1 /mountpoin9 nfs mount-options 0 0
声明路径
fstab_path: /tmp/fstab
并将文件获取到控制器
- fetch:
src: "{{ fstab_path }}"
dest: /tmp/ansible/fstab/
声明控制器上的本地路径
fstab_local: "/tmp/ansible/fstab/{{ inventory_hostname }}{{ fstab_path }}"
并解析文件
fstab: "{{ lookup('pipe', 'cat ' ~ fstab_local ~ ' | jc --fstab') }}"
给予
fstab:
- fs_file: /mountpoint1
fs_freq: 0
fs_mntops: mount-options
fs_passno: 0
fs_spec: Aaaaa:/mount1
fs_vfstype: nfs
- fs_file: /mountpoint4
fs_freq: 0
fs_mntops: mount-options
fs_passno: 0
fs_spec: Aaaaa:/mount2
fs_vfstype: nfs
- fs_file: /mountpoin9
fs_freq: 0
fs_mntops: mount-options
fs_passno: 0
fs_spec: Bbbbbn:/mount1
fs_vfstype: nfs
声明您要更新的内容
fstab_update:
fs_spec: Aaaaa
fs_mntops: new-mount-options
并更新 fstab
fstab_new: |
{% filter from_yaml %}
{% for i in fstab %}
{% if i.fs_spec is search(fstab_update.fs_spec) %}
- {{ i|combine({'fs_mntops': fstab_update.fs_mntops}) }}
{% else %}
- {{ i }}
{% endif %}
{% endfor %}
{% endfilter %}
- debug:
msg: |
{% for i in fstab_new %}
{{ fstab_labels|map('extract', i)|join(' ') }}
{% endfor %}
给予
msg: |-
Aaaaa:/mount1 /mountpoint1 nfs new-mount-options 0 0
Aaaaa:/mount2 /mountpoint4 nfs new-mount-options 0 0
Bbbbbn:/mount1 /mountpoin9 nfs mount-options 0 0
更新文件
- copy:
dest: "{{ fstab_path }}"
content: |
{% for i in fstab_new %}
{{ fstab_labels|map('extract', i)|join(' ') }}
{% endfor %}
用于测试的完整剧本示例
- hosts: localhost
vars:
fstab_path: /tmp/fstab
fstab_local: "/tmp/ansible/fstab/{{ inventory_hostname }}{{ fstab_path }}"
fstab: "{{ lookup('pipe', 'cat ' ~ fstab_local ~ ' | jc --fstab') }}"
fstab_labels: [fs_spec, fs_file, fs_vfstype, fs_mntops, fs_freq, fs_passno]
fstab_update:
fs_spec: Aaaaa
fs_mntops: new-mount-options
fstab_new: |
{% filter from_yaml %}
{% for i in fstab %}
{% if i.fs_spec is search(fstab_update.fs_spec) %}
- {{ i|combine({'fs_mntops': fstab_update.fs_mntops}) }}
{% else %}
- {{ i }}
{% endif %}
{% endfor %}
{% endfilter %}
tasks:
- fetch:
src: "{{ fstab_path }}"
dest: /tmp/ansible/fstab/
- debug:
var: fstab
- debug:
msg: |
{% for i in fstab_new %}
{{ fstab_labels|map('extract', i)|join(' ') }}
{% endfor %}
- copy:
dest: "{{ fstab_path }}"
content: |
{% for i in fstab_new %}
{{ fstab_labels|map('extract', i)|join(' ') }}
{% endfor %}
when: not dry_run|d(true)|bool