题
我的流程已经运行了很长时间,并且不想结束它。
如何将它置于nohup之下(即,即使关闭终端,如何让它继续运行?)
解决方案
使用bash的作业控制将流程发送到背景:
- Ctrl + Z 停止(暂停)程序并返回shell。
-
bg
在后台运行。 -
disown -h [job-spec]
其中[job-spec]是作业编号(如第一个正在运行的作业的%1
;使用jobs
命令查找您的编号),以便在终端关闭时不会终止作业
醇>
其他提示
假设由于某种原因 Ctrl + Z 也无效,转到另一个终端,找到进程ID(使用ps
)并运行:
kill -SIGSTOP PID
kill -SIGCONT PID
SIGSTOP
将暂停该过程,SIGCONT
将在后台恢复该过程。所以现在,关闭两个终端并不会停止你的过程。
将正在运行的作业与shell分离的命令(=使其成为nohup)是disown
和基本的shell命令。
来自bash-manpage(man bash):
disown [-ar] [-h] [jobspec ...]
如果没有选项,则会从活动作业表中删除每个jobspec。如果给出-h选项,则不是每个jobspec 从表中删除,但标记为如果shell收到SIGHUP,则不会将SIGHUP发送到作业。如果没有jobspec 当前作业既不提供-a也不提供-r选项,而是使用当前作业。如果未提供jobspec,则使用-a选项 意味着删除或标记所有工作;没有jobspec参数的-r选项将操作限制为正在运行的作业。回报 值为0,除非jobspec未指定有效作业。
这意味着,这很简单
disown -a
将从作业表中删除所有作业并使其成为nohup
以上这些都是很好的答案,我只是想补充说明:
你不能disown
一个pid或过程,你<=>一份工作,这是一个重要的区别。
作业是附加到shell的进程概念,因此您必须将作业放入后台(而不是暂停它)然后将其取消。
问题:
% jobs
[1] running java
[2] suspended vi
% disown %1
请参阅 http://www.quantprinciple.com/投资/ index.php文件/文件/ tipsandtricks / UNIX / JobControl作业控制/ 有关Unix作业控制的更详细讨论。
不幸的是disown
特定于bash,并且在所有shell中都不可用。
某些版本的Unix(例如AIX和Solaris)在nohup
命令本身上有一个选项,可以应用于正在运行的进程:
nohup -p pid
Node的答案真的很棒,但是它还有一个问题是如何让stdout和stderr重定向。我找到了 Unix <!> amp;的解决方案。 Linux ,但它也不完整。我想合并这两个解决方案。这是:
对于我的测试,我创建了一个名为loop.sh的小型bash脚本,它在无限循环中打印了一小段睡眠。
$./loop.sh
现在以某种方式得到这个过程的PID。通常ps -C loop.sh
足够好,但是我会打印出来。
现在我们可以切换到另一个终端(或按^ Z并在同一个终端)。现在gdb
应该附加到这个过程。
$ gdb -p <PID>
这会停止脚本(如果正在运行)。它的状态可以通过ps -f <PID>
检查,其中STAT
字段是'T +'(或者在^ Z'T'的情况下),这意味着(man ps(1))
T Stopped, either by a job control signal or because it is being traced
+ is in the foreground process group
(gdb) call close(1)
$1 = 0
关闭(1)成功时返回零。
(gdb) call open("loop.out", 01102, 0600)
$6 = 1
如果成功,Open(1)将返回新的文件描述符。
此开放与open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)
相同。
而不是O_RDWR
O_WRONLY
可以应用,但/usr/sbin/lsof
对所有std *文件处理程序(FD
列)说'u',这是O_APPEND
。
我检查了/usr/include/bits/fcntl.h头文件中的值。
输出文件可以用nohup
打开,如man open(2)
那样,但由于可能存在NFS问题,call perror("")
不建议这样做。
如果我们将-1作为返回值,则p errno
输出错误消息。如果我们需要errno,请使用/usr/sbin/lsof -p <PID>
gdb comand。
现在我们可以检查新重定向的文件。 call close(2)
打印:
loop.sh <PID> truey 1u REG 0,26 0 15008411 /home/truey/loop.out
如果我们想要,我们可以将stderr重定向到另一个文件,如果我们想再次使用call open(...)
和bash
使用不同的文件名。
现在必须发布附件^Z
,我们可以退出jobs
:
(gdb) detach
Detaching from program: /bin/bash, process <PID>
(gdb) q
如果脚本被gdb -q -x loop.gdb -p <PID>
从其他终端停止,它将继续运行。我们可以切换回loop.sh的终端。现在它不会向屏幕写任何内容,而是运行并写入文件。我们必须把它放到后台。所以按<=>。
^Z
[1]+ Stopped ./loop.sh
(现在我们处于相同的状态,就像在开头按<=>一样。)
现在我们可以查看工作状态:
$ ps -f 24522
UID PID PPID C STIME TTY STAT TIME CMD
<UID> <PID><PPID> 0 11:16 pts/36 S 0:00 /bin/bash ./loop.sh
$ jobs
[1]+ Stopped ./loop.sh
因此,进程应该在后台运行并从终端分离。方括号中<=>命令输出中的数字标识<=>内的作业。我们可以在以下内置的<=>命令中使用在作业号前面应用'%'符号:
$ bg %1
[1]+ ./loop.sh &
$ disown -h %1
$ ps -f <PID>
UID PID PPID C STIME TTY STAT TIME CMD
<UID> <PID><PPID> 0 11:16 pts/36 S 0:00 /bin/bash ./loop.sh
现在我们可以退出调用bash了。该过程继续在后台运行。如果我们退出它的PPID变为1(init(1)进程)并且控制终端变得未知。
$ ps -f <PID>
UID PID PPID C STIME TTY STAT TIME CMD
<UID> <PID> 1 0 11:16 ? S 0:00 /bin/bash ./loop.sh
$ /usr/bin/lsof -p <PID>
...
loop.sh <PID> truey 0u CHR 136,36 38 /dev/pts/36 (deleted)
loop.sh <PID> truey 1u REG 0,26 1127 15008411 /home/truey/loop.out
loop.sh <PID> truey 2u CHR 136,36 38 /dev/pts/36 (deleted)
<强> COMMENT 强>
可以自动化gdb内容,创建包含命令的文件(例如loop.gdb)并运行<=>。我的loop.gdb看起来像这样:
call close(1)
call open("loop.out", 01102, 0600)
# call close(2)
# call open("loop.err", 01102, 0600)
detach
quit
或者可以使用以下一个班轮代替:
gdb -q -ex 'call close(1)' -ex 'call open("loop.out", 01102, 0600)' -ex detach -ex quit -p <PID>
我希望这是对解决方案的完整描述。
将运行流程发送到nohup( http://en.wikipedia.org/wiki/Nohup一>)
nohup -p pid
,它对我不起作用
然后我尝试了以下命令,它工作得很好
-
运行一些SOMECOMMAND, 说
/usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1
。 -
Ctrl + Z 停止(暂停)程序并返回shell。
-
bg
在后台运行。 -
disown -h
以便终端关闭时不会终止进程。 -
键入
exit
以退出shell,因为现在你很高兴因为操作将在后台运行它自己的进程,所以它不依赖于shell。
醇>
此过程相当于运行nohup SOMECOMMAND
。
在我的AIX系统上,我试过
nohup -p processid>
这很好用。即使在关闭终端窗口后,它仍继续运行我的过程。我们将ksh作为默认shell,因此bg
和disown
命令不起作用。
- ctrl + z - 这会暂停作业(不会取消!)
-
bg
- 这会将作业置于后台并返回正在运行的过程 -
disown -a
- 这将切断所有附件与作业(因此您可以关闭终端,它仍然会运行)
醇>
这些简单的步骤将允许您在保持流程运行的同时关闭终端。
它不会穿上nohup
(基于我对你的问题的理解,你在这里不需要它。)
在tcshell中,这对我在Ubuntu linux上有用。
-
Ctrl Z 暂停
-
bg
在后台运行 -
jobs
获取其工作号 -
nohup %n
其中n是作业编号
醇>