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