Unix-signals-traps

提供:Dev Guides
移動先:案内検索

Unix/Linux-シグナルとトラップ

この章では、Unixのシグナルとトラップについて詳しく説明します。

シグナルは、重要なイベントが発生したことを示すためにプログラムに送信されるソフトウェア割り込みです。 イベントは、ユーザーの要求から不正なメモリアクセスエラーまでさまざまです。 割り込み信号などの一部の信号は、ユーザーがプログラムに通常の制御フローにない何かを行うように要求したことを示します。

次の表に、遭遇する可能性があり、プログラムで使用する一般的な信号を示します-

Signal Name Signal Number Description
SIGHUP 1 Hang up detected on controlling terminal or death of controlling process
SIGINT 2 Issued if the user sends an interrupt signal (Ctrl + C)
SIGQUIT 3 Issued if the user sends a quit signal (Ctrl + D)
SIGFPE 8 Issued if an illegal mathematical operation is attempted
SIGKILL 9 If a process gets this signal it must quit immediately and will not perform any clean-up operations
SIGALRM 14 Alarm clock signal (used for timers)
SIGTERM 15 Software termination signal (sent by kill by default)

信号のリスト

システムでサポートされているすべての信号をリストする簡単な方法があります。 kill -l コマンドを発行すると、サポートされているすべての信号が表示されます-

$ kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL
 5) SIGTRAP      6) SIGABRT      7) SIGBUS       8) SIGFPE
 9) SIGKILL     10) SIGUSR1     11) SIGSEGV     12) SIGUSR2
13) SIGPIPE     14) SIGALRM     15) SIGTERM     16) SIGSTKFLT
17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU
25) SIGXFSZ     26) SIGVTALRM   27) SIGPROF     28) SIGWINCH
29) SIGIO       30) SIGPWR      31) SIGSYS      34) SIGRTMIN
35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3  38) SIGRTMIN+4
39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12
47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14
51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10
55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7  58) SIGRTMAX-6
59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

信号の実際のリストは、Solaris、HP-UX、およびLinuxによって異なります。

デフォルトのアクション

すべてのシグナルには、デフォルトアクションが関連付けられています。 シグナルのデフォルトのアクションは、スクリプトまたはプログラムがシグナルを受信したときに実行するアクションです。

可能なデフォルトのアクションのいくつかは次のとおりです-

  • プロセスを終了します。
  • 信号を無視します。
  • ダンプコア。 これにより、 core というファイルが作成され、シグナルを受信したプロセスのメモリイメージが含まれます。
  • プロセスを停止します。
  • 停止したプロセスを続行します。

信号を送る

信号をプログラムまたはスクリプトに配信する方法はいくつかあります。 最も一般的な方法の1つは、ユーザーがスクリプトの実行中に CONTROL-C または* INTERRUPTキー*を入力することです。

*_Ctrl + C_* キーを押すと、 *SIGINT* がスクリプトに送信され、定義済みのデフォルトアクションスクリプトに従って終了します。

信号を配信する他の一般的な方法は、* killコマンド*を使用することです。その構文は次のとおりです-

$ kill -signal pid

ここで、 signal は配信するシグナルの番号または名前であり、 pid はシグナルの送信先のプロセスIDです。 例-

$ kill -1 1001

上記のコマンドは、*プロセスID 1001 *で実行されているプログラムにHUPまたはハングアップ信号を送信します。 同じプロセスにキル信号を送信するには、次のコマンドを使用します-

$ kill -9 1001

これにより、*プロセスID 1001 *で実行されているプロセスが強制終了されます。

信号の捕捉

シェルプログラムの実行中に端末で_Ctrl + C_またはBreakキーを押すと、通常、そのプログラムはすぐに終了し、コマンドプロンプトに戻ります。 これは常に望ましいとは限りません。 たとえば、クリーンアップされない一時ファイルの束を残すことがあります。

これらの信号をトラップすることは非常に簡単であり、トラップコマンドには次の構文があります-

$ trap commands signals

ここで、_command_は任意の有効なUnixコマンド、またはユーザー定義関数である場合があり、signalはトラップする任意の数のシグナルのリストです。

シェルスクリプトのトラップには2つの一般的な用途があります-

  • 一時ファイルをクリーンアップする
  • 信号を無視

一時ファイルのクリーンアップ

trapコマンドの例として、以下は、いくつかのファイルを削除し、誰かが端末からプログラムを中止しようとした場合に終了する方法を示しています-

$ trap "rm -f $WORKDIR/work1$$ $WORKDIR/dataout$$; exit" 2

このトラップが実行されるシェルプログラムのポイントから、シグナル番号2がプログラムによって受信されると、2つのファイル _work1 _* および *_dataout _ が自動的に削除されます。

したがって、このトラップの実行後にユーザーがプログラムの実行を中断した場合、これらの2つのファイルがクリーンアップされることが保証されます。 rm に続く exit コマンドが必要です。これがないと、プログラムは信号を受信したときに中断した時点で実行が継続されるためです。

*hangup* に対してシグナル番号1が生成されます。 誰かが意図的に回線を切るか、回線が誤って切断されます。

この場合、シグナル番号1をシグナルのリストに追加することにより、前述のトラップを変更して、指定された2つのファイルも削除できます-

$ trap "rm $WORKDIR/work1$$ $WORKDIR/dataout$$; exit" 1 2

これで、回線がハングアップした場合、または_Ctrl + C_キーが押された場合、これらのファイルは削除されます。

トラップするように指定されたコマンドに複数のコマンドが含まれる場合は、引用符で囲む必要があります。 また、トラップコマンドが実行されたとき、およびリストされた信号の1つが受信されたときに、シェルがコマンドラインをスキャンすることに注意してください。

したがって、前の例では、トラップコマンドの実行時に WORKDIR および $$ の値が置換されます。 シグナル1または2が受信されたときにこの置換が発生するようにしたい場合は、コマンドを単一引用符で囲むことができます-

$ trap 'rm $WORKDIR/work1$$ $WORKDIR/dataout$$; exit' 1 2

信号を無視する

トラップ用にリストされたコマンドがヌルの場合、指定されたシグナルは受信時に無視されます。 たとえば、コマンド-

$ trap '' 2

これは、割り込み信号を無視することを指定します。 中断したくない操作を実行するときに、特定の信号を無視したい場合があります。 次のように無視される複数の信号を指定できます-

$ trap '' 1 2 3 15

最初の引数は無視される信号のために指定する必要があり、それ自体が別の意味を持つ次の記述と同等ではないことに注意してください-

$ trap  2

シグナルを無視すると、すべてのサブシェルもそのシグナルを無視します。 ただし、信号の受信時に実行するアクションを指定した場合、すべてのサブシェルはその信号の受信時にデフォルトのアクションを実行します。

トラップのリセット

シグナルの受信時に実行されるデフォルトのアクションを変更した後、最初の引数を単に省略した場合、トラップを使用して再度アクションを変更できます。そう-

$ trap 1 2

これにより、シグナル1または2の受信時に実行されるアクションがデフォルトにリセットされます。