如何将已经运行的进程置于 nohup 下?

发布于 2024-07-14 22:00:58 字数 72 浏览 14 评论 0原文

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

如何将其放在nohup下(即如何使其即使关闭终端也继续运行?)

I have a process that is already running for a long time and don't want to end it.

How do I put it under nohup (that is, how do I cause it to continue running even if I close the terminal?)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

回首观望 2024-07-21 22:00:58

使用 bash 的作业控制将进程发送到后台:

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

Using the Job Control of bash to send the process into the background:

  1. Ctrl+Z to stop (pause) the program and get back to the shell.
  2. bg to run it in the background.
  3. disown -h [job-spec] where [job-spec] is the job number (like %1 for the first running job; find about your number with the jobs command) so that the job isn't killed when the terminal closes.
想挽留 2024-07-21 22:00:58

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

kill -SIGSTOP PID 
kill -SIGCONT PID

< code>SIGSTOP 将暂停进程,SIGCONT 将在后台恢复进程。 所以现在,关闭两个终端不会停止您的进程。

Suppose for some reason Ctrl+Z is also not working, go to another terminal, find the process id (using ps) and run:

kill -SIGSTOP PID 
kill -SIGCONT PID

SIGSTOP will suspend the process and SIGCONT will resume the process, in background. So now, closing both your terminals won't stop your process.

寄意 2024-07-21 22:00:58

将正在运行的作业与 shell 分离的命令(= 使其为 nohup)是 disown,它是一个基本的 shell 命令。

来自 bash 手册页 (man bash):

否认[-ar] [-h] [工作规范...]

如果没有选项,每个作业规范都会从活动作业表中删除。 如果给出了 -h 选项,则每个作业规范都不是
从表中删除,但已标记,以便如果 shell 收到 SIGHUP,则不会将 SIGHUP 发送到作业。 如果没有工作规范
如果存在,且未提供 -a 和 -r 选项,则使用当前作业。 如果未提供作业规范,则 -a 选项
指删除或标记所有作业; 不带 jobspec 参数的 -r 选项将操作限制为正在运行的作业。 回报
除非作业规范未指定有效作业,否则值为 0。

这意味着,一个简单的操作

disown -a

将从作业表中删除所有作业并使它们成为 nohup

The command to separate a running job from the shell ( = makes it nohup) is disown and a basic shell-command.

From bash-manpage (man bash):

disown [-ar] [-h] [jobspec ...]

Without options, each jobspec is removed from the table of active jobs. If the -h option is given, each jobspec is not
removed from the table, but is marked so that SIGHUP is not sent to the job if the shell receives a SIGHUP. If no jobspec is
present, and neither the -a nor the -r option is supplied, the current job is used. If no jobspec is supplied, the -a option
means to remove or mark all jobs; the -r option without a jobspec argument restricts operation to running jobs. The return
value is 0 unless a jobspec does not specify a valid job.

That means, that a simple

disown -a

will remove all jobs from the job-table and makes them nohup

伪装你 2024-07-21 22:00:58

上面这些都是很好的答案,我只是想添加一个说明:

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

作业是附加到 shell 的进程的概念,因此您必须将作业放入后台(而不是挂起它),然后放弃它。

问题:

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

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

These are good answers above, I just wanted to add a clarification:

You can't disown a pid or process, you disown a job, and that is an important distinction.

A job is something that is a notion of a process that is attached to a shell, therefore you have to throw the job into the background (not suspend it) and then disown it.

Issue:

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

See http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/
for a more detailed discussion of Unix Job Control.

能怎样 2024-07-21 22:00:58

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

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

nohup -p pid

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

Unfortunately disown is specific to bash and not available in all shells.

Certain flavours of Unix (e.g. AIX and Solaris) have an option on the nohup command itself which can be applied to a running process:

nohup -p pid

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

情绪少女 2024-07-21 22:00:58

Node 的答案确实很棒,但它留下了一个悬而未决的问题:如何重定向 stdout 和 stderr。 我在 Unix & 上找到了解决方案 Linux,但它还不完整。 我想合并这两个解决方案。 它是这样的:

为了我的测试,我制作了一个名为loop.sh的小bash脚本,它在无限循环中打印它自己的pid并进行一分钟的睡眠。

$./loop.sh

现在以某种方式获取该进程的 PID。 通常 ps -C Loop.sh 就足够了,但在我的情况下它被打印了。

现在我们可以切换到另一个终端(或在同一终端中按 ^Z )。 现在 gdb 应该附加到这个进程。

$ gdb -p <PID>

这将停止脚本(如果正在运行)。 可以通过 ps -f 检查其状态,其中 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

Close(1) 成功时返回零。

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

如果成功,Open(1) 返回新的文件描述符。

此 open 等同于 open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)
可以应用 O_RDWR O_WRONLY,但 /usr/sbin/lsof 表示所有 std* 文件处理程序为“u”(FD 列),即 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

如果我们愿意,我们可以将 stderr 重定向到另一个文件,如果我们想使用 call close(2)并使用不同的文件名再次调用 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)

注释

gdb 的东西可以自动创建一个包含命令的文件(例如loop.gdb)并运行gdb -q -x Loop.gdb -p。 我的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>

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

Node's answer is really great, but it left open the question how can get stdout and stderr redirected. I found a solution on Unix & Linux, but it is also not complete. I would like to merge these two solutions. Here it is:

For my test I made a small bash script called loop.sh, which prints the pid of itself with a minute sleep in an infinite loop.

$./loop.sh

Now get the PID of this process somehow. Usually ps -C loop.sh is good enough, but it is printed in my case.

Now we can switch to another terminal (or press ^Z and in the same terminal). Now gdb should be attached to this process.

$ gdb -p <PID>

This stops the script (if running). Its state can be checked by ps -f <PID>, where the STAT field is 'T+' (or in case of ^Z 'T'), which means (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

Close(1) returns zero on success.

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

Open(1) returns the new file descriptor if successful.

This open is equal with open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR).
Instead of O_RDWR O_WRONLY could be applied, but /usr/sbin/lsof says 'u' for all std* file handlers (FD column), which is O_RDWR.

I checked the values in /usr/include/bits/fcntl.h header file.

The output file could be opened with O_APPEND, as nohup would do, but this is not suggested by man open(2), because of possible NFS problems.

If we get -1 as a return value, then call perror("") prints the error message. If we need the errno, use p errno gdb comand.

Now we can check the newly redirected file. /usr/sbin/lsof -p <PID> prints:

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

If we want, we can redirect stderr to another file, if we want to using call close(2) and call open(...) again using a different file name.

Now the attached bash has to be released and we can quit gdb:

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

If the script was stopped by gdb from an other terminal it continues to run. We can switch back to loop.sh's terminal. Now it does not write anything to the screen, but running and writing into the file. We have to put it into the background. So press ^Z.

^Z
[1]+  Stopped                 ./loop.sh

(Now we are in the same state as if ^Z was pressed at the beginning.)

Now we can check the state of the job:

$ 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

So process should be running in the background and detached from the terminal. The number in the jobs command's output in square brackets identifies the job inside bash. We can use in the following built in bash commands applying a '%' sign before the job number :

$ 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

And now we can quit from the calling bash. The process continues running in the background. If we quit its PPID become 1 (init(1) process) and the control terminal become unknown.

$ 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

The gdb stuff can be automatized creating a file (e.g. loop.gdb) containing the commands and run gdb -q -x loop.gdb -p <PID>. My loop.gdb looks like this:

call close(1)
call open("loop.out", 01102, 0600)
# call close(2)
# call open("loop.err", 01102, 0600)
detach
quit

Or one can use the following one liner instead:

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

I hope this is a fairly complete description of the solution.

画离情绘悲伤 2024-07-21 22:00:58

简单且最简单的步骤

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

Simple and easiest steps

  1. Ctrl + Z ----------> Suspends the process
  2. bg --------------> Resumes and runs background
  3. disown %1 -------------> required only if you need to detach from the terminal
苏别ゝ 2024-07-21 22:00:58

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

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

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

  1. 运行一些命令,
    /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

To send running process to nohup (http://en.wikipedia.org/wiki/Nohup)

nohup -p pid , it did not worked for me

Then I tried the following commands and it worked very fine

  1. Run some SOMECOMMAND,
    say /usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1.

  2. Ctrl+Z to stop (pause) the program and get back to the shell.

  3. bg to run it in the background.

  4. disown -h so that the process isn't killed when the terminal closes.

  5. Type exit to get out of the shell because now you're good to go as the operation will run in the background in its own process, so it's not tied to a shell.

This process is the equivalent of running nohup SOMECOMMAND.

北渚 2024-07-21 22:00:58
  1. ctrl + z - 这将暂停作业(不会取消!)
  2. bg - 这将使作业进入后台并返回运行状态process
  3. disown -a - 这将剪切作业的所有附件(因此您可以关闭终端,它仍然会运行)

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

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

  1. ctrl + z - this will pause the job (not going to cancel!)
  2. bg - this will put the job in background and return in running process
  3. disown -a - this will cut all the attachment with job (so you can close the terminal and it will still run)

These simple steps will allow you to close the terminal while keeping process running.

It wont put on nohup (based on my understanding of your question, you don't need it here).

顾忌 2024-07-21 22:00:58

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

nohup -p  processid>

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

On my AIX system, I tried

nohup -p  processid>

This worked well. It continued to run my process even after closing terminal windows. We have ksh as default shell so the bg and disown commands didn't work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文