ansible 执行的命令正在等待交互式输入

ansible 执行的命令正在等待交互式输入

我的 ansible box(vagrant) 遇到了一些奇怪的问题。

昨天一切顺利,我的剧本也运行良好。

今天 ansible 挂在“收集事实”上?

以下是详细输出:

<5.xxx.xxx.xxx> ESTABLISH CONNECTION FOR USER: deploy
<5.xxx.xxx.xxx> REMOTE_MODULE setup
<5.xxx.xxx.xxx> EXEC ['ssh', '-C', '-tt', '-vvv', '-o', 'ControlMaster=auto', '-
o', 'ControlPersist=60s', '-o', 'ControlPath=/home/vagrant/.ansible/cp/ansible-s
sh-%h-%p-%r', '-o', 'Port=2221', '-o', 'KbdInteractiveAuthentication=no', '-o',
'PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey', '-o
', 'PasswordAuthentication=no', '-o', 'User=deploy', '-o', 'ConnectTimeout=10',
'5.xxx.xxx.xxx', "/bin/sh -c 'mkdir -p $HOME/.ansible/tmp/ansible-tmp-1411372677
.18-251130781588968 && chmod a+rx $HOME/.ansible/tmp/ansible-tmp-1411372677.18-2
51130781588968 && echo $HOME/.ansible/tmp/ansible-tmp-1411372677.18-251130781588
968'"]

答案1

我在 Vagrant 上使用 Ansible ping 时也遇到了类似的问题,它突然无缘无故地卡住了,之前一直运行良好。与 ssh 或连接问题等其他问题不同,它会永远死机,不会超时。

我解决这个问题的方法是清理~/.ansible目录,然后它又可以正常工作了。我不知道为什么,但问题确实解决了。

如果您再次遇到这种情况,请尝试~/.ansible在刷新 Vagrant 之前清理该文件夹。

答案2

有很多原因导致 ansible 在事实收集时挂起,但在进一步讨论之前,这是在任何此类情况下您应该进行的第一个测试:

ansible -m ping <hostname>

此测试仅连接到主机,并执行足够的代码以返回:

<hostname> | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

如果此方法有效,您几乎可以排除任何设置或连接问题,因为这证明您可以解析目标主机名、打开连接、进行身份验证并使用远程 python 解释器执行 ansible 模块。

现在,这里有一个(非详尽的)列表,列出了剧本开始时可能出错的事情:

ansible 执行的命令正在等待交互式输入

我记得这发生在旧版 ansible 上,其中命令会等待永远不会出现的交互式输入,例如 sudo 密码(当您忘记开关时-K)或接受新的 ssh 主机指纹(对于新的目标主机)。

现代版本的 ansible 可以妥善处理这两种情况,并在正常使用情况下立即引发错误,因此除非您自己执行诸如调用 ssh 或 sudo 之类的操作,否则您不应该遇到此类问题。即使您遇到了,那也是事后才发现的。

SSH 主连接已失效

在这里给出的调试日志中,传递给 ssh 客户端的一些非常有趣的选项:

  • ControlMaster=auto
  • ControlPersist=60s
  • ControlPath=/home/vagrant/.ansible/cp/ansible-ssh-%h-%p-%r

这些选项记录在ssh_config 手册

默认情况下,ansible 会尝试智能地使用 ssh 连接。对于给定的主机,它不会为剧本中的每个任务创建新连接,而是会打开一次,并在整个剧本(甚至跨剧本)中保持打开状态。

这很好,因为建立新连接比使用现有连接要慢得多,而且计算量也大得多。

实际上,每个 ssh 连接都会检查 处是否存在套接字~/.ansible/cp/some-host-specific-path。第一个连接找不到它,因此它正常连接,然后创建它。每个后续连接都将使用此套接字来通过已建立的连接。

即使建立的连接最终超时并在长时间未使用后关闭,套接字也会关闭,我们又回到原点。

到目前为止,一切都很好。

但有时,连接实际上已经断开,但 ssh 客户端仍认为它已建立。这种情况通常发生在您从笔记本电脑执行剧本时,并且丢失了 WiFi 连接(或从 WiFi 切换到以太网等...)

最后一个例子是一个可怕的情况:你使用默认的 ssh 配置通过 ssh 连接到目标机器,但只要您之前的连接仍然被视为活动连接,ansible 甚至不会尝试建立新的连接。

此时,我们只想摆脱这个旧套接字,最简单的方法就是将其删除:

# Delete all the current sockets (may disrupt currently running playbooks)
rm -r ~/.ansible/cp
# Delete only the affected socket (requires to know which one it is)
rm ~/.ansible/cp/<replace-by-your-socket>

这对于一次性修复来说非常完美,但如果这种情况发生得太频繁,您可能需要寻找一个长期修复方案。以下是一些可能有助于实现这一目标的提示:

  • 从服务器启动剧本(网络连接比笔记本电脑更稳定)
  • 使用ansible 配置或直接ssh 客户端配置禁用连接共享
  • 使用相同的资源,但要微调超时,以便主连接崩溃实际上超时更快

请注意,在撰写本文时,一些选项已经发生了变化(例如,我最近的运行给了我ControlPath=/home/toadjaune/.ansible/cp/871b533295),但总体思路仍然有效。

收集事实实际上花费了太多时间

在每个游戏开始时,ansible 都会收集目标系统的大量信息,并将其放入事实。这些是您可以在剧本中使用的变量,通常非常方便,但有时,获取这些信息可能需要很长时间(错误的挂载点、具有高 i/o 的磁盘、高负载……)

话虽如此,你不需要严格需要事实来运行剧本,而且几乎肯定不是全部,所以让我们尝试禁用我们不需要的内容。为此,有几种选择:

为了调试目的,直接从命令行调用设置模块非常方便:

ansible -m setup <hostname>

最后一个命令应该和你的剧本一样挂起,并最终超时(或成功)。现在,让我们再次执行模块,禁用所有我们可以禁用的功能:

ansible -m setup -a gather_subset='!all' <hostname>

如果问题仍然没有解决,您可以尝试在游戏中完全禁用该模块,但问题很可能出在其他地方。

但是,如果它运行良好(并且快速),那么看看模块文档。您有两个选择:

  • 将事实收集限制在一个子集内,排除不需要的内容(参见的可能值gather_subset
  • gather_timeout也可以帮助你解决问题,通过提供更多的时间(虽然这是为了修复超时错误,而不是挂起)

其他事宜

显然,其他事情也可能出错。以下是一些有助于调试的提示:

  • 使用 ansible 最大详细级别(-vvvv),因为它会显示执行的每个命令
  • 如上所述,直接从命令行使用ping和模块setup
  • ansible -m ping如果不起作用,请尝试手动 ssh

答案3

Ansible 可能会因多种原因而挂起,通常是由于连接问题或设置模块挂起。以下是如何缩小问题范围以便解决问题。

Ansible 无法连接到目标主机

主机密钥 (known_hosts) 问题

1) 在旧版本的 Ansible(2.1 或更早版本)中,Ansible 不会总是告诉您目标的主机密钥是否在源上不存在,或者是否存在不匹配。

解决方案:尝试使用相同的参数打开到该目标的 SSH 连接。您可能会发现需要解决的 SSH 错误,然后该命令就会起作用。

2) 有时 Ansible 会在其他状态中向您显示 SSH 连接消息,导致 Ansible 在该任务上“冻结”:

Warning: the ECDSA host key for 'myhost' differs from the key for the IP address '10.10.1.10'
Offending key for IP in /etc/ssh/ssh_known_hosts:246
Matching host key in /etc/ssh/ssh_known_hosts:477
Are you sure you want to continue connecting (yes/no)?

在这种情况下,只需对所询问的所有 SSH 问题都输入“yes”即可继续播放。之后,您可以修复 root known_hosts 问题。

私钥认证问题

如果使用基于密钥的身份验证而不是密码,其他问题包括:

  • 目的地可能未正确设置私钥
  • 私钥可能在本地具有不正确的权限(只有运行 Ansible 作业的用户才能读取)

解决方案:尝试ansible -m ping <destination> -k针对问题主机运行 - 如果不起作用,请尝试主机密钥问题上述解决方案。

Ansible 无法快速收集事实

setup模块(在运行开始时自动运行ansible-playbook或手动运行时ansible -m setup <host>)在收集硬件事实时通常会挂起(例如,如果从具有高 i/o、坏挂载条目等的主机获取磁盘信息)。

解决方案:尝试运行ansible -m setup -a gather_subset=!all <destination>。如果可行,您应该考虑在 ansible.cfg 中设置此行:

gather_subset=!hardware

答案4

我在 Gathering Facts 中遇到了类似的 Ansible 挂起问题。我将脚本缩减为没有任务或角色的提示,但它仍然挂起。

我在我的进程列表中发现了一天内积累的 12 个挂起的 ansible 进程。

/usr/bin/python /tmp/ansible_Jfv4PA/ansible_module_setup.py
/usr/bin/python /tmp/ansible_M2T10L/ansible_module_setup.py

一旦我杀死它们,它就会再次开始工作。

相关内容