我正在使用 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 直到加载会话即可。