Shell 如何将已经运行的进程置于nohup下?
我有一个进程已经运行了很长时间,不想结束它Shell 如何将已经运行的进程置于nohup下?,shell,nohup,Shell,Nohup,我有一个进程已经运行了很长时间,不想结束它 如何将其置于nohup下(即,即使关闭终端,如何使其继续运行?将正在运行的作业与shell分离的命令(=使其成为nohup)是disown和基本shell命令 从bash手册页(manbash): 拒绝[-ar][h][jobspec…] 如果没有选项,将从活动作业表中删除每个作业规范。如果给出了-h选项,则每个jobspec都不可用 已从表中删除,但进行了标记,以便在shell收到SIGHUP时不会将SIGHUP发送到作业。如果没有作业规范 当前,并
如何将其置于nohup下(即,即使关闭终端,如何使其继续运行?将正在运行的作业与shell分离的命令(=使其成为nohup)是
disown
和基本shell命令
从bash手册页(manbash):
拒绝[-ar][h][jobspec…]
如果没有选项,将从活动作业表中删除每个作业规范。如果给出了-h选项,则每个jobspec都不可用
已从表中删除,但进行了标记,以便在shell收到SIGHUP时不会将SIGHUP发送到作业。如果没有作业规范
当前,并且既不提供-a选项也不提供-r选项,则使用当前作业。如果未提供jobspec,则-a选项
指移除或标记所有作业;没有jobspec参数的-r选项将操作限制为运行的作业。回归
值为0,除非作业规范未指定有效作业
这意味着,一个简单的
disown -a
将从作业表中删除所有作业,并使用bash将进程发送到后台,使其成为nohup:
bg
在后台运行disown-h[job spec]
其中[job spec]是作业编号(如第一个运行作业的%1
;使用jobs
命令查找您的编号),以便在终端关闭时不会终止作业以上都是很好的答案,我只想补充一点: 您不能
disown
一个pid或流程,您可以disown
一个作业,这是一个重要的区别
作业是附加到shell的进程的概念,因此您必须将作业扔到后台(而不是挂起它),然后拒绝它
问题:
% jobs
[1] running java
[2] suspended vi
% disown %1
看
有关Unix作业控制的更详细讨论。假设由于某种原因Ctrl+Z也不工作,请转到另一个终端,找到进程id(使用ps
)并运行:
SIGSTOP
将暂停进程,而SIGCONT
将在后台恢复进程。所以现在,关闭两个终端不会停止进程 不幸的是,disown
是bash特有的,并非在所有shell中都可用
某些风格的Unix(例如AIX和Solaris)在nohup
命令本身上有一个选项,可以应用于正在运行的进程:
nohup -p pid
请参见将正在运行的进程发送到nohup()
nohup-ppid
,它对我不起作用
然后我尝试了以下命令,效果非常好
/usr/bin/python/vol/scripts/python\u scripts/retention\u all\u properties.py 1
bg
在后台运行disown-h
,以便在终端关闭时不会终止进程exit
退出shell,因为现在您可以开始了,因为操作将在其自己的进程中在后台运行,因此它不会绑定到shell这个过程相当于在我的AIX系统上运行
nohupsomecommand
,我尝试过
nohup -p processid>
这很有效。即使在关闭终端窗口后,它仍继续运行我的进程。我们使用ksh作为默认shell,因此
bg
和disown
命令不起作用。节点的答案非常好,但它留下了如何重定向stdout和stderr的问题。我在上找到了一个解决方案,但它也不完整。我想合并这两种解决方案。这是:
在我的测试中,我制作了一个名为loop.sh的小bash脚本,它在无限循环中以一分钟的睡眠打印自己的pid
$./loop.sh
现在以某种方式获取此过程的PID。通常ps-C loop.sh
就足够了,但它是在我的箱子里打印出来的
现在我们可以切换到另一个终端(或在同一终端中按^Z和)。现在应将gdb
附加到此流程
$ gdb -p <PID>
Close(1)在成功时返回零
(gdb) call open("loop.out", 01102, 0600)
$6 = 1
如果成功,Open(1)将返回新的文件描述符
此打开等同于打开(路径,O|u TRUNC | O|u create | O|u RDWR,S|u IRUSR | S|u IWUSR)
。
只能应用/usr/sbin/lsof
而不是O_-RDWR
,但是/usr/sbin/lsof
为所有std*文件处理程序(FD
列)显示“u”,即O_-RDWR
我检查了/usr/include/bits/fcntl.h头文件中的值
输出文件可以使用O_APPEND
打开,正如nohup
所做的那样,但是man open(2)
不建议这样做,因为可能存在NFS问题
如果返回值为-1,则call perror(“”
打印错误消息。如果我们需要errno,请使用p errno
gdb命令
现在我们可以检查新重定向的文件<代码>/usr/sbin/lsof-p打印:
loop.sh <PID> truey 1u REG 0,26 0 15008411 /home/truey/loop.out
如果脚本被另一个终端的gdb
停止,它将继续运行。我们可以切换回loop.sh的终端。现在它不向屏幕写入任何内容,而是运行并写入文件。我们必须把它放在背景中。所以按^Z
^Z
[1]+ Stopped ./loop.sh
(现在我们处于相同的状态,就好像开始时按下了^Z
)
现在,我们可以检查作业的状态:
$ 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
现在我们可以退出呼叫狂欢了。进程继续在后台运行。如果我们退出它的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)
或者,可以使用以下一种衬里:
gdb -q -ex 'call close(1)' -ex 'call open("loop.out", 01102, 0600)' -ex detach -ex quit -p <PID>
gdb-q-ex'调用关闭(1)'-ex'调用打开(“loop.out”,011020600)'-ex分离-ex退出-p
我希望这是对解决方案的一个相当完整的描述。
$ 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
$ 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)
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>