我正在尝试取消所有挂载点,除非它们是当前列表的一部分:
excluded: ['home', 'cdrom', 'tmpfs', 'sys', 'run', 'dev', 'root']
仅 fstab 设备示例:
/- dev/mapper/vgroot-local_home
- devtmpfs
- TMPFS
应从卸载中排除/dev/mapper/vgroot-local_home
,因为子字符串home
存在于数组上,并且devtmpfs
子字符串tmpfs
也是如此。对于tmpfs
,我们有一个完美的匹配。目标是检查设备。
在检查了所有 Ansible 过滤器和 Jinja2 文档后,我没有找到解决此问题的方法。收集所有 Ansible 事实。
- name: Ensure the mountpoint is on the excluded list
ansible.posix.mount:
path: '{{ mount.device }}'
state: unmounted
when: {{ ??? }}
with_items: '{{ ??? }}'
become: true
tags: mountpoints
为了测试一个字符串是否包含 Jinja 中的子字符串,我们使用in
测试,非常类似于 Python:
"somestring" in somevariable
在您的情况下,您要检查给定字符串是否包含excluded
列表中的任何子字符串。从概念上讲,我们想要的是类似于Python表达式的东西。
if any(x in mount.device for x in excluded)
使用 Jinja 过滤器,我们需要稍微颠倒一下我们的逻辑。 我们 可以使用select
筛选器从excluded
给定目标字符串中包含的列表(例如mount.device
) 像这样:
excluded|select('in', item)
如果item
与excluded
列表中的任何内容匹配,则上述 表达式将生成一个非空列表(计算结果为true
在布尔上下文中使用时)。
在剧本中使用,它看起来像这样:
- hosts: localhost
gather_facts: false
vars:
excluded: ['home', 'cdrom', 'tmpfs', 'sys', 'run', 'dev', 'root']
mounts:
- /dev/mapper/vgroot-local_home
- devtmpfs
- tmpfs
- something/else
tasks:
- debug:
msg: "unmount {{ item }}"
when: not excluded|select('in', item)
loop: "{{ mounts }}"
上述剧本生成为输出:
TASK [debug] *******************************************************************
skipping: [localhost] => (item=/dev/mapper/vgroot-local_home)
skipping: [localhost] => (item=devtmpfs)
skipping: [localhost] => (item=tmpfs)
ok: [localhost] => (item=something/else) => {
"msg": "unmount something/else"
}
也就是说,当当前循环项包含excluded
列表中的子字符串。
假设您的目标是"卸载除以下文件系统之外的所有文件系统 设备名称包含excluded
列表中的子字符串", 你可以这样写:
- name: Unmount filesystems that aren't excluded
ansible.posix.mount:
path: '{{ mount.device }}'
state: unmounted
when: not excluded|select('in', item.device)
loop: "{{ ansible_mounts }}"
become: true
tags: mountpoints
如果您不想因为匹配路径而排除挂载的项目,例如,如果您不想排除/dev/mapper/vgroot-local_home
,因为排除列表中的dev
而迭代基本名称
- debug:
msg: "Unmount {{ item }}"
loop: "{{ mounts|map('basename') }}"
when: not excluded|select('in', item)