任务异步执行
通过 async
和 poll
可以设置异步操作和轮询。
Ansible Ad-Hoc 的异步、并发和查询
启动异步任务
[root@awx-1 ansible]# ansible localhost -B 3600 -P 5 -a "sleep 30"
localhost | CHANGED => {
"ansible_job_id": "j445703768934.50473",
"changed": true,
"cmd": [
"sleep",
"30"
],
"delta": "0:00:30.003839",
"end": "2025-04-21 23:31:02.617454",
"finished": 1,
"msg": "",
"rc": 0,
"results_file": "/root/.ansible_async/j445703768934.50473",
"start": "2025-04-21 23:30:32.613615",
"started": 1,
"stderr": "",
"stderr_lines": [],
"stdout": "",
"stdout_lines": []
}
-B
:设置超时时间-P
:轮询间隔,用于设置任务后台执行- 当值不为 0 时,任务后台跑,但是前台不会退出,定期检查结果
- 当值为 0 时,前台也会推出,后续可以用
ansible.builtin.async_status
模块查询
Ansible 默认同步执行,下表是和异步执行的对比:
特性 | 默认(前台连接) | async 模式(后台运行) |
---|---|---|
SSH 连接是否保持 | ✅ 一直保持 | ❌ 执行命令后立即断开 |
控制节点是否阻塞 | ✅ 是 | ❌ 不阻塞,立即返回 |
是否占用连接资源 | ✅ 是 | ❌ 否 |
是否适合长任务 | ❌ 容易超时、失败 | ✅ 非常适合 |
是否能中途查询状态 | ❌ 不行 | ✅ 可以用 async_status 查询 |
使用异步执行任务时,可以通过
--forks
增大并发执行的主机数量。
启动并发任务
-p
设置为 0 时,任务为并发任务。
[root@awx-1 ansible]# ansible localhost -B 3600 -P 0 -a "sleep 30"
localhost | CHANGED => {
"ansible_job_id": "j100035338039.50544",
"changed": true,
"finished": 0,
"results_file": "/root/.ansible_async/j100035338039.50544",
"started": 1
}
查询异步任务信息
当 -P
参数为 0 时,任务的完全后台执行,此时需要通过 ansible.builtin.async_status
模块查询:
ansible.builtin.async_status
的介绍在后边。
# 启动一个异步任务
[root@awx-1 ansible]# ansible localhost -B 3600 -P 0 -a "sleep 30"
localhost | CHANGED => {
"ansible_job_id": "j594674720907.50900",
"changed": true,
"finished": 0,
"results_file": "/root/.ansible_async/j594674720907.50900",
"started": 1
}
# 查询结果
[root@awx-1 ansible]# ansible localhost -m ansible.builtin.async_status -a "jid=j594674720907.50900"
localhost | CHANGED => {
"ansible_job_id": "j594674720907.50900",
"changed": true,
"cmd": [
"sleep",
"30"
],
"delta": "0:00:30.004651",
"end": "2025-04-21 23:54:24.838790",
"finished": 1,
"msg": "",
"rc": 0,
"results_file": "/root/.ansible_async/j594674720907.50900",
"start": "2025-04-21 23:53:54.834139",
"started": 1,
"stderr": "",
"stderr_lines": [],
"stdout": "",
"stdout_lines": []
}
# 清理缓存文件
[root@awx-1 ansible]# ansible localhost -m ansible.builtin.async_status -a "jid=j594674720907.50900 mode=cleanup"
localhost | SUCCESS => {
"ansible_job_id": "j594674720907.50900",
"changed": false,
"erased": "/root/.ansible_async/j594674720907.50900",
"finished": 0,
"started": 0,
"stderr": "",
"stderr_lines": [],
"stdout": "",
"stdout_lines": []
}
Playbook 的异步、并发和轮询
异步 Playbook 任务
在对应的 Play 中添加 async
和 poll
就可以设置任务异步执行(注意超时时间)
- name: sleep 30
ansible.builtin.command: sleep 30
poll: 5
async: 300
部分执行结果:
TASK [sleep 30] **********************************************************************
ASYNC POLL on localhost: jid=j503432663133.51123 started=1 finished=0
ASYNC POLL on localhost: jid=j503432663133.51123 started=1 finished=0
ASYNC POLL on localhost: jid=j503432663133.51123 started=1 finished=0
ASYNC POLL on localhost: jid=j503432663133.51123 started=1 finished=0
ASYNC POLL on localhost: jid=j503432663133.51123 started=1 finished=0
ASYNC OK on localhost: jid=j503432663133.51123
changed: [localhost]
async
没有默认值,poll
默认 15s。
并发 Playbook 任务
当 poll
为 0 时,任务为并发任务:
- name: sleep 30
ansible.builtin.command: sleep 30
poll: 0
async: 300
下边是个例子:
root@awx-1 ansible]# ansible-playbook test.yml
PLAY [test] *******************************************************************************************************************
TASK [sleep 30] ***************************************************************************************************************
changed: [localhost]
PLAY RECAP ********************************************************************************************************************
localhost : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@awx-1 ansible]# ps -ef | grep sleep
root 51246 51245 0 00:02 ? 00:00:00 sleep 30
root 51248 46905 0 00:02 pts/2 00:00:00 grep --color=auto sleep
可以看到 Playbook 已经结束了,但是 sleep 30
进程还在。
并发任务的轮询
ansible.builtin.async_status
说到并发任务的轮询就要说一下 ansible.builtin.async_status
模块,这个模块用于查询任务的状态。
参数名 | 类型 | 默认值 | 说明 |
---|---|---|---|
jid |
str |
无 | 必须参数。要查询的异步任务的 job ID(任务标识),由前面的任务结果 .ansible_async 中获取。 |
mode |
str |
status |
可选值:status 或 cleanup 。- status :默认,查询任务状态;- cleanup :用于清理任务状态文件。 |
- name: Asynchronous yum task
ansible.builtin.yum:
name: docker-io
state: present
async: 1000
poll: 0
register: yum_sleeper
- name: Wait for asynchronous job to end
ansible.builtin.async_status:
jid: '{{ yum_sleeper.ansible_job_id }}'
register: job_result
until: job_result.finished
retries: 100
delay: 10
- name: Clean up async file
ansible.builtin.async_status:
jid: '{{ yum_sleeper.ansible_job_id }}'
mode: cleanup
async
:异步超时时间poll
:查询任务结果的间隔,为 0 时不查询任务结果,即任务后台执行,前台结果直接结束register
:当前 Play 结果注册成一个变量供后续 Play 使用until
:当满足判断时,任务结束delay
:任务重试间隔retries
:任务重试次数
说一下这个模块的使用逻辑:
Asynchronous yum task
Play 用于执行docker-io
软件包的安装,超时时间为 1000s,并发执行。最后任务注册一个变量名为yum_sleeper
,这个变量有一个子变量名为ansible_job_id
,是任务的 ID;Wait for asynchronous job to end
Play 通过上一个任务注册的变量获取任务 ID,每 10s 进行一次查询,最多重试 100 次。自己注册一个变量名为job_result
,这个变量有一个子变量为finished
,当finished
为 1 时,任务执行完成;Clean up async file
Play 用于清理缓存文件。
注意
async
的值,如果值不够高,可能会造成任务超时退出。如果想为任务设置
changed_when
或creates
等选项时,需要针对ansible.builtin.async_status
设置。