web-dev-qa-db-ja.com

背景のサブシェルを制御する方法は?

Bashプロンプトで次のコマンドを実行した場合:

(for i in {1..100}; do echo $i; sleep 1; done) &

カウントが開始され、すぐにプロンプ​​トに戻ります。通常どおり作業を続けることができますが、毎秒、作業中のものの上に新しい番号が印刷されます。期待どおり、jobsfg/killでジョブを確認できます。

ここで、このコマンドを次のスクリプトに移動すると、test.sh

#!/usr/bin/bash
(for i in {1..100}; do echo $i; sleep 1; done) &

./test.shを実行すると、同じことが起こりますが、ジョブはjobsに表示されなくなり、fgできなくなります。 2番目の動作が最初の動作とまったく異なるのはなぜですか?2番目のジョブを制御するにはどうすればよいですか(PIDを見つけてそのように強制終了する以外)?

2
smitelli

その目的のためだけに、$!に配置されているPIDを追跡する必要があります。例えば。、

#!/usr/bin/bash

(sleep 30; echo "slept for 30 seconds") &
sleeping_pid=$!
# do something
kill $sleeping_pid # or you can wait on it, or...

$!は最近開始されたバックグラウンドジョブであることに注意してください。そのため、上書きされる傾向があるため、すぐに別の変数にコピーします。

3
derobert

私の特定のケースでは、test.sh内のサブシェルをグループコマンドに変更することで目標を達成することができました。

(for i in {1..100}; do echo $i; sleep 1; done) &

なりました

{ for i in {1..100}; do echo $i; sleep 1; done; } &

その後、すべてのジョブ制御機能を使用することができました。幸いなことに、サブシェルとグループコマンドはどちらも私の目的では基本的に同等ですが、すべての人に適しているとは限りません。

0
smitelli