如何实现Ansible跳过已运行的async任务,重启后直接轮询原有任务?
Ansible 异步任务跨控制节点重启的实现方案
Ansible 支持实现你描述的需求,但需要额外处理异步任务 ID(job_id)的持久化——默认情况下,控制节点(笔记本)重启后会丢失之前的 job_id 记录,因此需要将 job_id 存储在远程目标节点上,确保再次运行 playbook 时可以读取并复用。
核心原理
- 远程节点上的异步任务本身不受控制节点重启影响,只要远程节点未重启,任务会持续运行;
- 实现再次识别已有任务的关键是持久化存储 async 任务的 job_id(比如写入远程节点的本地文件);
- 再次运行 playbook 时,先读取存储的 job_id,验证任务是否仍在运行,存在有效任务则直接进入轮询流程,否则启动新任务。
示例 Playbook
- name: 管理持久化异步任务 hosts: your_target_hosts gather_facts: false vars: # 远程节点上存储 job_id 的文件路径 async_job_id_file: "/tmp/ansible_async_job_id" # 异步任务超时时间(根据实际任务时长调整) async_timeout: 3600 # 轮询间隔(秒) async_poll_interval: 10 tasks: - name: 读取远程节点存储的 job_id slurp: src: "{{ async_job_id_file }}" register: stored_job_id ignore_errors: true # 文件不存在时忽略错误 - name: 解析存储的 job_id set_fact: current_job_id: "{{ stored_job_id.content | b64decode | trim }}" when: stored_job_id is succeeded - name: 验证存储的 job_id 对应的任务是否仍在运行 async_status: jid: "{{ current_job_id }}" register: job_status ignore_errors: true when: current_job_id is defined - name: 启动新的异步任务(无有效运行任务时) # 替换为你的实际长时间运行任务 shell: "sleep 300 && echo '任务执行完成'" async: "{{ async_timeout }}" poll: 0 register: new_job when: > current_job_id is not defined or job_status is failed or job_status.finished - name: 将新任务的 job_id 保存到远程节点 copy: content: "{{ new_job.ansible_job_id }}" dest: "{{ async_job_id_file }}" when: new_job is defined - name: 设置当前需要轮询的有效 job_id set_fact: target_job_id: "{{ new_job.ansible_job_id | default(current_job_id) }}" - name: 轮询异步任务状态直到完成 async_status: jid: "{{ target_job_id }}" register: job_result until: job_result.finished retries: "{{ async_timeout // async_poll_interval }}" delay: "{{ async_poll_interval }}" - name: 任务完成后清理存储的 job_id file: path: "{{ async_job_id_file }}" state: absent when: job_result.finished
关键说明
- job_id 持久化:通过
slurp和copy模块在远程节点读写 job_id 文件,避免控制节点重启后丢失记录; - 任务有效性验证:用
async_status检查存储的 job_id 是否对应仍在运行的任务,避免复用已完成的无效 ID; - 分支逻辑:仅当无有效任务时才启动新任务,否则直接复用现有任务 ID 进入轮询;
- 清理机制:任务完成后删除存储的 job_id,确保下次运行 playbook 会启动新任务。
注意事项
- 确保远程节点上的
async_job_id_file路径有写入权限,普通用户可调整为~/.ansible_async_job_id这类路径; - 如果远程节点重启,之前的异步任务会被终止,这种情况无法恢复(远程进程随节点重启消失);
- 根据实际任务时长调整
async_timeout数值,避免 Ansible 提前标记任务超时。
内容的提问来源于stack exchange,提问作者Kerrick Staley
相关产品推荐
相关产品推荐

