回答:
Ctrl+ を押すCと、SIGINT
シグナルがフォアグラウンドプロセスグループ全体に配信されます。ここでは、find
プロセスと呼び出し元のシェルプロセスの両方に送信されます。find
すぐに終了することで反応し、シェルはトラップを呼び出すことで反応します。
トラップ内のコードが戻る(つまりexit
、を呼び出さない)場合は、シグナルによって中断されたコマンドの後にコマンドが実行されます。ここでは、find
コマンドの後にスクリプトの終わりが来るため、スクリプトはとにかくすぐに終了します。しかし、別のコマンドを追加することで、0と1の入力の違いを確認できます。
find /
echo "find returned $?"
あなたがやりたいことができます; しかし、私の答えのこの部分は、実際の問題を解決することよりも、シェルプログラミングを発見することに関するものです。
あなたが殺害を回避したい場合find
、あなたはそれを起動する必要があり背景:find / &
。次に、wait
組み込みを使用して、正常に終了するのを待ちます。信号はwait
組み込みを中断します。これは、伝播する信号を受信するまでループで実行できます。次にkill
、ジョブを強制終了するために使用します。
hell () {
echo "Do you want to quit? Press 1 for yes and 0 for no"
read n
if [ "$n" = 1 ]; then
# Kill the job if it's running, then exit
if [ -n "$job_pid" ]; then kill $job_pid; fi
exit 1
fi
}
job_pid=
trap "hell" SIGINT
# Start a demo job in the background
for i in 1 2 3 4 5; do date; sleep 1; done &
job_pid=$!
# Call wait in a loop; wait will return 0 if the job exits, and 128+$signum if interrupted by a signal.
while ! wait; do
echo "resuming wait"
done
job_pid=
echo last exit code: $?
シェルのこのアプローチには制限があります。
job_pid=
$jobpid
wait
SIGCHLD
wait $job_pid
フォームを使用する必要があります。しかし、「wait
シグナルによって中断された」と「ジョブがシグナルによって強制終了された」(または「ジョブがリターンステータス≥128で終了したためにジョブが終了した」と区別することはできませんが、これはシェルの一般的な事実です)プログラミング)。これらの制限を克服するには、PerlやPythonなどのより洗練された言語を使用します。