防止从SSH注销后终止当前正在运行的linux任务


18

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

我想重新启动从中打开ssh会话的本地计算机(而不是服务器),但希望保持任务运行。那有可能吗?

Answers:


22

如果你的任务已经启动,为时已晚*考虑其他的解决方案,将您之间的附加层ssh会话和shell中运行命令一样screentmuxbyobunohup和喜欢。

如果您的过程支持要放在后台,尤其是当它不能挂起stdoutstderr无法写/关闭时,您可以将其放在后台ControlZbg然后再注销,然后使用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
$ 

*正如Bob所评论的那样,在Linux下,实际上有几种方法可以重载tty会话。repty,rettyinjcodeneercs。最高级的似乎是reptyr,但是您可能需要root特权才能启用ptrace来入侵您的进程。


我使用Ctrl + Z,作业停止并移至后台,然后执行disown命令。它返回:bash:警告:删除进程组24876的停止的作业1。现在列出了我的作业,ps -all但似乎不起作用(CPU使用率为0%)
Ali

似乎我的过程已停止。我想我应该已经用disown命令提供了进程ID
阿里

@Ali我认为您忘记了运行bg命令来恢复已暂停的作业。

1
@JasonZhu感谢您指出这一点。不清楚bg我答复的第一部分中是否需要该命令。编辑。
jlliagre 2014年

2
如果您忘记了bg命令而只运行了disown命令,则应该能够使该进程再次运行,并且kill -CONT该进程的运行与bg大致相同。
kasperd 2014年

5

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

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

编辑:如注释中所述,仅当您记得screen在运行命令之前启动时,此方法才起作用。如果该命令已在运行,则需要@jlliagre的解决方案。


2
tmux是另一个类似的程序screen,它允许您进行远程会话,该会话不依赖于当前的SSH连接。
Darth Android

2
您的解决方案很棒。但是,它并不完全适合我的问题-我询问了当前正在运行的进程,而不是将来使用来运行的进程screen
阿里

啊好吧。在这种情况下,我认为您将需要使用@jlliagre的解决方案。(据我所知,还没有办法将已经运行的进程连接到screentmux。)
Scott Weldon 2014年

1

这样做的“标准”方法之一是使用nohup包含在中的命令coreutils,如下所示:

nohup COMMAND [ARGS] &

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


2
再读一次。该进程已在运行
与Monica进行的Lightness竞赛

/ ashamed没有仔细阅读。抱歉。
wangguoqin1001 2014年

实际上nohup可以用于此。只需暂停正在运行的进程并将其发送到后台(Ctrl+ Z并运行bg),然后就可以发出nohup %1
mike 2014年

0

除此以外,nohup您还可以使用“&”和subshel​​l在后台启动该过程:

在命令后缀&并将其括在括号中

$ (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断开连接。

尝试退出外壳程序,然后输入新的外壳程序。即使此外壳连接到相同的点,您现在也可以看到没有点的过程:

$ 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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.