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 -- -29643
。kill 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を終了するよりも優れています。