我在前台运行一个应用程序,然后通过点击CTRL+ Z(并停止)将其置于后台。为了让它重新运行,我运行了命令bg %1
(这是它的 JOBSPEC)。
我想为什么不尝试让它运行回来kill -CONT <PID>
。所以,我跑去jobs -l
获取它的 PID,并将这个 pid 与带有 CONT 信号的 kill 一起使用。
然而,该节目并没有再次上线!jobs -l
尝试用 CONT 杀死后报告它正在运行,但它不是(因为它是灰色的)。
我使用命令查看了应用程序 PID ps
,发现两个具有不同 PID(和 status Tl
)的相同命令。
然后我查看了同样的东西pstree
,发现它们都在一个父进程下。父进程与列出的进程不同,jobs -l
因为我放在后台的似乎启动了另一个程序。另一个程序似乎创建了子进程。
我注意到的总结如下:
使用
kill
将 CONT 发送到父进程使程序运行。父进程 PID 与 报告的不同
jobs -l
。换句话说,我应该发送 CONT 信号的过程与我使用jobs -l
.向父进程发送 CONT 不会对子进程应用相同的信号。
使用命令
bg
返回一个进程运行,发送 CONT 信号给父进程的所有子进程。
我的结论正确吗?如果是这样,那么这意味着使用该命令bg
将节省向每个相关进程发送 CONT 的时间。这是正确的吗?
编辑我从命令行调用并放在后台的主要应用程序是git difftool
. 我正在谈论的另一个应用程序本身创建了新的子meld
节点,我将其设置为用作 git 中的差异工具。
首先,
jobs -l
不列出进程,而是列出进程组(又名作业)。每个进程组都有一个进程负责人,其进程 id (pid) 等于它的进程组 id (pgid)。为了向进程组中的所有进程发送信号,而不仅仅是向其领导者发送信号,您应该
kill
使用 pgid 的负数进行调用。这在 kill(2) 联机帮助页中有描述:在 shell 中也是如此:
现在,你的结论:
正确的
错了,是同一个pid,和它的pgid也是同一个。
正确的
是的,但前提是父进程和子进程都在同一个进程组中。此外,它不会为每个进程依次调用 kill(2),它只是使用 pgid 的负数(=进程组领导的 pid)调用它一次,并依赖内核将信号路由到所有进程在那个组。
我在这里看不到这种行为。
这是我的示例代码,在命令行中逐字输入:
收到
This is child xx
消息后,单击CtrlZ以暂停该过程。再等待 7 秒以确认它确实已暂停
现在
jobs -l
列出进程领导者(父 PID)。实际上,我们可以使用工作编号,在这种情况下%1
在后台继续该过程
kill -CONT %1
我看到孩子继续然后退出,让父母完成。
这是完整的运行结果(包括
>$
shell提示)如果您想进一步试验自动测试线束,您可以使用发送与键盘上
kill -TSTP ...
生成的信号相同的信号。CtrlZ