我正在前台运行一个应用程序,然后通过按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 中的比较工具。
答案1
首先,jobs -l
没有列出进程,但是进程组(又名工作)。每个进程组都有一个进程领导者,其进程ID(pid)等于其进程组ID(pgid)。
为了向进程组中的所有进程发送信号,而不仅仅是向其领导者发送信号,您应该kill
使用 pgid 的负数进行调用。 Kill(2) 联机帮助页对此进行了描述:
如果pid小于-1,则将sig发送到进程组中ID为-pid的每个进程。
在 shell 中也有同样的作用:
$ sh -c 'while echo -n 1; do sleep 1; done'
111^Z
[1]+ Stopped sh -c 'while echo -n 1; do sleep 1; done'
$ jobs -l
[1]+ 11046 Stopped sh -c 'while echo -n 1; do sleep 1; done'
$ kill -CONT 11046
<nothing>
$ kill -CONT -11046
$ 11111111...
现在,得出你的结论:
使用kill 向父进程发送CONT 使程序运行。
正确的
父进程 PID 与 jobs -l 报告的 PID 不同。换句话说,我应该发送 CONT 信号的进程与我使用 jobs -l 找到的进程不同。
错了,是同一个pid,也和它的pgid一样。
向父进程发送 CONT 不会对子进程应用相同的信号。
正确的
使用命令 bg 使进程返回运行状态,向父进程及其所有子进程发送 CONT 信号。
是的,但前提是父进程和子进程都在同一个进程组中。另外,它不会依次为每个进程调用kill(2),它只是使用pgid(=进程组领导者的pid)的负数调用一次,并依赖内核将信号路由到所有进程在那个组里。
答案2
我在这里没有看到这种行为。
这是我的示例代码,在命令行中逐字输入:
bash -c 'echo This is parent $$; sleep 7; bash -c "echo This is child \$$; sleep 7; echo Child done"; echo This is parent $$ again; sleep 7'
一旦收到消息
This is child xx
,请点击CtrlZ暂停该进程。再等待 7 秒以确认它确实已暂停
现在
jobs -l
列出进程领导者(父PID)。实际上,我们可以使用职位编号,在本例中%1
在后台继续该过程
kill -CONT %1
我看到孩子继续然后退出,让家长完成。
这是完整的运行结果(包括>$
shell提示)
>$ bash -c 'echo This is parent $$; sleep 7; bash -c "echo This is child \$$; sleep 7; echo Child done"; echo This is parent $$ again; sleep 7'
This is parent 2004
This is child 10696
[1]+ Stopped bash -c 'echo This is parent $$; sleep 7; bash -c "echo This is child \$$; sleep 7; echo Child done"; echo This is parent $$ again; sleep 7'
>$ jobs -l
[1]+ 2004 Stopped bash -c 'echo This is parent $$; sleep 7; bash -c "echo This is child \$$; sleep 7; echo Child done"; echo This is parent $$ again; sleep 7'
>$ kill -CONT %1
>$ Child done
This is parent 2004 again
如果您想进一步尝试自动测试工具,您可以使用发送与键盘上kill -TSTP ...
生成的信号相同的信号。CtrlZ