Ansible 提供任务调试器,让你能在执行过程中修正错误。你可以直接在出错任务的上下文中检查或设置变量、更新模块参数,再使用新的变量和参数重新执行任务。这样可以查明失败原因,并继续执行 playbook。
启用调试器
调试器默认关闭。要在 playbook 执行期间进入调试器,必须先启用它。可以使用 debugger 关键字、配置文件或环境变量,也可以使用调试策略。
使用 debugger 关键字
此功能在 Ansible 2.5 中加入。debugger 可以在 play、role、block 或 task 上启用或禁用调试器,适合开发和扩展 playbook、play 及 role 时使用。对于新增或修改后的任务,启用调试器后就能在失败时直接修正问题。这个关键字接受以下五个值:
| 值 | 行为 |
|---|---|
always |
无论任务结果如何,始终进入调试器。 |
never |
无论任务结果如何,都不进入调试器。 |
on_failed |
仅在任务失败时进入调试器。 |
on_unreachable |
仅在主机无法访问时进入调试器。 |
on_skipped |
仅在任务被跳过时进入调试器。 |
debugger 的显式设置会覆盖启用或禁用调试器的全局配置。如果在多个层级设置了这个关键字,Ansible 采用粒度最细的定义。play 或 role 级定义适用于其中所有 block 和 task,除非更具体的层级指定了其他值;block 级定义覆盖 play 或 role,并适用于该 block 中的任务;task 级定义仅适用于该任务,且优先于 block、play 和 role 的定义。
关键字使用示例
在单个任务上设置:
- name: Execute a command
ansible.builtin.command: "false"
debugger: on_failed
在 play 上设置:
- name: My play
hosts: all
debugger: on_skipped
tasks:
- name: Execute a command
ansible.builtin.command: "true"
when: False
在多个层级设置:
- name: Play
hosts: all
debugger: never
tasks:
- name: Execute a command
ansible.builtin.command: "false"
debugger: on_failed
最后一个示例中,play 的值是 never,而 task 的值是 on_failed。如果任务失败,Ansible 仍会进入调试器,因为任务定义覆盖了父级 play 的定义。
使用配置文件或环境变量
这两种全局启用方式在 Ansible 2.5 中加入。可以在 ansible.cfg 或环境变量中设置任务调试器,只接受 True 与 False。设置为 True 后,Ansible 默认在任务失败时进入调试器。
要从 ansible.cfg 启用,在 [defaults] 节中加入:
[defaults]
enable_task_debugger = True
要通过环境变量启用,在运行 playbook 时传入该变量:
ANSIBLE_ENABLE_TASK_DEBUGGER=True ansible-playbook -i hosts site.yml
全局启用后,每个失败的任务都会进入调试器,除非 role、play、block 或 task 明确禁用它。如果需要更精确地控制触发条件,请使用 debugger 关键字。
使用调试策略
旧版 playbook 或 role 可能通过 strategy 启用调试器。可以在 play 级别、ansible.cfg,或通过环境变量 ANSIBLE_STRATEGY=debug 设置。例如:
- hosts: test
strategy: debug
tasks:
- name: Example task
debug:
msg: "This is a debug message"
也可以在 ansible.cfg 中配置:
[defaults]
strategy = debug
这是一种与 Ansible 2.5 之前版本相兼容的旧方法,未来版本可能移除它。
在调试器中解决错误
进入调试器后,可以使用下文列出的七个命令排查错误。下面的 playbook 定义了变量 var1,却在任务中误用了未定义的 wrong_var:
- hosts: test
debugger: on_failed
gather_facts: false
vars:
var1: value1
tasks:
- name: Use a wrong variable
ansible.builtin.ping: data={{ wrong_var }}
运行该 playbook 时,任务失败会触发调试器。在调试提示符中,可以修改模块参数或变量,然后重新运行任务。以下是官方文档提供的示例输出:
PLAY ***************************************************************************
TASK [wrong variable] **********************************************************
fatal: [192.0.2.10]: FAILED! => {"failed": true, "msg": "ERROR! 'wrong_var' is undefined"}
Debugger invoked
[192.0.2.10] TASK: wrong variable (debug)> p result._result
{'failed': True,
'msg': 'The task includes an option with an undefined variable. The error '
"was: 'wrong_var' is undefined\n"
'\n'
'The error appears to have been in '
"'playbooks/debugger.yml': line 7, "
'column 7, but may\n'
'be elsewhere in the file depending on the exact syntax problem.\n'
'\n'
'The offending line appears to be:\n'
'\n'
' tasks:\n'
' - name: wrong variable\n'
' ^ here\n'}
[192.0.2.10] TASK: wrong variable (debug)> p task.args
{u'data': u'{{ wrong_var }}'}
[192.0.2.10] TASK: wrong variable (debug)> task.args['data'] = '{{ var1 }}'
[192.0.2.10] TASK: wrong variable (debug)> p task.args
{u'data': '{{ var1 }}'}
[192.0.2.10] TASK: wrong variable (debug)> redo
ok: [192.0.2.10]
PLAY RECAP *********************************************************************
192.0.2.10 : ok=1 changed=0 unreachable=0 failed=0
将任务参数从 wrong_var 改为 var1 后,示例中的任务成功完成。
可用的调试命令
可以在调试提示符中使用以下七个命令:
| 命令 | 简写 | 作用 |
|---|---|---|
print |
p |
输出任务信息。 |
task.args[key] = value |
无 | 更新模块参数。 |
task_vars[key] = value |
无 | 更新任务变量;之后必须执行 update_task。 |
update_task |
u |
使用更新后的任务变量重新创建任务。 |
redo |
r |
重新运行任务。 |
continue |
c |
从下一个任务开始继续执行。 |
quit |
q |
退出调试器。 |
输出信息:print
print task、print task.args、print task_vars、print host 与 print result 用于输出对应的任务信息。例如:
[192.0.2.10] TASK: install package (debug)> p task
TASK: install package
[192.0.2.10] TASK: install package (debug)> p task.args
{u'name': u'{{ pkg_name }}'}
[192.0.2.10] TASK: install package (debug)> p task_vars
{u'ansible_all_ipv4_addresses': [u'192.0.2.10'],
u'ansible_architecture': u'x86_64',
...
}
[192.0.2.10] TASK: install package (debug)> p task_vars['pkg_name']
u'bash'
[192.0.2.10] TASK: install package (debug)> p host
192.0.2.10
[192.0.2.10] TASK: install package (debug)> p result._result
{'_ansible_no_log': False,
'changed': False,
u'failed': True,
...
u'msg': u"No package matching 'not_exist' is available"}
更新模块参数:task.args
task.args[key] = value 用来更新模块参数。下面的 playbook 使用了无效的软件包名称:
- hosts: test
strategy: debug
gather_facts: true
vars:
pkg_name: not_exist
tasks:
- name: Install a package
ansible.builtin.apt: name={{ pkg_name }}
运行时,无效的软件包名称导致错误并进入调试器。可以先查看模块参数,再把软件包名称改为正确的值:
[192.0.2.10] TASK: install package (debug)> p task.args
{u'name': u'{{ pkg_name }}'}
[192.0.2.10] TASK: install package (debug)> task.args['name'] = 'bash'
[192.0.2.10] TASK: install package (debug)> p task.args
{u'name': 'bash'}
[192.0.2.10] TASK: install package (debug)> redo
更新模块参数后,使用 redo,让任务以新的参数重新执行。
更新任务变量:task_vars
task_vars[key] = value 用来更新任务变量。对于上一个示例,也可以查看并更新变量,而不直接修改模块参数:
[192.0.2.10] TASK: install package (debug)> p task_vars['pkg_name']
u'not_exist'
[192.0.2.10] TASK: install package (debug)> task_vars['pkg_name'] = 'bash'
[192.0.2.10] TASK: install package (debug)> p task_vars['pkg_name']
'bash'
[192.0.2.10] TASK: install package (debug)> update_task
[192.0.2.10] TASK: install package (debug)> redo
修改任务变量后,必须先使用 update_task 加载新变量,然后才能使用 redo 重新运行任务。
从 Ansible 2.5 起,这个名称由 vars 改为 task_vars,以避免与 Python 的 vars() 函数冲突。
重新创建任务:update_task
此命令在 Ansible 2.8 中加入。u 或 update_task 会依据任务原始数据结构及模板,使用更新后的任务变量重新创建任务。上面的更新变量示例展示了它的用法。
重新执行:redo
r 或 redo 会重新运行当前任务。
继续执行:continue
c 或 continue 会从下一个任务开始继续执行。
退出:quit
q 或 quit 会退出调试器,并中止 playbook 执行。
调试器与 free 策略如何交互
使用默认的 linear 策略时,调试器处于活动状态期间,Ansible 会暂停执行;输入 redo 后,会立即重新运行被调试的任务。
free 策略不等待所有主机同步推进。因此,在一台主机上的任务失败之前,另一台主机的后续任务可能已经排入队列。调试器处于活动状态时,Ansible 不会新增排队任务,也不会执行任务,但已排队的任务仍会保留。
退出调试器后,这些已排队任务会立即恢复执行。如果通过 redo 重新安排一个任务,其他已排队任务可能先于该任务执行。更多说明见 执行策略。










暂无评论内容