如何终止使用 -f 选项启动的 SSH 会话(在后台运行)

Mou*_*inX 87 ssh ssh-tunneling background-process

我很迷茫。从手册页:

 -f      Requests ssh to go to background just before command execution.
Run Code Online (Sandbox Code Playgroud)

使用该-f选项启动 SSH 后,我有一个工作隧道。但是用完之后不知道怎么和它进一步交互。例如,当我完成它时,我无法关闭 SSH 隧道

我知道的常用方法不起作用。例如,不jobs返回任何内容。该~命令无法识别(无论如何我不知道如何使用它)。

但是,pgrep告诉我 SSH 隧道仍在运行(在我关闭终端等之后)。我如何与它互动?我该如何关闭它?

小智 113

脚本编写的一个特别好的解决方案是使用master mode, 和控制命令的套接字:

ssh -f -N -M -S <path-to-socket> -L <port>:<host>:<port> <server>
Run Code Online (Sandbox Code Playgroud)

再次关闭它:

ssh -S <path-to-socket> -O exit <server>
Run Code Online (Sandbox Code Playgroud)

这避免了对进程 ID 的 grepping 以及可能与其他方法相关的任何计时问题。

  • 只是为初学者扩展一点, *&lt;path-to-socket&gt;* 是 ssh 客户端的主实例将为与其他想要共享主实例的 ssh 客户端实例的进程间通信而创建的文件的路径联系。创建的文件实际上将代表一个 unix 域套接字。它可以被命名和定位在任何你想要的地方,例如`/tmp/session1`(尽管建议使用 *%* 模式命名它 - 请参阅 `man ssh_config` 中的 *ControlPath* 描述) (17认同)
  • 这个答案和问题有些陈旧,但我想认可这可能是我见过的处理这个问题的最优雅和“正确”的方式。谢谢你,先生! (5认同)
  • 此外,`ssh -S &lt;path-to-socket&gt; -O exit &lt;server&gt;` 命令的 *&lt;server&gt;* 部分似乎可以是任何字符串,但它必须存在。这有点笨拙。 (3认同)

Mou*_*inX 65

我在这里找到了解决方案:http : //www.g-loaded.eu/2006/11/24/auto-closure-ssh-tunnels/

最好的方法——自动关闭的隧道

正如前面提到的,我们可以不使用 -f -N 开关组合,而是单独使用 -f,但也可以在远程机器上执行命令。但是,应该执行哪个命令,因为我们只需要初始化一个隧道?

这时候 sleep 可能是最有用的命令了!在这种特殊情况下,睡眠有两个优点:

  • 它什么都不做,所以不消耗资源
  • 用户可以指定执行多长时间

下面解释了这些如何帮助自动关闭 ssh 隧道。

我们在后台启动 ssh 会话,同时在远程机器上执行 sleep 命令 10 秒。秒数并不重要。同时,我们和之前完全一样执行vncviewer:

[me@local]$ ssh -f -L 25901:127.0.0.1:5901 me@remote.example.org sleep 10; \
          vncviewer 127.0.0.1:25901:1
Run Code Online (Sandbox Code Playgroud)

在这种情况下,ssh客户端被指示将ssh会话分叉到后台(-f),创建隧道(-L 25901:127.0.0.1:5901)并在远程服务器上执行sleep命令10秒(sleep 10)。

这种方法与前一种方法(-N 开关)的区别基本上在于,在这种情况下,ssh 客户端的主要目标不是创建隧道,而是执行 10 秒的 sleep 命令。隧道的创建是某种副作用,是次要目标。如果不使用 vncviewer,ssh 客户端将在 10 秒后退出,因为它没有更多的工作要做,同时破坏隧道。

在执行 sleep 命令期间,如果另一个进程,在本例中为 vncviewer,开始使用该隧道并使其占用超过 10 秒,那么,即使 ssh 客户端完成其远程作业(执行 sleep),它也无法退出,因为另一个进程占用了隧道。换句话说,ssh 客户端不能破坏隧道,因为它也必须杀死 vncviewer。当 vncviewer 停止使用隧道时,ssh 客户端也会退出,因为它已经完成了目标。

这样,没有 ssh 进程在后台运行。

  • 简短评论/更正:据我所知,您必须指定 `vncviewer 127.0.0.1::25091`,因为您使用的是端口语法而不是显示语法。 (4认同)
  • 对于仍在查看此答案的任何人。这个答案也在“TCP FORWARDING”标题下的“man ssh”中给出 (3认同)

Gil*_*il' 17

要终止隧道,请使用ps -C sshps | grep ssh或任何其他变体来确定哪个 ssh 进程正在运行您的隧道。然后杀死它。

或者,您可以通过确定哪个端口打开来查找进程:

netstat -lnpt | awk '$4 ~ /:1234$/ {sub(/\/.*/, "", $7); print $7}'
Run Code Online (Sandbox Code Playgroud)

如果您想杀死在您的机器上运行的所有 ssh 客户端(作为您的用户),pkill ssh请执行此操作。


小智 13

正如这里的其他人所回答的那样,pkill ssh杀死它。

为了创建一个可以带回的隧道,我在screen没有-f选项的情况下启动它,然后使用Ctrl-A D. 要恢复隧道,请调用screen -r

  • 如果您是远程连接,请当心。pkill ssh 甚至会终止您当前的连接。 (2认同)

And*_*ódi 8

我在 SO 找到了一个强大的解决方案,请参阅:https ://stackoverflow.com/a/26470428 。所有功劳都归功于@ghoti。

我希望大家原谅我没有重复整个故事。它基于“高级”SSHControlMaster配置选项,您最好将其放入~/.ssh/config文件中。以下是我对 VNC-over-SSH 的操作方法(我雇主的 VPN 关闭了除 SSH 和 HTTPS 之外的所有端口)。

~/.ssh/config部分(注意ControlMasterControlPath条目:

Host vnc
    HostName    my.desktop.internal.within.company
    User    laryx
    IdentityFile ~/.ssh/id_ecdsa
    LocalForward 5999 127.0.0.1:5900
    RequestTTY no
    ExitOnForwardFailure yes
    ControlMaster auto
    ControlPath ~/.ssh/control_sockets%r@%h:%p
Run Code Online (Sandbox Code Playgroud)

我用一个小 Bash 脚本连接/断开连接:

#!/bin/bash
if [ $# -lt 1 ]; then
    echo "This script creates an SSH tunnel to my desktop"
    echo "so that I can share its screen via VNC-over-SSH"
    echo "Usage: $0 start|stop"
    echo "Remember to start VPN first!"
    exit 1
fi

if [ "$1" = "start" ]; then
    # Assuming that the VPN connection has been established
    # 1) Start the tunnel with
    ssh -f vnc -N
    # 2) check it
    ssh -O check vnc
    echo "Now share the screen by connecting to 'vnc://localhost:5999'"
    exit 0
fi

if [ "$1" = "stop" ]; then
    ssh -O exit vnc
    echo "Now you may exit the VPN"
    exit 0
fi
Run Code Online (Sandbox Code Playgroud)

隧道是通过ssh -O命令控制的。


Phi*_*oud 5

我发现在一个命令行中杀死所有隧道的最佳解决方案是

ps -lef|grep ssh|grep "\-L"|awk '{print $4}'|xargs kill

对于 ssh 会话,只需删除隧道选项

ps -lef|grep ssh|awk '{print $4}'|xargs kill


num*_*web 5

当我使用以下命令启动隧道时:

ssh -fN -D 8080 SOME_IP_HERE -l LOGIN_NAME_HERE
Run Code Online (Sandbox Code Playgroud)
  • -f 在命令执行之前请求 ssh 进入后台。
  • -N不要执行远程命令。这对于仅转发端口很有用。
  • -D 指定本地“动态”应用程序级端口转发。
  • -l 指定在远程机器上登录的用户。

我可以关闭它:

ps -lef | grep ssh | grep "8080" | awk "{print \$2}" | xargs kill
Run Code Online (Sandbox Code Playgroud)

  • 对于我在 Ubuntu 20.04 上,它是 `awk "{print \$4}"` 而不是 `awk "{print \$2}" ` 因为 `ps -lef` 在第四个位置而不是第二个位置打印 PID。 (2认同)