循环的两种风格
循环用于对一组值重复执行同一个任务。现代风格用 loop 接一个列表或列表表达式,历史风格用 with_ 系列关键字,例如按字典、按文件匹配。两者在常见场景等价,但循环控制选项与错误处理细节不同。选型先问三个问题:值是列表还是键值对、要不要索引、要不要在循环里重试或跳过失败项。
基本信息
| 现代写法 | loop 接列表或表达式 |
|---|---|
| 历史写法 | with_items、with_dict、with_fileglob 等关键字 |
| 循环控制 | 标签、索引变量、暂停间隔、每轮显示名称 |
| 返回结构 | 注册变量中保存每轮结果的列表 |
典型使用场景
- 批量创建用户、目录或文件:列表迭代最直接
- 遍历字典键值:先转成键值项列表再迭代
- 按通配匹配批量下发:文件匹配类循环,匹配在控制端求值
- 循环里需要对单轮重试:把重试参数接在任务上
- 回显太长看不清进度:用循环控制设置每轮显示名称与索引
三种迭代写法
三种迭代写法
- name: 列表迭代 # 现代写法,按列表逐项执行
ansible.builtin.user:
name: "{{ item }}"
state: present
loop:
- alice
- bob
- name: 遍历字典 # 先转键值项再分别取键与值
ansible.builtin.debug:
msg: "{{ item.key }}={{ item.value }}"
loop: "{{ ports | dict2items }}"
- name: 带索引与标签 # 便于在回显里辨认当前项
ansible.builtin.debug:
msg: "{{ idx }}:{{ item }}"
loop: [a, b]
loop_control:
index_var: idx
label: "{{ item }}"写法与适用
| 写法 | 适用 | 注意 |
|---|---|---|
| 列表迭代 | 绝大多数重复操作 | 表达式结果必须真是列表 |
| 字典转键值项后迭代 | 键值对遍历 | 需要转换过滤器 |
| 历史 with 系列 | 兼容旧 playbook | 风格统一即可,避免两代混写 |
| 文件匹配类循环 | 按路径批量处理 | 匹配在控制端求值 |
loop 的值可以是表达式,但要确认结果类型:字符串会被逐字符展开,字典需要先转换。写完先打印一次取值结果,比反复猜语法省时间。
把本来能批量完成的操作拆成循环逐项执行(例如一个个装包)会显著变慢。包、用户等模块支持一次传列表时,优先批量传递。
循环与外层结果
循环任务的结果是每轮结果的列表,注册变量后不能再当单项使用:想判断是否有任意一项失败,要按列表逐项查看或使用筛选;想拿到某一项的内容,就按下标取。把循环结果在后续任务里当单值用,是循环场景里最常见的类型错误之一。