![如何防止从 SSH 注销后当前正在运行的 Linux 任务被终止?](https://linux22.com/image/1429417/%E5%A6%82%E4%BD%95%E9%98%B2%E6%AD%A2%E4%BB%8E%20SSH%20%E6%B3%A8%E9%94%80%E5%90%8E%E5%BD%93%E5%89%8D%E6%AD%A3%E5%9C%A8%E8%BF%90%E8%A1%8C%E7%9A%84%20Linux%20%E4%BB%BB%E5%8A%A1%E8%A2%AB%E7%BB%88%E6%AD%A2%EF%BC%9F.png)
我在 Linux 服务器上通过 SSH 连接运行了几天的计算任务。它不在后台,因此 SSH 连接处于任务暂停状态。
我想重新启动已打开 SSH 会话的本地计算机(而不是服务器),但希望保持任务运行。
这可能吗?
答案1
如果您的任务已经启动,那么考虑在您的会话和运行命令的 shell 之间插入额外层的替代解决方案就太晚了,例如,,,等等。ssh
screen
tmux
byobu
nohup
如果您的进程支持放置在后台,特别是在无法写入/关闭时不会挂起stdout
,stderr
您可以在注销之前将其放置在后台ControlZ,bg
然后使用内置命令将其从您的 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。STDERR
nohup.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