一、循环与条件判断任务
1.1 循环迭代任务
基础知识点
- 核心作用:通过单个任务批量处理多个项,减少重复代码
- 基础语法:使用
loop关键字指定循环列表,内置变量item获取当前循环项 - 支持的循环类型:
- 简单值列表:遍历字符串、数字等简单值
- 字典列表:遍历多参数项,通过
item['key']获取字典内的参数
- 旧版本兼容:Ansible 2.5 之前使用
with_*系列关键字(如with_items),现已全部被loop替代,不推荐使用
重难易错点:循环 + Register 变量
-
基础用法:可将循环任务的执行结果注册到变量中,后续遍历查看每个项的输出
-
嵌套结构易错:注册后的变量为嵌套结构,不能直接遍历注册变量本身 :
注册变量(如echo_results) ├── 整体状态字段:changed、failed、msg等,描述整个循环任务的状态 └── results: 列表,存储每个循环项的单独执行结果 ├── 每个列表元素都是独立字典,包含单个循环项的完整执行信息 ├── stdout: 命令的标准输出 ├── stderr: 命令的错误输出 ├── rc: 命令返回码(0为成功) └── 其他执行细节字段 -
正确用法:
- 遍历注册变量的
results子列表:loop: "{``{ echo_results['results'] }}" - 从每个循环项的字典中,取出
stdout字段获取命令输出:item['stdout']
- 遍历注册变量的
-
错误用法:直接遍历注册变量,或直接打印
item,会导致输出整个结果字典,而非预期的命令输出。
1.2 条件任务
基础知识点
- 核心作用:仅当满足指定条件时,才执行对应任务,否则跳过
- 基础语法:使用
when关键字指定条件,when是任务的顶层参数,必须放在模块外部 - 支持的条件判断类型:
- 布尔变量判断:直接使用变量名,如
when: run_my_task - 变量存在性判断:
when: my_service is defined - 列表包含判断:
when: ansible_facts['distribution'] in supported_distros - 多条件组合:使用
and/or连接,或用条件列表(默认and),可通过括号分组
- 布尔变量判断:直接使用变量名,如
重难易错点
- 布尔变量注意:Ansible 2.12 之后,
when中的所有字符串都会被视为true,因此布尔判断必须使用真正的布尔值true/false,不能用字符串 when的位置:不能将when写到模块的参数内部,必须放在任务的顶层,否则会报错
1.3 循环与条件的组合
- 核心规则:
when会对循环中的每个项单独执行判断,符合条件的项执行任务,不符合的跳过,互不影响 - 示例:遍历主机挂载点时,仅对根分区满足空间条件时,才执行安装任务
二、处理程序(Handlers)
基础知识点
- 核心作用:处理任务修改系统后的后续操作(如修改配置后重启服务),仅当任务真的修改了系统时才执行,保证幂等性
- 工作流程:
- 普通任务通过
notify指定要触发的处理程序名称 - 仅当普通任务返回
changed状态时,才会触发处理程序的通知 - 处理程序不会立即执行,会等到所有普通任务执行完成后,统一运行
- 普通任务通过
重难运行规则
处理程序有固定的运行规则,是日常使用与考试的核心重点:
- 全局唯一:处理程序的名称在整个 Play 中全局唯一,不能重名
- 仅运行一次:无论有多少个任务通知同一个处理程序,该处理程序只会运行一次,不会重复执行
- 普通任务后运行:所有普通任务执行完成后,才会运行处理程序
- 按定义顺序运行:处理程序的运行顺序,由它在
handlers部分的定义顺序决定,与任务通知的顺序无关 - 仅 changed 触发:只有通知它的任务返回
changed状态,才会触发处理程序,ok状态不会触发 - 易错:普通
include引入的外部处理程序,无法接收当前 Play 任务的通知,因此处理程序建议直接定义在当前 Play 中,若要拆分需使用专门的import_handlers - 不能代替普通任务:处理程序仅用于处理修改后的后续操作,不能作为普通任务直接调用
三、任务失败处理
默认情况下,任务失败会终止整个 Play 的执行,Ansible 提供了多种方式调整该行为:
| 功能关键字 | 作用 | 用法 |
|---|---|---|
ignore_errors |
忽略单个任务的失败,继续执行后续任务 | 在任务中添加ignore_errors: yes |
force_handlers |
强制运行处理程序,即使后续任务失败导致 Play 终止 | 在 Play 中添加force_handlers: yes |
failed_when |
自定义任务的失败条件,即使命令返回码为 0,也可标记任务为失败 | 在任务中添加failed_when: "'错误信息' in 注册变量.stdout" |
changed_when |
自定义任务的 changed 状态,手动控制是否触发处理程序 | 在任务中添加changed_when: "'成功信息' in 注册变量.stdout" |
block |
任务分组,实现错误处理与兜底逻辑 | 分为三个部分:1. block:正常要执行的主任务2. rescue:block 任务失败时执行的补救任务3. always:无论成败都会执行的兜底任务 |
四、易错点汇总
- 循环任务的 register 变量:必须遍历
results子列表,通过item['stdout']获取命令输出,不能直接使用item when关键字的位置:必须放在任务顶层,不能写到模块参数内部- 处理程序的通知问题:不要用普通
include拆分处理程序,否则notify无法找到对应处理程序 - 处理程序的运行规则:运行顺序是定义顺序而非通知顺序,且同一个处理程序无论被通知多少次,只会运行一次
- 布尔变量判断:必须用真正的
true/false布尔值,不能用字符串做布尔判断 - 循环 + 条件的逻辑:
when是对每个循环项单独判断,不是对整个任务做一次性判断