スクリプトの対象:スクリプトは、./script.sh cmd1 cmd2 ... cmdn
バックグラウンドでコマンドラインから引数として渡されたすべてのコマンドを実行し、すべてのコマンドの実行が完了したことを確認する必要があります。また、SIGTERM信号がスクリプトに送信されたら、上記のすべてのプロセス(cmd1 ... cmdn
)を終了してからそれ自体を終了する必要があります。
質問:自動シャットダウンを除いて、すべてが機能しているようですが、理由がわかりません。を試してみましたが、kill $$
実行時に。コマンドが関数の内部にあるという事実に関連しているようsegmentation fault
ですが、コマンドをコメントアウトしてそのままにしておくと後者が機能します。誰かが私が逃したことを説明できますか?kill
kill $$
kill ${PIDAR[*]}
#!/bin/bash
# signal handler
killemall () {
echo $$
kill ${PIDAR[*]}
kill $$ # implicated line
}
PIDAR=() # pid array
STAR=() # process state array
# execute processes in bg and save their pid
for i in "$@" ; do
$i &
PIDAR+=($!)
done
trap 'killemall' SIGTERM
terminated=1 # flag to indicate when all processes are terminated
while sleep 1 && [ $terminated -eq 1 ]; do
for (( i=0; i<${#PIDAR[*]}; i++ )); do
STAR[$i]=$(ps hp ${PIDAR[$i]} | awk '{ print $3 }')
if [ -z ${STAR[$i]} ]; then
terminated=0
else terminated=1
fi
echo "Process state ${PIDAR[$i]}:${STAR[$i]}" | tee -a logg
done
done
echo "All processes are terminated"
ありがとう
解決策:user18197が指摘したように、問題はkill $$
実際にはkill
マニュアルページに報告されているように呼び出しにあります。
Killの基本信号はTERMです。
その後、呼び出されるkill $$
たびにスクリプトはハンドラを呼び出し、 killemall
ハンドラは繰り返し呼び出すkill $$
などの操作を実行します。この動作を防ぐためにSIGTERM
信号をキャプチャできます。レポートによるとhelp trap
:
ARGが存在しない場合(単一のSIGNAL_SPECが提供されている場合)、'-'の場合、指定された各信号は元の値にリセットされます。
したがって、新しい関数本体は次のようになります。
killemall () {
echo $$
trap - SIGTERM
kill ${PIDAR[@]}
kill $$
}
答え1
セグメントエラーを再現することはできませんが、SIGTERMを自分に送信すると、Killemall関数を再度呼び出し、SIGTERMを送信してKillemallを呼び出すと推測されます。
実際にスクリプトを終了するために何もする必要はありません。関数killemall
が呼び出され、完了するとスクリプトは終了します。必要に応じて、関数の末尾に追加してexit 0
より明確にすることができます。