如何防止从 SSH 注销后当前正在运行的 Linux 任务被终止?

如何防止从 SSH 注销后当前正在运行的 Linux 任务被终止?

我在 Linux 服务器上通过 SSH 连接运行了几天的计算任务。它不在后台,因此 SSH 连接处于任务暂停状态。

我想重新启动已打开 SSH 会话的本地计算机(而不是服务器),但希望保持任务运行。

这可能吗?

答案1

如果您的任务已经启动,那么考虑在您的会话和运行命令的 shell 之间插入额外层的替代解决方案就太晚了,例如,,,等等。sshscreentmuxbyobunohup

如果您的进程支持放置在后台,特别是在无法写入/关闭时不会挂起stdoutstderr您可以在注销之前将其放置在后台ControlZbg然后使用内置命令将其从您的 shell 中分离出来disown

例如:

$ ssh localhost
You have new mail.
Last login: Fri Jun  6 11:26:56 2014

$ /bin/sleep 3600    


^Z[1] + Stopped                  /bin/sleep 3600
$ bg
[1] /bin/sleep 3600&
$ jobs
[1] +  Running                 /bin/sleep 3600
$ disown %1
$ exit
Connection to localhost closed.
$ ps -ef|grep sleep
jlliagre 12864     1  0 21:12 ?        00:00:00 /bin/sleep 3600
jlliagre 13056 12477  0 21:13 pts/18   00:00:00 grep sleep
$ 

1正如 Bob 所评论的,实际上有几种在 Linux 下重新设置 tty 会话父级的黑客方法。雷蒂注入代码内尔克. 最先进的看起来是雷普特但您可能需要 root 权限才能启用 ptrace 来破解您的进程。

答案2

一个解决方案是使用GNU 屏幕。您可以启动screen,运行命令,然后使用 分离C-a d。稍后,要重新连接,请执行screen -r,然后您就会回到上一个会话。

screen 的其他好处是窗口管理(因此您可以在命令运行时切换到其他 shell,而无需新的 SSH 连接),并且它允许您的命令保留在前台,无论是在当前会话还是在以后的会话中。

编辑:正如评论中所述,这只有在您记得在screen运行命令之前启动时才会起作用。如果命令已在运行,那么您将需要@jlliagre 的解决方案。

答案3

执行此操作的“标准”方法之一是使用nohup包含在中的命令coreutils,如下所示:

nohup COMMAND [ARGS] &

但是该命令会将程序的输出(STDOUT& AFAIK)重定向到一个文件中,有时会使其变得烦人(例如生成一个巨大的日志文件),因此您可能需要进行自己的重定向,或者如果需要,将其重定向到/dev/null。STDERRnohup.out

答案4

此外,nohup您还可以使用“&”和子shell在后台启动该进程:

在命令后加上 & 并将其括在括号中

$ (thecommand args &)

假设你的进程获得了 pid 1922:

$ ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
usr      11473  2643  0 15:07 pts/1    00:00:00 bash
usr      11922     1  0 15:11 pts/1    00:00:00 thecommand

看起来它已从其原始父级 shell 进程 11473 中脱离。因此,如果您退出或终止当前 shell (11473),进程 11922 将继续运行,并且它将与 pts 断开连接。

尝试退出该 shell,然后进入一个新的 shell。即使这个 shell 连接到相同的 pts,您现在也可以在没有 pts 的情况下看到该进程:

$ ps -fp 11922
UID        PID  PPID  C STIME TTY          TIME CMD
usr      11922     1  0 15:11 ?        00:00:00 thecommand

我不知道它在 Posix 中是如何调用或记录的,但我从 1990 年起在 bsh、ksh 以及现在的 bash 中都使用这种方式。

最后,您可以使用bg内置的 shell 命令:

只需启动您的程序,如果您决定暂停它,或计划将其保留在后台,请输入 CTRL+Z:

$ thecommand
^Z
[1] Stopped          thecommand

现在让它继续在后台运行:

$ bg
[1]+ thecommand &

如果你查看进程信息,你会发现它还有一个父进程:

$ ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
usr      12046  2643  0 15:18 pts/6    00:00:00 bash
usr      12571 12046  0 16:00 pts/6    00:00:00 thecommand
usr      12601 12046  0 16:04 pts/6    00:00:00 ps -f

因此,退出当前进程。后台运行的进程将脱离其原始父进程并继续在后台运行:

$ exit

再次登录并查看进程信息:

$ ps -f 12571
UID        PID  PPID  C STIME TTY          TIME CMD
usr      12571     1  0 16:00 ?        00:00:00 thecommand

相关内容