until是轮询等待而非失败重试,反复执行任务直至条件为真或超时;retries是模块内瞬时错误的自动重试机制,仅对uri等少数模块生效;二者功能不同且互不依赖。

until 循环不是重试,是轮询等待
很多人看到 until 就以为是“失败后重试”,其实它和 retries 完全不是一回事。until 的作用是:**反复执行一个任务,直到某个条件为真(或超时)才停止**,不管每次执行是否成功。它不关心任务本身报错,只看 register 变量里你定义的判断逻辑。
典型场景是等服务端口就绪、文件生成、进程启动完成。比如用 command 检查 curl -I http://localhost:8080 返回码,直到返回 200 才继续。
-
until必须配合register和delay/retries参数使用,否则会无限循环 -
retries在until里表示最多轮询多少次,不是“失败重试次数” -
delay是每次轮询间隔秒数,别设成 0,否则可能压垮目标服务 - 如果某次执行本身失败(比如命令不存在、权限拒绝),
until会直接中断,不会等到retries耗尽
- name: wait for app port to be ready
uri:
url: http://localhost:8080/health
status_code: 200
register: health_check
until: health_check.status == 200
retries: 12
delay: 5retries 是模块级重试,只对部分模块生效
retries 不是全局配置,它只在少数支持该参数的模块中起作用,比如 uri、wait_for、get_url、pip 等。它和 until 无关,也不依赖 register —— 它是在单次任务执行内部,由模块自己控制的底层重试逻辑。
例如 uri 模块加了 retries: 3,意思是:哪怕第一次 HTTP 请求因网络抖动失败,模块内部会自动再发 2 次请求,只要有一次成功,整个任务就标为 ok;如果三次都失败,才报 failed。
-
retries对shell、command、yum等绝大多数模块无效,写了也白写 - 它不改变任务逻辑,只是让模块“多试几次”,适合解决瞬时性错误(如 DNS 解析慢、连接拒绝)
- 不能替代幂等设计:如果第一次执行已写入半截配置,重试可能造成重复或冲突
真正需要“失败后重试任务”的场景,得靠 playbook 控制流
Ansible 没有内置的“任务失败自动重试 N 次”机制。如果你希望某个关键步骤(比如上传证书、调用外部 API)失败后重试 3 次再彻底放弃,必须手动组合 ignore_errors + register + until + 条件判断。
本质是把“重试逻辑”显式写进 playbook:先执行,捕获结果;若失败,延迟后重新执行;直到成功或达到上限。
- 不要用
shell+until写 bash 风格循环,那会失去 Ansible 的状态追踪和幂等性 - 避免在
until中调用耗时长或副作用强的操作(如重启服务),容易卡住或引发雪崩 - 如果重试依赖外部状态(如第三方服务可用性),建议加
timeout参数防死等
- name: retry upload cert with backoff
shell: scp /tmp/cert.pem user@target:/etc/ssl/
register: upload_result
ignore_errors: true
until: upload_result.rc == 0
retries: 3
delay: "{{ 2 ** (ansible_loop.index0 | int) }}" # 指数退避retry_files_enabled 和 .retry 文件不是一回事
别被名字误导:retry_files_enabled 是控制 Ansible 是否生成 playbook.retry 这类主机清单文件的开关,和任务级重试完全无关。它只影响 playbook 执行失败后,是否记录哪些主机没跑完。
这个文件不会触发任何重试动作,也不会重跑失败的任务 —— 它只是个纯文本主机列表,必须手动配合 --limit @site.retry 才能定向重试。它不保存任务名、不记录错误原因、也不支持跳过已成功步骤(除非你额外加 --start-at-task)。
- 默认开启,设为
False可禁用,避免 clutter 当前目录 - 生成的
.retry文件内容不可编辑,改了也没用;它只读取主机名,不解析格式 - 如果 inventory 用了动态脚本或 YAML 锚点,
.retry文件里的主机名可能和实际不一致
真正难处理的是跨任务依赖和状态残留。比如一个任务创建了临时目录,下个任务失败退出,重试时得先清理再重来 —— 这种逻辑没法靠 until 或 retries 自动解决,得靠你写清楚 cleanup handler 或前置检查。

















