我有一个已经运行很长时间并且不想结束它的进程 .
我怎么把它放在nohup下(也就是说,即使关闭终端,如何让它继续运行?)
假设由于某种原因Ctrl Z也不起作用,转到另一个终端,找到进程ID(使用 ps )并运行:
ps
kill -20 PID kill -18 PID
kill -20 ( SIGTSTP )将暂停该过程, kill -18 ( SIGCONT )将在后台恢复该过程 . 所以现在,关闭两个终端并不会停止你的过程 .
kill -20
SIGTSTP
kill -18
SIGCONT
ctrl z - 这将暂停作业(不会取消!)
bg - 这会将作业放在后台并在运行过程中返回
bg
disown -a - 这将切断作业的所有附件(这样你就可以关闭终端,它仍会运行)
disown -a
这些简单的步骤将允许您在保持进程运行的同时关闭终端 .
它不会穿上 nohup (基于我对你的问题的理解,你在这里不需要它) .
nohup
将正在运行的作业与shell分离的命令(=使其成为nohup)是 disown 和一个基本的shell命令 .
disown
从bash-manpage(man bash):
disown [-ar] [-h] [jobspec ...]如果没有选项,每个jobspec都会从活动作业表中删除 . 如果给出-h选项,则不会从表中删除每个jobspec,但会对其进行标记,以便在shell收到SIGHUP时不会将SIGHUP发送到作业 . 如果不存在jobspec,并且既未提供-a选项也未提供-r选项,则使用当前作业 . 如果未提供jobspec,则-a选项表示删除或标记所有作业;没有jobspec参数的-r选项将操作限制为正在运行的作业 . 除非jobspec未指定有效作业,否则返回值为0 .
那意味着,这很简单
将删除作业表中的所有作业并使其成为nohup
Node的答案真的很棒,但它仍然提出了如何让stdout和stderr重定向的问题 . 我在Unix & Linux上找到了一个解决方案,但它也没有完整 . 我想合并这两个解决方案 . 这里是:
对于我的测试,我创建了一个名为loop.sh的小bash脚本,它在无限循环中打印一小段睡眠 .
$./loop.sh
现在以某种方式得到这个过程的PID . 通常 ps -C loop.sh 已经足够好了,但它是在我的情况下打印的 .
ps -C loop.sh
现在我们可以切换到另一个终端(或按^ Z并在同一个终端) . 现在 gdb 应该附加到这个过程 .
gdb
$ gdb -p <PID>
这会停止脚本(如果正在运行) . 它的状态可以通过 ps -f <PID> 检查,其中 STAT 字段是'T+'(或者在^ Z 'T'的情况下),这意味着(man ps(1))
ps -f <PID>
STAT
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 .
open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)
O_RDWR
O_WRONLY
/usr/sbin/lsof
FD
我检查了/usr/include/bits/fcntl.h头文件中的值 .
输出文件可以使用 O_APPEND 打开,如 nohup 那样,但 man open(2) 不建议这样做,因为可能存在NFS问题 .
O_APPEND
man open(2)
如果我们得到-1作为返回值,则 call perror("") 打印错误消息 . 如果我们需要errno,请使用 p errno gdb命令 .
call perror("")
p errno
现在我们可以检查新重定向的文件 . /usr/sbin/lsof -p <PID> 打印:
/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(...) .
call close(2)
call open(...)
现在附件 bash 必须被释放,我们可以退出 gdb :
bash
(gdb) detach Detaching from program: /bin/bash, process <PID> (gdb) q
如果脚本被 gdb 从另一个终端停止,它将继续运行 . 我们可以切换回loop.sh的终端 . 现在它不会向屏幕写任何内容,而是运行并写入文件 . 我们必须把它放到后台 . 所以按 ^Z .
^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 命令中使用在作业号之前应用'%'符号:
jobs
$ 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看起来像这样:
gdb -q -x loop.gdb -p <PID>
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>
我希望这是对解决方案的完整描述 .
这些都是上面的好答案,我只是想补充说明:
你不能 disown 一个pid或过程,你是一份工作,这是一个重要的区别 .
作业是附加到shell的进程的概念,因此您必须将作业放入后台(而不是暂停它)然后将其取消 .
问题:
% jobs [1] running java [2] suspended vi % disown %1
有关Unix作业控制的更详细讨论,请参阅http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/ .
使用bash的Job Control将进程发送到后台:
Ctrl Z.停止(暂停)程序并返回shell .
bg 在后台运行它 .
disown -h [job-spec] 其中[job-spec]是作业编号(如第一个正在运行的作业的 %1 ;使用 jobs 命令查找您的编号),以便在终端关闭时不会终止作业 .
disown -h [job-spec]
%1
将运行进程发送到nohup(http://en.wikipedia.org/wiki/Nohup)
nohup -p pid ,它对我不起作用
nohup -p pid
然后我尝试了以下命令,它工作得很好
运行一些SOMECOMMAND,比如 /usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1 .
/usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1
Ctrl Z停止(暂停)程序并返回shell .
disown -h 以便终端关闭时不会终止进程 .
disown -h
键入 exit 以退出shell,因为现在你're good to go as the operation will run in the background in its own process, so it'没有绑定到shell .
exit
此过程相当于运行 nohup SOMECOMMAND .
nohup SOMECOMMAND
在tcshell中,这对我在Ubuntu linux上工作 .
CtrlZ暂停它
bg 在后台运行
jobs 获取其工作号码
nohup %n 其中n是作业编号
nohup %n
遗憾的是 disown 特定于bash并且并非在所有shell中都可用 .
某些类型的Unix(例如AIX和Solaris)在 nohup 命令本身上有一个选项,可以应用于正在运行的进程:
见http://en.wikipedia.org/wiki/Nohup
在我的AIX系统上,我试过了
nohup -p processid>
这很好用 . 即使在关闭终端窗口后,它仍继续运行我的过程 . 我们将ksh作为默认shell,因此 bg 和 disown 命令不起作用 .
10 回答
假设由于某种原因Ctrl Z也不起作用,转到另一个终端,找到进程ID(使用
ps
)并运行:kill -20
(SIGTSTP
)将暂停该过程,kill -18
(SIGCONT
)将在后台恢复该过程 . 所以现在,关闭两个终端并不会停止你的过程 .ctrl z - 这将暂停作业(不会取消!)
bg
- 这会将作业放在后台并在运行过程中返回disown -a
- 这将切断作业的所有附件(这样你就可以关闭终端,它仍会运行)这些简单的步骤将允许您在保持进程运行的同时关闭终端 .
它不会穿上
nohup
(基于我对你的问题的理解,你在这里不需要它) .将正在运行的作业与shell分离的命令(=使其成为nohup)是
disown
和一个基本的shell命令 .从bash-manpage(man bash):
那意味着,这很简单
将删除作业表中的所有作业并使其成为nohup
Node的答案真的很棒,但它仍然提出了如何让stdout和stderr重定向的问题 . 我在Unix & Linux上找到了一个解决方案,但它也没有完整 . 我想合并这两个解决方案 . 这里是:
对于我的测试,我创建了一个名为loop.sh的小bash脚本,它在无限循环中打印一小段睡眠 .
现在以某种方式得到这个过程的PID . 通常
ps -C loop.sh
已经足够好了,但它是在我的情况下打印的 .现在我们可以切换到另一个终端(或按^ Z并在同一个终端) . 现在
gdb
应该附加到这个过程 .这会停止脚本(如果正在运行) . 它的状态可以通过
ps -f <PID>
检查,其中STAT
字段是'T+'(或者在^ Z 'T'的情况下),这意味着(man ps(1))关闭(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
.我检查了/usr/include/bits/fcntl.h头文件中的值 .
输出文件可以使用
O_APPEND
打开,如nohup
那样,但man open(2)
不建议这样做,因为可能存在NFS问题 .如果我们得到-1作为返回值,则
call perror("")
打印错误消息 . 如果我们需要errno,请使用p errno
gdb命令 .现在我们可以检查新重定向的文件 .
/usr/sbin/lsof -p <PID>
打印:如果我们想要,我们可以将stderr重定向到另一个文件,如果我们想要使用不同的文件名再次使用
call close(2)
和call open(...)
.现在附件
bash
必须被释放,我们可以退出gdb
:如果脚本被
gdb
从另一个终端停止,它将继续运行 . 我们可以切换回loop.sh的终端 . 现在它不会向屏幕写任何内容,而是运行并写入文件 . 我们必须把它放到后台 . 所以按^Z
.(现在我们处于相同的状态,就像
^Z
在开始时被按下一样 . )现在我们可以检查工作状态:
因此,进程应该在后台运行并从终端分离 . 方括号中
jobs
命令输出中的数字标识bash
中的作业 . 我们可以在以下内置bash
命令中使用在作业号之前应用'%'符号:现在我们可以退出调用bash . 该过程继续在后台运行 . 如果我们退出它的PPID变为1(init(1)进程)并且控制终端变得未知 .
COMMENT
gdb的东西可以自动化,创建一个包含命令的文件(例如loop.gdb)并运行
gdb -q -x loop.gdb -p <PID>
. 我的loop.gdb看起来像这样:或者可以使用以下一个班轮代替:
我希望这是对解决方案的完整描述 .
这些都是上面的好答案,我只是想补充说明:
你不能
disown
一个pid或过程,你是一份工作,这是一个重要的区别 .作业是附加到shell的进程的概念,因此您必须将作业放入后台(而不是暂停它)然后将其取消 .
问题:
有关Unix作业控制的更详细讨论,请参阅http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/ .
使用bash的Job Control将进程发送到后台:
Ctrl Z.停止(暂停)程序并返回shell .
bg
在后台运行它 .disown -h [job-spec]
其中[job-spec]是作业编号(如第一个正在运行的作业的%1
;使用jobs
命令查找您的编号),以便在终端关闭时不会终止作业 .将运行进程发送到nohup(http://en.wikipedia.org/wiki/Nohup)
nohup -p pid
,它对我不起作用然后我尝试了以下命令,它工作得很好
运行一些SOMECOMMAND,比如
/usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1
.Ctrl Z停止(暂停)程序并返回shell .
bg
在后台运行它 .disown -h
以便终端关闭时不会终止进程 .键入
exit
以退出shell,因为现在你're good to go as the operation will run in the background in its own process, so it'没有绑定到shell .此过程相当于运行
nohup SOMECOMMAND
.在tcshell中,这对我在Ubuntu linux上工作 .
CtrlZ暂停它
bg
在后台运行jobs
获取其工作号码nohup %n
其中n是作业编号遗憾的是
disown
特定于bash并且并非在所有shell中都可用 .某些类型的Unix(例如AIX和Solaris)在
nohup
命令本身上有一个选项,可以应用于正在运行的进程:见http://en.wikipedia.org/wiki/Nohup
在我的AIX系统上,我试过了
这很好用 . 即使在关闭终端窗口后,它仍继续运行我的过程 . 我们将ksh作为默认shell,因此
bg
和disown
命令不起作用 .