Ansible异步启动进程telnet端口检测无rc属性报错解决
Ansible异步端口检测报错修复方案(30秒耗时达标)
问题根因
给telnet检测的shell任务同时配置async: 600和poll: 0时,Ansible不会等待任务执行完成,只会立即返回包含异步任务ID(jid)的初始结果,结果结构中仅存在ansible_job_id、started字段,不会携带实际执行结果的rc返回码,此时直接在该任务上配置until: telnetcheck.rc == 0必然触发属性不存在的报错。
正确实现逻辑
rc判断逻辑必须放在轮询异步任务状态的async_status任务上,同时调整任务并行策略保证总耗时控制在30秒内,具体修改点如下:
- 调整
main.yml的调用逻辑,不要串行循环调用internal.yml,给批量调用逻辑加异步配置让三个应用的启动、检测流程完全并行,避免串行等待累加耗时。 - 初始触发telnet检测的shell任务仅保留
async: 600、poll: 0配置,移除until、retries、delay参数,注册变量仅用于获取异步任务jid。 - 在
async_status轮询任务上配置重试、延迟和判断条件:每次轮询先确认异步任务已执行完成(telnetcheck.finished == 1),再校验返回码telnetcheck.rc == 0即为端口检测成功。 - 轮询参数设置为
delay: 3、retries: 10,总等待窗口30秒,刚好匹配启动最慢的4445端口(脚本休眠30秒后启动监听)的耗时要求,三个任务并行执行时总耗时稳定在30秒左右。
修正后Playbook代码
main.yml内容:
- name: 启动应用并检测端口 hosts: all gather_facts: no tasks: - name: 并行触发三个应用的启动检测流程 include_tasks: internal.yml loop: - { script_path: /tmp/startapp1.sh, port: 4443 } - { script_path: /tmp/startapp2.sh, port: 4445 } - { script_path: /tmp/startapp3.sh, port: 4447 } loop_control: loop_var: app_item # 关键配置:三个应用流程并行执行,不串行等待 async: 600 poll: 0
internal.yml内容:
- name: 异步启动应用常驻脚本 shell: "bash {{ app_item.script_path }}" async: 600 poll: 0 - name: 派发异步端口检测任务 shell: "timeout 3 bash -c 'echo > /dev/tcp/127.0.0.1/{{ app_item.port }}'" delegate_to: localhost async: 600 poll: 0 register: telnet_job # 此处不添加重试/判断逻辑,仅获取异步任务jid - name: 轮询检测结果直到端口通或超时 async_status: jid: "{{ telnet_job.ansible_job_id }}" register: telnetcheck until: telnetcheck.finished and telnetcheck.rc == 0 retries: 10 delay: 3 delegate_to: localhost
端口检测优先使用bash内置的
/dev/tcp能力配合timeout限制执行时长,比调用telnet命令更轻量,避免telnet进程挂起导致异步任务异常。
三个流程完全并行执行,最长等待时间为30秒,刚好覆盖所有端口的启动等待周期,满足总耗时要求。
内容的提问来源于stack exchange,提问作者Ashar
相关产品推荐
相关产品推荐

