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

fly*_*ire 907 shell nohup

我有一个已经运行了很长时间并且不想结束它的进程.

我怎么把它放在nohup下(也就是说,即使关闭终端,如何让它继续运行?)

Nod*_*ode 1322

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

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

  • 问题是如何"把它置于nohup"之下,`disown -h`也许是更确切的答案:"使得disown表现得更像nohup(即作业将保留在当前shell的进程树中,直到你退出shell)这允许您查看此shell启动的所有作业." (来自[http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/]) (38认同)
  • 在"disown"之后,您无法看到作业的输出,disown使进程成为守护进程,这意味着标准输入/输出被重定向到/ dev/null.因此,如果您计划取消某项工作,最好通过登录文件来启动它,例如`my_job_command | tee my_job.log` (26认同)
  • `disown`解除了流程中的任何管道.要重新连接管道,请使用[this thread](http://unix.stackexchange.com/a/31830/11884)中所述的`gdb`.更具体地说,[这篇文章](http://etbe.coker.com.au/2008/02/27/redirecting-output-from-a-running-process/). (22认同)
  • 我如何以后恢复工作?我可以看到它使用ps -e运行. (8认同)
  • 有可能以某种方式做'my_job_command |之类的事情 tee my_job.log'_ after_命令已在运行? (7认同)
  • 为什么"jobspec"是一个前缀为`%`的工作号码?我在文档中找不到任何内容,任何人都可以给我指针吗? (4认同)
  • 如何在不知情的情况下"重新"一个过程? (4认同)
  • 很奇怪:在`disown -h%1`之后,我仍然在shell中看到进程的输出.这个过程看起来似乎是正确的nohup'd; 我可以关闭shell并继续运行.这是在Ubuntu 16 LTS上. (4认同)
  • @CoryKendall [这里有一些信息](http://structure.usc.edu/bash/bashref_7.html). (2认同)
  • @Node根据这个:http://unix.stackexchange.com/questions/3886/difference-between-nohup-disown-如果终端关闭并且程序试图从标准输入读取或从标准写入,则无效进程将失败输出. (2认同)

Pun*_*ngs 171

假设由于某种原因Ctrl+ Z也无法正常工作,请转到另一个终端,找到进程ID(使用ps)并运行:

kill -SIGSTOP PID 
kill -SIGCONT PID
Run Code Online (Sandbox Code Playgroud)

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

  • 是的,这就是操作系统问题,在Windows上使用Cygwin不能使用kill. (10认同)
  • 如果作业是从另一个ssh会话启动的话,也非常有用. (6认同)
  • 只需记住在关闭之前在第一个终端中执行`disown%1`. (5认同)
  • 这似乎不适用于Cygwin. (2认同)
  • 更容易记住的是“kill -SIGTSTP PID”和“kill -SIGCONT PID”。 (2认同)

ser*_*sam 90

将正在运行的作业与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选项将操作限制为正在运行的作业.除非jobspec未指定有效作业,否则返回值为0.

那意味着,这很简单

disown -a
Run Code Online (Sandbox Code Playgroud)

将删除作业表中的所有作业并使其成为nohup

  • `disown -a`删除所有工作.一个简单的`disown`只删除当前的工作.正如答案中的手册页所说. (9认同)

Q B*_*ler 71

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

你不能disown成为一个pid或过程,disown一个工作,这是一个重要的区别.

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

问题:

%  jobs
[1]  running java 
[2]  suspended vi
%  disown %1
Run Code Online (Sandbox Code Playgroud)

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


Dal*_*ale 45

遗憾的disown是特定于bash并且并非在所有shell中都可用.

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

nohup -p pid
Run Code Online (Sandbox Code Playgroud)

http://en.wikipedia.org/wiki/Nohup

  • 仅适用于“AIX”和“Solaris”。“nohup 的 AIX 和 Solaris 版本有一个 -p 选项,可以修改正在运行的进程以忽略未来的 SIGHUP 信号。与上述 disown 内置的 bash 不同,nohup -p 接受进程 ID。”。[来源](https://en.wikipedia.org/wiki/Nohup) (2认同)

Tru*_*ueY 25

Node的答案真的很棒,但它仍然提出了如何让stdout和stderr重定向的问题.我在Unix和Linux上找到了一个解决方案,但它也不完整.我想合并这两个解决方案.这里是:

对于我的测试,我创建了一个名为loop.sh的小bash脚本,它在无限循环中打印一小段睡眠.

$./loop.sh
Run Code Online (Sandbox Code Playgroud)

现在以某种方式得到这个过程的PID.通常ps -C loop.sh是足够好,但它打印在我的情况下.

现在我们可以切换到另一个终端(或按^ Z并在同一个终端).现在gdb应该附上这个过程.

$ gdb -p <PID>
Run Code Online (Sandbox Code Playgroud)

这会停止脚本(如果正在运行).它的状态可以通过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
Run Code Online (Sandbox Code Playgroud)

关闭(1)成功时返回零.

(gdb) call open("loop.out", 01102, 0600)
$6 = 1
Run Code Online (Sandbox Code Playgroud)

如果成功,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.

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

可以像使用O_APPEND那样打开输出文件nohup,但man open(2)由于可能存在NFS问题,因此不建议这样做.

如果我们得到-1作为返回值,则call perror("")打印错误消息.如果我们需要errno,请使用p errnogdb命令.

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

loop.sh <PID> truey    1u   REG   0,26        0 15008411 /home/truey/loop.out
Run Code Online (Sandbox Code Playgroud)

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

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

(gdb) detach
Detaching from program: /bin/bash, process <PID>
(gdb) q
Run Code Online (Sandbox Code Playgroud)

如果脚本gdb从另一个终端停止,它将继续运行.我们可以切换回loop.sh的终端.现在它不会向屏幕写任何内容,而是运行并写入文件.我们必须把它放到后台.所以按^Z.

^Z
[1]+  Stopped                 ./loop.sh
Run Code Online (Sandbox Code Playgroud)

(现在我们处于相同的状态,就像^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
Run Code Online (Sandbox Code Playgroud)

因此,进程应该在后台运行并从终端分离.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
Run Code Online (Sandbox Code Playgroud)

现在我们可以退出调用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)
Run Code Online (Sandbox Code Playgroud)

评论

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
Run Code Online (Sandbox Code Playgroud)

或者可以使用以下一个班轮代替:

gdb -q -ex 'call close(1)' -ex 'call open("loop.out", 01102, 0600)' -ex detach -ex quit -p <PID>
Run Code Online (Sandbox Code Playgroud)

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


Tho*_*ohn 20

简单且最容易的步骤

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


min*_*s23 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.

此过程相当于运行nohup SOMECOMMAND.


hi-*_*zir 5

  1. ctrl+ z - 这将暂停作业(不会取消!)
  2. bg- 这会将作业置于后台并在运行过程中返回
  3. disown -a- 这将切断作业的所有附件(因此您可以关闭终端,它仍然会运行)

这些简单的步骤将允许您关闭终端,同时保持进程运行。

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