(信号の番号だけがあり、名前が必要な場合は、 kill -l $SIGNAL_NUM
シグナルの名前を出力します。 trap
の呼び出しで番号の代わりにシグナル名を使用することで、これを回避できます。 以下のように。)
This answerは、シグナル名にアクセスする方法がないことを示していますが、トラップするシグナルごとに個別の関数がある場合、シグナル名はすでにわかっています:
trap 'echo trapped the HUP signal' HUP
trap 'echo different trap for the INT signal' INT
多くの場合、それで十分かもしれませんが、同じ質問に対する別の回答では、その事実を使用して、必要な動作を偽造するための回避策を提供しています。関数とシグナルのリストを取り、シグナル名で呼び出されたその関数のシグナルごとに個別のトラップを設定するため、内部的には実際にはシグナルごとに個別の関数ですが、引数としてのシグナル名:
コード:
#!/bin/bash
trap_with_arg() {
func="$1" ; shift
for sig ; do
trap "$func $sig" "$sig"
done
}
func_trap() {
echo "Trapped: $1"
}
trap_with_arg func_trap INT TERM EXIT
echo "Send signals to PID $$ and type [enter] when done."
read # Wait so the script doesn't exit.
それを実行すると、プロセスにシグナルを送信でき、次のような出力が得られます
Trapped: INT
Trapped: TERM
Trapped: EXIT
$?
の参照 上記の解決策:$?
最後に実行されたコマンドの終了コードが反映されます。これを考慮してください:
#!/bin/bash
trap 'echo CODE: $?; exit 1' 1 2 3 15
sleep 3600
これを実行してCtrl-Cを押すと 、 CODE: 130
を出力します .それは sleep
実行可能ファイルは SIGINT によって中断され、そのコードで終了しました。
それを比較してください:
#!/bin/bash
trap 'echo CODE: $?; exit 1' 1 2 3 15
read X
これを実行してCtrl-Cを押すと 、 CODE: 0
を出力します 、おそらく read
コマンドは組み込みであり、終了コードの規則は異なります (while : ; do : ; done
を中断した場合も同じことが起こります) ).
つまり、$?
信号が外部コマンドを中断した場合にのみ、信号について通知します。および その特定のプログラムがシグナルをキャッチせず、独自の終了コードで終了した場合。場合のポイントは上記の bash スクリプトです:SIGINT を受け取ると、コード 1
で終了します 、 130
ではありません .
トラップ内で (シグナルによってトリガーされた場合)、$? variable は、最初はシグナル番号に 128 を加えた値に設定されているため、トラップ アクションの最初のステートメントを次のようにすることで、シグナル番号を変数に割り当てることができます
sig=$(($? - 128))
その後、kill コマンドを使用してシグナルの名前を取得できます
kill -l $sig
更新:コメントに記載されているように、これは一部の組み込みシェル コマンドでは機能しません。これらにトラップの $? を設定させるには変数、サブシェルで実行できます。例:
(read)
の代わりに
read
これを行う簡単な方法:
_handler() {
signal=$1
echo signal was $signal
}
trap '_handler SIGTERM' SIGTERM
trap '_handler SIGINT' SIGINT