【问题标题】:Unable to fully close remote SSH tunnel in script's exit无法在脚本退出时完全关闭远程 SSH 隧道
【发布时间】:2017-12-22 15:55:16
【问题描述】:

我正在编写一个脚本,它从我们远程部署的虚拟机双跳 SSH 转发端口 80,并在本地浏览器中打开这个“状态页面”。要打开它,SSH 隧道必须是“背景的”,但是这样做会导致 SSH 隧道退出,并且在我正在通过隧道的 SSH 服务器上保留一个持久隧道 (bastion)。到目前为止,这是脚本:

#!/bin/sh
# SSH needs a HUP when this script exits
shopt -s huponexit

echo "SSH Forwards the VM status page for a given host..."
read -p "Host Name: " CODE
PORT=$(($RANDOM + 1024))

# "-t -t" (force tty) needed to avoid orphan tunnels on bastion after exit. (Only seems to work when not backgrounded?)
ssh -t -t -4L $PORT:localhost:$PORT user1@bastion sudo ssh -4NL $PORT:localhost:80 root@$CODE.internal-vms &
PID=$!

# Open browser to VM Status Page
sleep 1
open http://localhost:$PORT/

# Runs the SSH tunnel in the background, ensuring it gets killed on shell's exit...
bash

kill -CONT $PID
#kill -QUIT $PID
echo "Killed SSH Tunnel. Exiting..."
sleep 2

不幸的是,考虑到 SSH 隧道的背景(在第 10 行使用 &),当脚本被终止(通过 CTRL-C)时,“堡垒”服务器最终会无限期地保留一个孤立的 SSH 连接。

-t -t”和“shopt -s huponexit”已修复,我试过了,但似乎没有帮助。我还在最终的kill 中尝试了各种 SIG。我在这里做错了什么?感谢您的帮助!

【问题讨论】:

  • 很遗憾,我在这个系统中继承了一些奇怪的约束。最大的需求是需要使用 sudo 从堡垒 ssh 到虚拟机。并且有许多虚拟机,因此将 user1 的 SSH 密钥部署到所有虚拟机会很困难。
  • 我可以建议 Ansible 管理您的虚拟机并为所有虚拟机部署密钥吗?这将使您的生活更轻松,虚拟机更安全。
  • 实际上,我们现在正在推出 Ansible 配置管理。 Ansible 很棒。不幸的是,有很多遗留服务需要我们一点一点地“Ansiblize”。
  • 我几乎可以肯定,我什至已经看到 -t -t -t 在 SSH 上取得了一些成功,但不记得正在解决的具体问题。值得一试。祝你好运。

标签: bash ssh ssh-tunnel


【解决方案1】:

-f 标志可用于后台进程。要结束连接,ssh -O exit user1@bastion 是一个比kill 更好的选择,kill 比较暴力。

我会这样做。仅供参考,我没有测试修改后的脚本,虽然我经常使用类似的长 SSH 命令。

#!/bin/sh
# SSH needs a HUP when this script exits
shopt -s huponexit

echo "SSH Forwards the VM status page for a given host..."
read -p "Host Name: " CODE
PORT=$(($RANDOM + 1024))

# "-t -t" (force tty) needed to avoid orphan tunnels on bastion after exit. (Only seems to work when not backgrounded?)
ssh -t -t -f -4L $PORT:localhost:$PORT user1@bastion sudo ssh -4NL $PORT:localhost:80 root@$CODE.internal-vms
#PID=$!

# Open browser to VM Status Page
sleep 1
open http://localhost:$PORT/

# Runs the SSH tunnel in the background, ensuring it gets killed on shell's exit...
#bash

#kill -CONT $PID
#kill -QUIT $PID
ssh -O exit user@bastion

echo "Killed SSH Tunnel. Exiting..."
sleep 2

【讨论】:

  • 我已经实现了这个建议,做了一些修改(ControlPath 需要一个套接字,而不是一个普通文件)。但是,在断开连接后,由 sudo 调用的第二个连接会在 Bastion 上继续运行,并且必须在该服务器上手动断开连接。
  • 我认为解决方案是避免使用 sudo,因为它会调用一个新的 shell 进程,该进程不会接收来自原始 SSH 连接的信号。
  • ssh -O exit 需要 ControlPath 才能工作。您可能在 sudo-ed SSH 上没有退出,因为它以 root 身份运行。一种解决方案是让 SSH 服务器在某个时间范围后自动 d/c 2daygeek.com/…
  • 是的,我将在此过程中不再需要 sudo。无论如何,这是做这种事情的一种时髦方式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-29
  • 2016-07-26
  • 1970-01-01
  • 2021-05-11
  • 2015-12-02
  • 2019-10-29
  • 2018-10-29
相关资源
最近更新 更多