如何在nohup下放置已经运行的进程?

时间:2009-03-09 08:33:38

标签: shell nohup

我的流程已经运行了很长时间,并且不想结束它。

如何将它置于nohup之下(即,即使关闭终端,如何让它继续运行?)

11 个答案:

答案 0 :(得分:1272)

使用bash的Job Control将流程发送到后台:

  1. Ctrl + Z 停止(暂停)程序并返回shell。
  2. bg在后​​台运行。
  3. disown -h [job-spec]其中[job-spec]是作业编号(如第一个正在运行的作业的%1;使用jobs命令查找您的编号)以便作业不是'终点关闭时死亡。

答案 1 :(得分:163)

假设由于某种原因, Ctrl + Z 也无效,转到另一个终端,找到进程ID(使用ps)并运行:< / p>

kill -SIGSTOP PID 
kill -SIGCONT PID

SIGSTOP将暂停此过程,SIGCONT将在后台恢复此过程。所以现在,关闭两个终端并不会停止你的过程。

答案 2 :(得分:84)

将正在运行的作业与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

答案 3 :(得分:67)

以上这些都是很好的答案,我只是想补充说明:

你不能disown一个pid或进程,你disown一份工作,这是一个重要的区别。

作业是附加到shell的进程概念,因此您必须将作业放入后台(而不是暂停它)然后将其取消。

问题:

%  jobs
[1]  running java 
[2]  suspended vi
%  disown %1

参见http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/ 有关Unix作业控制的更详细讨论。

答案 4 :(得分:40)

不幸的是disown特定于bash,并且在所有shell中都不可用。

某些版本的Unix(例如AIX和Solaris)在nohup命令本身上有一个选项,可以应用于正在运行的进程:

nohup -p pid

请参阅http://en.wikipedia.org/wiki/Nohup

答案 5 :(得分:22)

Node的答案真的很棒,但是它还有一个问题是如何让stdout和stderr重定向。我在Unix & 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_RDWR。< / p>

我检查了/usr/include/bits/fcntl.h头文件中的值。

可以使用O_APPEND打开输出文件,nohup会这样做,但man open(2)不建议这样做,因为可能存在NFS问题。

如果我们将-1作为返回值,那么call perror("")将输出错误消息。如果我们需要errno,请使用p errno gdb命令。

现在我们可以检查新重定向的文件。 /usr/sbin/lsof -p <PID>打印:

loop.sh <PID> truey    1u   REG   0,26        0 15008411 /home/truey/loop.out

如果我们需要,我们可以将stderr重定向到另一个文件,如果我们想要使用不同的文件名再次使用call close(2)call open(...)

现在必须发布附加的bash,我们可以退出gdb

(gdb) detach
Detaching from program: /bin/bash, process <PID>
(gdb) q

如果脚本被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

因此,进程应该在后台运行并从终端分离。方括号中jobs命令输出中的数字标识bash内的作业。我们可以在以下内置bash命令中使用在作业号前面应用'%'符号:

$ 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)并运行gdb -q -x loop.gdb -p <PID>。我的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>

我希望这是对解决方案的完整描述。

答案 6 :(得分:7)

将正在运行的进程发送到nohup(http://en.wikipedia.org/wiki/Nohup

nohup -p pid,它对我不起作用

然后我尝试了以下命令,它工作得很好

  1. 运行一些SOMECOMMAND, 说/usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1

  2. Ctrl + Z 停止(暂停)程序并返回shell。

  3. bg在后​​台运行。

  4. disown -h以便在终端关闭时不会终止该过程。

  5. 键入exit以退出shell,因为现在您可以继续操作,因为操作将在后台运行,因此它不依赖于shell。

  6. 此过程相当于运行nohup SOMECOMMAND

答案 7 :(得分:2)

在我的AIX系统上,我试过

nohup -p  processid>

这很好用。即使在关闭终端窗口后,它仍继续运行我的过程。我们将ksh作为默认shell,因此bgdisown命令不起作用。

答案 8 :(得分:1)

  1. ctrl + z - 这会暂停作业(不会取消!)
  2. bg - 这会将作业置于后台并返回正在运行的过程
  3. disown -a - 这将删除所有与作业相关的附件(因此您可以关闭终端并且它仍会运行)
  4. 这些简单的步骤将允许您在保持流程运行的同时关闭终端。

    它不会nohup(根据我对你的问题的理解,你不需要它)。

答案 9 :(得分:1)

最简单,最简单的步骤

  1. Ctrl + Z ----------> 暂停该过程
  2. bg --------------> 恢复并运行后台
  3. disown %1 -------------> 仅当您需要与终端分离时才需要

答案 10 :(得分:0)

在tcshell中,这对我在Ubuntu linux上有用。

  1. Ctrl Z 暂停

  2. bg在后​​台运行

  3. jobs获取其职位编号

  4. nohup %n其中n是工作号