我使用的剧本在客户的旧版 Debian 5 机器上莫名其妙地失败了。剧本本身和我的 Ansible 配置都很稳定,我已经成功地在各种新旧主机上运行了它们,从 CentOS 6 和 7.x 机器到 Debian 10,但这台机器给我带来了麻烦,我不知道为什么。
这是一个失败的最小示例剧本:
- hosts: deb5
gather_facts: no
tasks:
- name: random test task
shell:
cmd: "sed -e 's/netmask/netflask/' /etc/network/interfaces"
register: test_out
failed_when: no
- debug: var=test_out
以下是相应的清单:
# my ansible.cfg has 'interpreter_python = /usr/bin/python3' but I override it for
# the rare older machines without Python 3, like this one.
deb5 ansible_host=xxx.xxx.xxx.xxx ansible_python_interpreter=/usr/bin/python
最后是 ansible.cfg:
[defaults]
remote_user = some_user
interpreter_python = /usr/bin/python3
[privilege_escalation]
become = True
become_ask_pass = True
become_flags = -i
该剧本运行时没有其他参数,只有-i inventory
剧本名称。以下是调试任务的输出,显示了失败shell
sed
任务的捕获输出:
ok: [deb5] => {
"test_out": {
"changed": false,
"failed": false,
"failed_when_result": false,
"module_stderr": "Shared connection to xxx.xxx.xxx.xxx closed.\r\n",
"module_stdout": "/bin/sh: /bin/sh: cannot execute binary file\r\n",
"msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
"rc": 126
}
}
此处运行的任务sed
没有问题,据我所知,可能是任何其他任务(我也尝试过command
而不是shell
,并且运行awk
而不是)。如果我取出,剧本在事实收集阶段就已经失败,永远不会完成任务,sed
这进一步证明了这一点:gather_facts: no
TASK [Gathering Facts]
fatal: [deb5]: FAILED! => {"ansible_facts": {}, "changed": false, "failed_modules": {"ansible.legacy.setup": {"failed": true, "module_stderr": "Shared connection to xxx.xxx.xxx.xxx closed.\r\n", "module_stdout": "/bin/sh: /bin/sh: cannot execute binary file\r\n", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 126}}, "msg": "The following modules failed to execute: ansible.legacy.setup\n"}
根据谷歌搜索,“无法执行二进制文件”通常表示架构不匹配,但我不知道这在这里如何适用。当我通过 SSH 连接到服务器并运行所涉及的任何命令(/bin/sh
、/usr/bin/python
、sed
)时,它们都运行正常。根据 ,我的 macOS Ansible 控制器是 x86_64,Debian 5 盒也是uname -m
。
关于 Debian 5 盒子的一个值得注意的事情是它的 Python 非常老,版本为 2.5.2。我认为 Ansible 目前只支持目标机器上 2.6 及以上的 Python。然而,这可能不是罪魁祸首,因为即使是模块raw
(无需 Python 即可运行,可用于在没有 Python 的主机上安装 Python)也会失败:
# Debian 5
- hosts: deb5
gather_facts: no
tasks:
- name: random test task
raw: "sed -e 's/netmask/netflask/' /etc/network/interfaces"
register: test_out
failed_when: no
- debug: var=test_out
在这种情况下的输出:
ok: [deb5] => {
"test_out": {
"changed": true,
"failed": false,
"failed_when_result": false,
"msg": "non-zero return code",
"rc": 126,
"stderr": "Shared connection to xxx.xxx.xxx.xxx closed.\r\n",
"stderr_lines": [
"Shared connection to xxx.xxx.xxx.xxx closed."
],
"stdout": "/bin/sh: /bin/sh: cannot execute binary file\r\n",
"stdout_lines": [
"/bin/sh: /bin/sh: cannot execute binary file"
]
}
}
我对 Ansible 内部结构或其操作原理了解不够,无法进行任何其他测试,所以我希望这里有人能有进一步的想法。
答案1
好的,事实证明这不是 Ansible 问题。这似乎是目标主机上的 sudo 问题,我可以通过简单的 SSH 连接进行复制。