You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Ansible Jinja2列表特性调用hostvars返回结果不符合预期

问题:Ansible筛选NVMe磁盘时的变量解析错误

问题场景

我尝试用Ansible的hostvars筛选以nvme开头的磁盘,编写了如下任务:

- name: Output disk information
  debug:
    var: hostvars[inventory_hostname].ansible_devices.keys() | map('regex_search', 'nvme.*') | select('string') | list

实际输出

执行后返回的结果包含完整的查询语句作为键,而非直接返回列表:

ok: [cm42.ag6hq.net] => {
    "hostvars[inventory_hostname].ansible_devices.keys() | map('regex_search', 'nvme.*') | select('string') | list": [
        "nvme0n1"
    ]
}
ok: [cm43.ag6hq.net] => {
    "hostvars[inventory_hostname].ansible_devices.keys() | map('regex_search', 'nvme.*') | select('string') | list": []
}

预期输出

我期望直接得到列表内容:

ok: [cm42.ag6hq.net] => {
    [
        "nvme0n1"
    ]
}
ok: [cm43.ag6hq.net] => {
    []
}

后续报错

当我把这个查询用在with_items:中时,Ansible没有解析表达式,而是把整个字符串当作item值,导致设备找不到的错误:

failed: [cm42.ag6hq.net] (item=hostvars[inventory_hostname].ansible_devices.keys() | map('regex_search', 'nvme.*') | select('string') | list) => {"ansible_loop_var": "item", "changed": false, "item": "hostvars[inventory_hostname].ansible_devices.keys() | map('regex_search', 'nvme.*') | select('string') | list", "msg": "Device /dev/hostvars[inventory_hostname].ansible_devices.keys() | map('regex_search', 'nvme.*') | select('string') | list not found."}

错误原因与解决方法

错误原因

你犯了两个核心错误:

  1. debug模块var参数的特性:var接收的是变量名字符串,直接写带管道的表达式时,Ansible不会解析表达式,而是把整个字符串当作变量名,所以输出会以该字符串为键,对应值才是表达式的计算结果。
  2. with_items的变量解析问题:旧版with_items(现在推荐用loop)如果直接写复杂表达式,必须用{{ }}包裹触发Jinja2解析,否则会被当作纯字符串处理。

解决方法

方法1:调整debug输出,直接显示计算结果

把var换成msg,并用{{ }}包裹表达式,让Jinja2解析后输出结果:

- name: Output disk information
  debug:
    msg: "{{ hostvars[inventory_hostname].ansible_devices.keys() | map('regex_search', 'nvme.*') | select('string') | list }}"

方法2:先存变量再使用(更规范)

通过set_fact把筛选后的磁盘列表存为变量,后续任务直接引用:

- name: Get NVME disks list
  set_fact:
    nvme_disks: "{{ hostvars[inventory_hostname].ansible_devices.keys() | map('regex_search', 'nvme.*') | select('string') | list }}"

- name: Output disk information
  debug:
    var: nvme_disks

- name: Process each NVME disk
  loop: "{{ nvme_disks }}"
  debug:
    msg: "Processing device /dev/{{ item }}"

额外优化:简化筛选表达式

可以用select结合match简化逻辑,效果一致:

nvme_disks: "{{ ansible_devices.keys() | select('match', 'nvme.*') | list }}"

(注:当前任务运行在目标主机上,直接用ansible_devices即可,无需通过hostvars[inventory_hostname]引用)


内容的提问来源于stack exchange,提问作者AG6HQ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 09:07:29