zsh ジョブ -p が bash のように動作するようにする

zsh ジョブ -p が bash のように動作するようにする

zshをbashのように動作させる方法はありますかjobs -p?与える ただ数字、そのような人は何ができますかkill $(jobs -p)

ベストアンサー1

jobsジョブに関するレポート、ジョブには複数のプロセスがあります。

対話型の場合、ジョブはプロセスグループに配置されるため、全体として一時停止/再開/中断することができます。

jobs -p(およびzsh)は、bashジョブ内のすべてのプロセスのプロセスIDではなく、各ジョブのプロセスグループIDを返します。

シェルが(ジョブ制御なしで)対話的に実行されていない場合、シェルはジョブ制御がある場合にプロセスグループリーダーになるプロセスのpidを報告します($!btwで返されるものとは異なる場合があります)。

$ sleep 1 | sleep 20 &
[1] 29643 29644
$ jobs -p
[1]  + 29643 done       sleep 1 |
             running    sleep 20

zshはpgid 29643のタスク2に対してzshが2つのプロセスを開始し、そのうちの1つが完了し、もう1つがまだ実行中であることを報告します。

のようなpgidを取得するには、パイプを介してbashこれを行うことができます。

awk '/^\[/{print $3}'

タスク内でpidを取得するには(シェルで始まるpidのみ)、$jobstates特別な連想配列を見るだけです。

$ typeset jobstates
jobstates=( 1 'running:+:29643=done:29644=running' )

タスク1でまだ実行されているプロセスのpidを抽出するには、次の手順を実行します。

$ echo ${${(M)${(s/:/)jobstates[1]}:#*=running}%=*}
29644

これらのタスクを終了するには、プロセスグループ(対話型シェル)、つまりタスク内の任意のプロセスではなく、タスク全体を終了する必要があります。

これを使用して、ID 29643のプロセスグループを終了できますkill -- -29643kill 29643プロセスID 29643(上記の例では無効)

ここでは、pidまたはpgid(非対話型シェルでは機能しません)ではなく、killするジョブ番号を渡す方が合理的です。ジョブ番号は次のとおりです。

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);

これら2つのプロセスが独自に作成された他のプロセスは終了しませんが(存在する場合)、アプローチと同様にkill $(jobs -p)29643を終了するよりも優れています。

おすすめ記事