register 存的是结构化结果
注册变量保存的是模块返回的完整结果字典,而不是简单的字符串:里面有变更状态、成败信息、返回码,以及模块专有字段。后续任务通过它判断“上一步到底做成了什么”。理解两件事就能用对:一是它的取值时机(任务执行完之后才有),二是在循环任务里它的结构会从单条结果变成一个结果列表。
基本信息
| 赋值时机 | 任务执行结束后写入,同一任务自己的条件判断看不到本轮结果 |
|---|---|
| 结构 | 字典,含公共字段与模块专有字段;循环时为字典列表 |
| 取值优先级 | 注册变量优先级较高,会覆盖同名的普通变量定义 |
| 判断方式 | 用状态测试判断成败与变更,例如已成功、已失败、已变更 |
| 循环取值 | 通过结果列表逐项引用,列表每一项对应一次迭代 |
| 作用范围 | 注册变量属于当前主机,跨主机引用需通过主机变量间接取得 |
典型使用场景
- 按结果分支:命令输出符合预期才继续下一步
- 幂等判定:用已变更状态决定是否触发后续动作
- 收集资产信息:把查询结果汇总成报告或写入本地文件
- 循环结果汇总:批量检查多项,统一判断是否有失败项
- 失败分类:按返回码区分“正常无匹配”和“真的出错”
- 跨任务传递:把上一步产出交给下一步作为参数
取值与判断
取值与判断
- name: 执行检查并注册结果
ansible.builtin.command: /usr/local/bin/app --check
register: check_result
changed_when: false
failed_when: check_result.rc not in [0, 1] # 1 表示存在差异,不算失败
- name: 按结果分支(用状态测试而非硬编码字段)
ansible.builtin.debug:
msg: 存在待处理差异
when: check_result is succeeded and check_result.rc == 1
- name: 循环任务的注册结果是列表
ansible.builtin.stat:
path: "{{ item }}"
loop:
- /etc/app/app.conf
- /var/lib/app
register: path_check
changed_when: false
- name: 汇总判断:任一缺失即报告
ansible.builtin.debug:
msg: "缺失:{{ path_check.results | selectattr('stat.exists', 'equalto', false) | map(attribute='item') | list }}"
- name: 只在确实发生变化时触发
ansible.builtin.command: /usr/local/bin/notify.sh
when: check_result is changed判断写法对照
| 写法 | 含义 | 使用要点 |
|---|---|---|
| 状态测试(已成功/已失败/已变更/已跳过) | 对整体结果的语义判断 | 优先使用,可读性最好 |
| 返回码比较 | 命令类任务的具体退出码 | 先确认哪些码属于正常 |
| 输出内容匹配 | 按关键字判断业务结果 | 注意输出措辞随版本变化 |
| 结果列表逐项引用 | 循环任务里每一项的结果 | 配合筛选与映射表达式汇总 |
| 已定义判断 | 字段是否存在 | 用于容忍版本差异导致的字段缺失 |
同一任务上的条件判断看不到它自己本轮注册的值:条件在任务执行前求值。循环场景里这条规则尤其容易踩坑,需要基于本轮结果判断时,应把判断放到下一个任务里。
注册变量会整体写入执行输出与日志,包含命令输出与部分参数。含敏感内容的任务应配合日志抑制,或在汇总时只取必要字段,避免把原始输出整段带入记录。
写得稳的方式
优先用状态测试而不是硬编码字段名,字段缺失时用已定义判断兜底;对命令类任务明确哪些返回码算正常;对循环任务用筛选加映射一次算出汇总结果,而不是写一串逐项判断。这三条能把“任务成功但判断失效”的比例压到很低。