9

バックグラウンドで別のスクリプトを起動して終了するスクリプトがあります。子スクリプトがなくなることを期待していましたが、最終的にはまだ何らかの出力を出力できます。次に例を示します。

スクリプト one.sh:

echo "this is one"
./two.sh &
sleep 1
pid=$!
kill $pid
echo "this was one"

スクリプト two.sh で:

echo "this is two"
./three.sh
echo "this was two"

スクリプト three.sh:

echo "this is three"
sleep 5
echo "this was three"

バックグラウンドで two.sh を実行するはずの ./one.sh を実行しました。これは、バックグラウンドではなく three.sh を実行します! 出力は次のとおりです。

this is one
this is two
this is three
this was one
this was three

three.sh がバックグラウンドで実行されず、two.sh が one.sh によって終了されたため、「this was three」は出力に表示されませんか? また、プロセスがバックグラウンドである場合 (そうでない場合) にどのように動作するか、およびプロセスが終了したときに何が起こるかを説明しているドキュメントを教えてください。

いつもお世話になっております!

4

3 に答える 3

0

これが意外に思える理由は、TERM シグナル ("kill" のデフォルト) が子プロセスに伝搬される、つまり、two.sh が受信した SIGTERM シグナル (シグナル #15) が伝搬されると予想されるからです。 three.shにも。ただし、実際にはそうではありません。two.sh を強制終了すると、単に three.sh が新しい親プロセスとして "init" プロセス (プロセス ID 1) に引き継がれ、init は three.sh が終了した後にクリーンアップします。

プロセス グループでは状況がさらに複雑になり、bash のドキュメントでは、キーボードで生成されたシグナルがフォアグラウンド プロセス グループ内のすべてのプロセスに送信される方法について説明されています。多くの場合、パイプラインは最後に「&」なしで実行されます。ただし、これらの問題はサンプル スクリプトには当てはまりません。

注: Unix では、実行可能スクリプトに「.sh」拡張子を使用しないでください。代わりに、正しい「#!/bin/bash」または「#!/bin/sh」を最初の行に置くことに注意してください。コマンドは、後で実装言語が変更されたときに間違ったものを残す必要がないように、コマンド名で実装言語を公開するべきではありませんが、他のコードは元の、現在は不適切な拡張子に依存するようになりました。

于 2013-06-28T21:47:12.237 に答える