使用 ssh 创建隧道时命令或 Shell 任务挂起

使用 ssh 创建隧道时命令或 Shell 任务挂起

我正在使用 Ansible 来推送配置。我在剧本中有一个任务,我想在后台为 MongoDB 启动一个 ssh 隧道。我使用的任务命令是

- name: Start tunnel service
  shell: ssh -f -N -L 27018:localhost:27017 mongo@remote-server 

但无论我做什么,我都无法让 ansible 继续运行。相反,它挂起或表现得像在等待某事返回响应。如果我像平常一样在 shell 中运行此命令,它不会出现任何问题,我可以连接到远程 mongo 实例。

起初我以为是因为我正在设置一个新服务器,所以 ssh 的 known_hosts 正在等待用户回答是/否才能继续。在这种情况下,我尝试了两个选项。首先,我尝试将服务器的指纹添加到 known_hosts 文件中。从 shell 运行后,它没有要求输入 known_hosts 条目,但 ansible 也仍然挂起。我还尝试了以下选项

ssh -o StrictHostKeyChecking=no -f -N -L 27018:localhost:27017 mongo@remote-server

但是此选项也会产生与 ansible 挂起相同的问题。

我尝试过在 ansible 的命令和 shell 模块之间切换,问题没有任何变化。我最近的实验是在命令前尝试 nohup,但这也不起作用。

nohup ssh -f -N -L 27018:localhost:27017 mongo@remote-server

我还试图创造性地思考,如果另一个进程能够运行该命令,那么之后它会将响应发送回 ansible,我尝试将其包装为 Upstart 任务。我将 shell 命令放在一个/etc/tunnel.sh文件中,并将 upstart 脚本放在 中/etc/init/tunnel.conf。但这也不起作用,似乎无法真正启动脚本。如果我运行,sudo service tunnel start它会启动,但无法停止。虽然通过 ansible 作为命令运行它不会执行任何操作,只是像所有其他实验一样呆在那里挂起。

- name: Start tunnel service
  command service tunnel start

答案1

如果您使用 sudo 和密钥,我敢打赌您没有保留 SSH_AUTH_SOCK 环境变量。这对于建立从协调机器到 mongodb 实例的连接是必需的。在这种情况下,您应该将以下内容添加到 /etc/sudoers:

Defaults        env_keep+=SSH_AUTH_SOCK
Defaults        env_reset

答案2

我做了同样的测试,发现这是因为 ssh 命令要求指纹确认当您第一次使用 ssh 时,ansible 卡住并且无法处理远程提示。

简单的方法是调整你的 ssh 隧道命令,如下所示:

ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -f -N -L 27018:localhost:27017 mongo@remote-server 

它将绕过主机密钥检查并完成你的 ansible 任务。

答案3

您还可以使用 ansible 的异步操作(http://docs.ansible.com/playbooks_async.html

- name: Start tunnel service
  shell: ssh -f -N -L 27018:localhost:27017 mongo@remote-server
  async: 15
  poll: 5

这将允许 ansible 完成任务,给予它 15 秒的最大运行时间来执行,并每 5 秒轮询一次是否完成。

答案4

除了使用 nohup,为什么不尝试使用screen呢?

ssh user@server screen -dR command

screen好用得多,因为您只需使用 CTRL-A、D 分离会话,然后注销,当您稍后需要返回会话时,只需使用 ssh 登录服务器并按 CTRL-A、1 或一直按 CTRL-A 直到加载会话即可。

相关内容