调试模块
详细调试步骤
Ansible模块打包成一个zip文件,包含模块文件和包装脚本内的各种Python模块样板。要查看模块中实际发生的情况,需要从包装器中提取文件。包装器脚本提供了可以执行此操作的辅助方法。
以下步骤使用localhost
作为目标主机,但也可以使用相同的步骤来调试远程主机。有关无需使用临时文件的更简单的调试方法,请参见简单调试。
在控制主机上将
ANSIBLE_KEEP_REMOTE_FILES
设置为1
,以便Ansible保留远程模块文件,而不是在模块执行完毕后将其删除。使用-vvv
选项使Ansible更详细。这将显示临时模块文件的名称。$ ANSIBLE_KEEP_REMOTE_FILES=1 ansible localhost -m ping -a 'data=debugging_session' -vvv <127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: badger <127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595 `" && echo "` echo $HOME/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595 `" )' <127.0.0.1> PUT /var/tmp/tmpjdbJ1w TO /home/badger/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595/AnsiballZ_ping.py <127.0.0.1> EXEC /bin/sh -c 'LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 /usr/bin/python /home/badger/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595/AnsiballZ_ping.py && sleep 0' localhost | SUCCESS => { "changed": false, "invocation": { "module_args": { "data": "debugging_session" }, "module_name": "ping" }, "ping": "debugging_session" }
导航到上一步中的临时目录。如果之前的命令针对远程主机运行,则先连接到该主机,然后再尝试导航到临时目录。
$ ssh remotehost # only if not debugging against localhost $ cd /home/badger/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595
运行包装器的
explode
命令将字符串转换为一些可以使用的Python文件。$ python AnsiballZ_ping.py explode Module expanded into: /home/badger/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595/debug_dir
如果要检查包装器文件,可以查看。它将显示一个包含大型base64编码字符串的小型Python脚本。该字符串包含要执行的模块。
查看临时目录时,将看到如下结构
├── AnsiballZ_ping.py └── debug_dir ├── ansible │ ├── __init__.py │ ├── module_utils │ │ ├── __init__.py │ │ ├── _text.py │ │ ├── basic.py │ │ ├── common │ │ ├── compat │ │ ├── distro │ │ ├── parsing │ │ ├── pycompat24.py │ │ └── six │ └── modules │ ├── __init__.py │ └── ping.py └── args
AnsiballZ_ping.py
是包含以base64编码字符串存储的模块代码的Python脚本。它包含各种用于执行模块的辅助函数。ping.py
是模块本身的代码。您可以修改此代码以查看它对模块的影响,或用于调试目的。args
文件包含一个JSON字符串。该字符串是一个字典,包含Ansible传递到模块中以更改其行为的模块参数和其他变量。修改此文件以更改传递给模块的参数。ansible
目录在modules
中包含模块代码,以及来自ansible.module_utils
的代码,模块使用这些代码。Ansible包含任何ansible.module_utils
导入的模块的文件,但不包含任何其他模块的文件。如果你的模块使用ansible.module_utils.url
,Ansible将为你包含它。但是,如果你的模块包含requests,则必须确保在运行模块之前系统上安装了Python requests库。
如果怀疑模块在此样板代码而不是你编写的模块代码中存在问题,可以修改此目录中的文件。
编辑展开树中的代码或参数后,使用
execute
子命令运行它$ python AnsiballZ_ping.py execute {"invocation": {"module_args": {"data": "debugging_session"}}, "changed": false, "ping": "debugging_session"}
此子命令将
debug_dir
的绝对路径插入sys.path
的第一个项目中,并使用args
文件中的参数调用脚本。您可以继续这样运行模块,直到理解问题。然后,您可以将更改复制回实际的模块文件,并通过使用ansible
或ansible-playbook
测试实际模块是否有效。
简单调试
在本地或远程模块中运行调试器的最简单方法是使用epdb。在控制节点上所需断点处的模块代码中添加import epdb; epdb.serve()
。要连接到调试器,请运行epdb.connect()
。有关如何指定host
和port
,请参阅epdb文档。如果连接到远程节点,请确保使用控制节点和远程节点之间任何防火墙允许的端口。
此技术应该适用于任何远程调试器,但我们不保证任何特定的远程调试工具都能正常工作。
q库是另一个非常有用的调试工具。
由于print()
语句不能在模块内使用,因此如果只想查看一些特定数据,则引发异常是一种好方法。在模块中的某个位置放置raise Exception(some_value)
并正常运行它。Ansible将处理此异常,将消息传递回控制节点并显示它。