シェルスクリプトの基礎 - シグナルとtrapコマンド

提供:MochiuWiki - SUSE, Electronic Circuit, PCB
2021年2月9日 (火) 08:28時点におけるWiki (トーク | 投稿記録)による版 (ページの作成:「== 概要 == シグナルとは、プロセス間で通信を行うための仕組みであり、Linuxカーネルに実装されている。<br> 実行中のプロセス…」)
(差分) ← 古い版 | 最新版 (差分) | 新しい版 → (差分)
ナビゲーションに移動 検索に移動

概要

シグナルとは、プロセス間で通信を行うための仕組みであり、Linuxカーネルに実装されている。
実行中のプロセスの処理を一時的に止めて、別のプロセスを処理する場合等に使用される。

シグナルは、キーボードからの割り込み(SIGINT)や浮動小数点例外(SIGFPE)、プロセスの終了(SIGTERM)等、30種類以上ある。
これらのシグナルは、プログラム(プロセス)自身の動作によって発生する同期シグナル、外的な要因で発生する非同期シグナルの2種類ある。

シグナルの動作を以下に示す。

  1. あるプロセスの実行中において、処理を割り込ませたい場合、カーネルがシグナルを発生させる。
  2. シグナルが発生すると実行中のプロセスが中断され,特定の処理が実行される。


この特定の処理のことを、シグナルハンドラと呼ぶ。
シグナルは突然発生するため、発生するシグナルごとに実行する処理を、予めシグナルハンドラとして登録する。

使用可能なシグナルの一覧は、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     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      35) SIGRTMIN    36) SIGRTMIN+1
...略



シグナルを送出する

プロセスにシグナルを送出するには、killコマンドを使用する。

以下のように、killコマンドのオプションとして、送出先プロセスのプロセスIDと送出するシグナルを指定して実行する。

kill [シグナル番号|シグナル名] PID


シグナルを送出するには、killコマンドに送出先プロセスのプロセスIDと送出するシグナルを指定して実行する。

シグナルの指定には、各シグナルに定義されているシグナル番号またはシグナル名のいずれかを使用する。
送出先プロセスのプロセスID(PID)は、psコマンドやpgrepコマンドで確認することができる。

シグナル番号またはシグナル名を省略する場合、標準で15番シグナル(TERM)が送出される。

sleep 100000 &  # sleepコマンドに&を付加してバックグラウンドで実行する

[1] 5355


pgrep -lf sleep  # pgrepコマンドでプロセスIDを検索する

5355 sleep 100000


kill -15 5355  # TERMシグナルを送出する


pgrep -lf sleep  # 再検索すると終了していることを確認できる

[1]+  終了しました            sleep 100000


下表に、各シグナルが持っている意味を示す。

表. 一般的なシグナル番号一覧

シグナル番号 シグナルが持つ意味
0 プロセス終了時に、プロセスが自分自身に対して送出するEXITシグナル。
1 XWindowのクローズやデーモンのリセットに使用されるハングアップシグナル。
2 [Ctrl]+[C]キーや[Delete]キーを押下した時に発生する割り込みシグナル。
3 [Ctrl]+[\]キーを押下した時に発生するクイットシグナル。
9 プロセスを強制終了するためのキルシグナル。
強制終了であるため、trapできない。
15 プロセスを終了させるための終了シグナル。
killコマンドは標準でこのシグナルを使用する。
(kill <PID>は、kill -15 <PID>と同じ意味)


表. 一般的なシグナル名一覧

シグナル番号 シグナル名 通知内容
1 HUP プロセスに再起動を通知する。
2 INT プロセスに割り込みを通知する。
[Ctrl]+[C]キー
3 QUIT プロセスに終了を通知する。
(coreを作成する)
9 KILL プロセスに強制終了を通知する。
15 TERM プロセスに終了を通知する。
(デフォルト)
18 CONT プロセスに再開を通知する。
19 STOP プロセスに中断を通知する。
20 TSTP プロセスにサスペンドを通知する。
[Ctrl]+[Z]キー



trap コマンド

trapコマンドの使用方法

trapコマンドは、送出されたシグナルを捕捉して、予め指定された処理を実行するコマンドである。

trap "<コマンド>" <シグナルリスト>


実行中のシェルスクリプトに対して送出されたシグナルは、trapコマンドを使用することで捕捉することができる。

killコマンド等により、シグナルリストに指定されたシグナルが送出されると、trapコマンドはそれを捕捉して、指定したコマンドを実行する。 trapコマンドを使用することにより、各シグナルの規定の動作を置き換えることができる。 ただし、強制終了のシグナルである9番はtrapすることはできないため、注意すること。

trap "echo trapped." 2

# ここで、[Ctrl]+[C]キーを押下する

trapped.


trap処理のリセット

trap コマンドでシグナル捕捉時に実行するように指定した動作は、リセットを行うことで解除することができる。

trap シグナルリスト → trap コマンドにシグナルリストのみを指定し、指定されたシグナルの捕捉処理をリセットする。

trap コマンドで指定した処理をリセットしたい場合、つまり trap 'rm -f *.tmp; exit 1' 1 2 3 15 などと指定していた動作を、各シグナルのデフォルトの動作に戻したい場合は、trap 1 2 3 15 のように trap コマンドにリセットしたいシグナルのみを指定し実行する。

trap コマンドの処理を指定していた部分に何も書かないことにより、シグナル受信時にデフォルトの動作をするようになる。ただし、処理部分に何も書かないと言っても**「trap '’ 1 2 3 15」とはまったく意味が違う**ので注意が必要だ。


trap 1 2 3 15 と書くと、シグナルを捕捉した場合は を実行する、つまり何もしない処理を実行するという意味になり、結果として該当するシグナルを無視するという設定になってしまう。

$ trap 'echo trapped.' 2 ※ ここで Ctrl+c を押す。 $ trapped.

  1. ↑trap に指定した処理が実行されている。

$ trap 2

  1. ↑trap をリセットする。

※ ここで Ctrl+c を押す。 $

  1. ↑指定した処理が解除されているのが確認できる。