我正在使用script.sh
包含cmd
在后台启动的命令的bash脚本:
#!/bin/bash
…
cmd &
…
如果我打开一个终端仿真器并运行script.sh
,cmd
则会按预期在后台正确执行。也就是说,虽然script.sh
已经结束,但cmd
继续在后台运行,并具有PPID 1。
但是,如果我打开另一个终端仿真程序(让说的xfce4终端)从以前的一个(或在桌面会话的开始,这是我的真实使用情况下),并执行script.sh
由
xfce4-terminal -H -x script.sh
cmd
不再正确执行:通过终止将其杀死script.sh
。仅使用nohup
阻止它是不够的。我必须在sleep
其后放置一个命令,否则,在与之分离之前会被cmd
终止而被杀死script.sh
。
我发现,做的唯一途径cmd
背景正确执行是把set -m
中script.sh
。为什么在这种情况下有必要,而不是第一个呢?为什么两种执行方式script.sh
(因此也是如此cmd
)之间的行为差异?
我假设在第一种情况下,未激活监视模式,就像通过输入可以看到的set -o
那样script.sh
。
您cmd
应该在其中运行的进程将被和SIGHUP
之间的信号杀死,任何包装程序或其他内容都将没有运行的机会,也不会产生任何效果。(您可以通过进行检查)fork()
exec()
nohup
strace
而不是nohup
,您应该在执行后台命令之前在父shell中设置SIGHUP
为SIG_IGN
(忽略);否则,您应该设置为(忽略)。如果信号处理程序设置为“忽略”或“默认”,则该处置将通过fork()
和继承exec()
。例子:
#! /bin/sh
trap '' HUP # ignore SIGHUP
xclock &
trap - HUP # back to default
或者:
#! /bin/sh
(trap '' HUP; xclock &)
如果您使用来运行此脚本xfce4-terminal -H -x script.sh
,则终止时,后台命令(xclock &
)不会被SIGHUP
发送的消息杀死script.sh
。
当会话负责人(script.sh
在您的情况下,一个“拥有”控制终端的进程)终止时,内核将SIGHUP
向其前台进程组中的所有进程发送a消息。但是set -m
将启用作业控制,并且以开头的命令&
将被放入后台进程组,并且不会通过发出信号SIGHUP
。
如果未启用作业控制(非交互式脚本的默认设置),则以开头的命令&
将在同一前台进程组中运行,并且通过从中重定向输入/dev/null
并让其忽略 SIGINT
和来伪造“后台”模式SIGQUIT
。
进程从曾经作为前台作业运行但已经退出的脚本启动SIGHUP
,因为它们的进程组(从其死去的父级继承)不再是终端上的前台进程,因此不会发出任何信号。
额外说明:
xterm
和之间xfce4-terminal
(可能还有其他基于vte的终端)之间的“保持模式”似乎有所不同。前者将使pty的主端保持打开状态,而后者将在使用-e
或-x
已退出的程序运行后将其断开,从而导致对从属端的任何写入操作均失败EIO
。当前台进程组中仍有进程正在运行时,它们xterm
还将忽略WM_DELETE_WINDOW
消息(即,它不会关闭)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句