有没有办法让jobs -p
zsh 的行为与 bash 一样,即。给
仅有的一个数字,这样一个人可以做什么kill $(jobs -p)
?
答案1
jobs
有关作业的报告,作业可以有多个进程。
交互时,作业被放置在进程组中,因此它们可以作为一个整体挂起/恢复/中断。
jobs -p
(在 和 中zsh
)bash
返回每个作业的进程组 ID,而不是作业中所有进程的进程 ID。
当 shell 不以交互方式运行时(没有作业控制),shell 会报告进程的 pid,如果存在作业控制,该进程将成为进程组领导者(可能与返回的不同)$!
顺便一提)。
$ sleep 1 | sleep 20 &
[1] 29643 29644
$ jobs -p
[1] + 29643 done sleep 1 |
running sleep 20
zsh 报告,对于 pgid 29643 的作业 2,zsh 启动了 2 个进程,其中一个已完成,另一个仍在运行。
如果您只想像 in 那样获取 pgids bash
,您可以通过管道执行以下操作:
awk '/^\[/{print $3}'
如果你想获取作业中的pid(仅由shell启动的pid),你可以查看$jobstates
特殊的关联数组:
$ typeset jobstates
jobstates=( 1 'running:+:29643=done:29644=running' )
要提取仍在作业 1 中运行的进程的 pid:
$ echo ${${(M)${(s/:/)jobstates[1]}:#*=running}%=*}
29644
现在,如果您想终止这些作业,您需要终止进程组(在交互式 shell 中),即整个作业,而不是作业中随机的一个进程。
你可以用 来杀死 id 29643 的进程组kill -- -29643
,kill 29643
只会杀死过程id 29643(在上面的示例中已经失效)。
在这里,传递作业编号而不是 pid 或 pgid(在非交互式 shell 中不起作用)来杀死会更有意义。这就是职位编号的用途:
kill %${(k)^jobstates}
不幸的是,我认为bash
没有可靠的等价物。
bash-4.4$ sleep $(: '
> [213] ...') 2134 &
[1] 29856
bash-4.4$ jobs
[1]+ Running sleep $(: '
[213] ...') 2134 &
从中可靠地提取工作编号是很困难的。 (我还发现甚至while kill %; do continue; done
不起作用,因为看起来像是一些竞争条件错误)。
请注意,当不以交互方式运行时,没有作业控制,因此当您kill %1
终止 1 号作业时,该作业没有进程组。因此,作为穷人的近似,外壳程序(bash
和zsh
)将杀死每个进程它知道单独代替。在上面的示例中,而不是:
kill(-29643, SIGTERM);
它会做:
kill(29643, SIGTERM);
kill(29644, SIGTERM);
它不会杀死这两个进程自己生成的其他进程(如果有),尽管它仍然比像您的kill $(jobs -p)
方法中只杀死 29643 个要好。