Answers:
使用bash 的作业控制将流程发送到后台:
bg
在后台运行它。disown -h [job-spec]
其中,[job-spec]是作业编号(如%1
第一个正在运行的作业;请使用jobs
命令查找您的编号),以便在终端关闭时不会终止该作业。disown -h
可能是更准确的答案:“使disown行为更像nohup(即,作业将保留在当前shell的进程树中,直到退出shell)为止。这个Shell开始的所有工作。” (从[ quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/...)
disown
,disown使进程成为守护程序之后,您看不到作业的输出,这意味着标准输入/输出被重定向到/ dev / null。因此,如果您打算my_job_command | tee my_job.log
假设由于某种原因Ctrl+ Z也无法正常工作,请转到另一个终端,找到进程ID(使用ps
)并运行:
kill -SIGSTOP PID
kill -SIGCONT PID
SIGSTOP
将暂停该过程并SIGCONT
在后台继续该过程。因此,现在关闭两个终端都不会停止您的过程。
disown %1
在关闭它之前在第一个终端中执行即可。
kwin
,崩溃后我从konsole开始,不考虑后果)。因此,如果我停止了kwin,一切都会冻结,并且我将无法运行bg
!
从外壳程序中分离正在运行的作业的命令(=使之成为nohup)是disown
一个基本的外壳程序命令。
从bash-manpage(man bash):
放弃[-ar] [-h] [jobspec ...]
如果没有选项,则会从活动作业表中删除每个作业规范。如果给出了-h选项,则不会从表中删除每个jobspec,而是对其进行标记,以便在外壳程序收到SIGHUP时不将SIGHUP发送给该作业。如果不存在jobspec,并且-a和-r选项均未提供,则使用当前作业。如果未提供jobspec,则-a选项表示删除或标记所有作业;不带jobspec参数的-r选项将操作限制为正在运行的作业。除非jobspec没有指定有效的作业,否则返回值为0。
这意味着,一个简单的
disown -a
将从作业表中删除所有作业,并使它们不再工作
disown -a
删除所有作业。简单disown
仅删除当前作业。正如答案中的手册页所述。
这些是上面的好答案,我只想添加一个说明:
您不能disown
是pid或流程,您不能disown
是工作,那是重要的区别。
作业是连接到Shell的进程的概念,因此您必须将作业置于后台(而不是挂起),然后将其丢弃。
问题:
% jobs
[1] running java
[2] suspended vi
% disown %1
有关 Unix Job Control的详细讨论,请参见http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/。
不幸的disown
是特定于bash,并非在所有shell中都可用。
某些类型的Unix(例如AIX和Solaris)在nohup
命令本身上具有一个选项,可以将其应用于正在运行的进程:
nohup -p pid
AIX
和Solaris
。“ AIX和Solaris版本的nohup具有-p选项,该选项修改正在运行的进程以忽略将来的SIGHUP信号。与上述bash内置的disown内置程序不同,nohup -p接受进程ID。” 消息来源
Node的回答确实很棒,但是却悬而未决的问题是如何使stdout和stderr重定向。我在Unix&Linux上找到了一个解决方案,但是它也不完整。我想将这两种解决方案合并。这里是:
在我的测试中,我制作了一个名为loop.sh的小型bash脚本,该脚本在无限循环中休眠一分钟即可显示自身的pid。
$./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
如果成功,Close(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
。
我检查了/usr/include/bits/fcntl.h头文件中的值。
输出文件可以与被打开O_APPEND
,因为nohup
会做,但这不是建议man open(2)
,因为可能的NFS问题。
如果我们得到-1作为返回值,则call perror("")
输出错误消息。如果需要errno,请使用p errno
gdb comand。
现在我们可以检查新重定向的文件了。/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)
评论
可以自动创建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>
我希望这是该解决方案的相当完整的描述。
lsof
(文件句柄的名称是pipe
,而不是/dev/pts/1
)还是通过ls -l /proc/<PID>/fd/<fd>
(这显示了句柄的符号链接)重定向了句柄。同样,子流程仍然不能重定向输出,应该将其重定向到文件。
要将运行过程发送到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停止(暂停)程序并返回外壳。
bg
在后台运行它。
disown -h
这样在终端关闭时不会终止该进程。
键入exit
以退出shell,因为现在您可以进行操作了,因为该操作将在其自己的进程中在后台运行,因此它与shell无关。
这个过程相当于运行nohup SOMECOMMAND
。
在tcshell中,这在Ubuntu Linux上对我有用。
CtrlZ 暂停它
bg
在后台运行
jobs
得到它的工作号
nohup %n
其中n是工作编号
nohup: failed to run command '%1': No such file or directory
yourExecutable &
并且输出不断出现在屏幕上,并且Ctrl+C
似乎没有停止任何操作,即使屏幕正在滚动显示输出,您也只能盲目地键入disown;
并按一下Enter
,而您看不到什么您正在输入。该过程将被取消,您将可以关闭终端而该过程不会终止。