GNU/Linux >> Linux の 問題 >  >> Linux

Bashで受信したシグナル名を特定する

(信号の番号だけがあり、名前が必要な場合は、 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

Linux
  1. Python - すべてのシグナルをトラップする

  2. パス名の .. を bash スクリプトの絶対名に変換する方法は?

  3. jenkins パイプラインで bash コマンドを実行する

  1. Bashシェル関数での循環名参照、ただしKshではない?

  2. Bash +正規表現で名前を確認しますか?

  3. 5 Bash Case ステートメントの例

  1. Bash スクリプトのスクリプト ファイル名を知るにはどうすればよいですか?

  2. BASH:SIGTSTP シグナルを送信 (ctrl+z)

  3. bashプロンプトに現在のディレクトリ名のみを表示します(フルパスではありません)