使 zsh jobs -p 的行为与 bash 中一样

使 zsh jobs -p 的行为与 bash 中一样

有没有办法让jobs -pzsh 的行为与 bash 一样,即。给 仅有的一个数字,这样一个人可以做什么kill $(jobs -p)

答案1

jobs有关作业的报告,作业可以有多个进程。

交互时,作业被放置在进程组中,因此它们可以作为一个整体挂起/恢复/中断。

jobs -p(在 和 中zshbash返回每个作业的进程组 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 -- -29643kill 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 号作业时,该作业没有进程组。因此,作为穷人的近似,外壳程序(bashzsh)将杀死每个进程它知道单独代替。在上面的示例中,而不是:

kill(-29643, SIGTERM);

它会做:

kill(29643, SIGTERM);
kill(29644, SIGTERM);

它不会杀死这两个进程自己生成的其他进程(如果有),尽管它仍然比像您的kill $(jobs -p)方法中只杀死 29643 个要好。

相关内容