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

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

我怎么把它放在nohup下(即使closuresterminal机,我怎样才能使它继续运行?)

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

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

假设由于某种原因, Ctrl + Z也不起作用,转到另一个terminal,find进程ID(使用ps )并运行:

 kill -20 PID kill -18 PID 

kill -20SIGTSTP )将暂停进程并kill -18SIGCONT )将在后台恢复进程。 所以现在,closures你的terminal不会停止你的过程。

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

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

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

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

 nohup -p pid 

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

节点的答案真的很好,但是它留下了一个问题,怎样才能得到stdout和stderrredirect。 我在Unix和Linux上find了一个解决scheme,但它也不完整。 我想合并这两个解决scheme。 这里是:

对于我的testing,我做了一个名为loop.sh的小型bash脚本,它在无限循环中打印了一段时间的睡眠。

 $./loop.sh 

现在得到这个进程的PID不知何故。 通常ps -C loop.sh已经足够了,但是在我的情况下是打印的。

现在我们可以切换到另一个terminal(或按^ Z和在同一个terminal)。 现在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 

closures(1)成功返回零。

 (gdb) call open("loop.out", 01102, 0600) $6 = 1 

打开(1)如果成功则返回新的文件描述符。

这个开放与open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)相等open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR) 。 而不是O_RDWR O_WRONLY可以被应用,但是/usr/sbin/lsof表示'u'表示所有的std *文件处理程序( FD列),即O_RDWR

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

输出文件可以用O_APPEND打开,因为nohup会这样做,但这不是由man open(2) ,因为可能的NFS问题。

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

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

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

如果我们想要的话,如果我们想要使用call close(2)并使用不同的文件名再次call open(...) ,我们可以将stderrredirect到另一个文件。

现在附加的bash必须被释放,我们可以退出gdb

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

如果脚本被其他terminal的gdb停止,它将继续运行。 我们可以切换回loop.sh的terminal。 现在它不会写任何东西到屏幕上,而是运行并写入文件。 我们必须把它放到后台。 所以按^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 

所以程序应该在后台运行,并从terminal上分离。 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)进程)并且控制terminal变得未知。

 $ 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的东西可以自动化创build一个包含命令的文件(例如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 

或者可以使用下面的一个class轮代替:

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

我希望这是一个相当完整的解决scheme的描述。

发送正在运行的进程到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以便在terminalclosures时不会终止进程。

  5. 键入exit shell,因为现在你很好,因为这个操作将在后台运行,所以它不会绑定到shell。

这个过程相当于运行nohup SOMECOMMAND

在我的AIX系统上,我试过了

 nohup -p processid> 

这工作得很好。 即使closuresterminal窗口,它仍然继续运行我的过程。 我们有ksh作为默认shell,所以bgdisown命令不起作用。

这在我的Ubuntu Linux上,而在tcshell工作。

  1. Ctrl Z暂停它

  2. BG在后台运行

  3. 工作以获得工作号码

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