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

こんにちは、将来のコンピュータの魔術師たち!今日は、Unix/Linuxのシグナルとトラップの魅力的な世界に飛び込みます。プログラミングが初めての方でも心配しないでください。私はこの冒険をステップバイステップで案内します。これまでに数多くの生徒を指導してきましたので。それでは、一緒にこのエキサイティングな旅に出発しましょう!

Unix / Linux - Signals and Traps

シグナルとは?

忙しいレストランの厨房を想像してください。シェフ(Unixシェフと呼びましょう)は、スタッフと迅速に通信する必要があります。喧騒を越えて叫ぶ代わりに、彼は手信号を使用します。Unix/Linuxの世界でのシグナルは、ほぼ同じです。プロセス間が迅速かつ効率的に通信する方法です。

シグナルは、重要なイベントが発生したことをプログラムに通知するためのソフトウェア中断です。これらのイベントは、ユーザーのリクエストから異常なランタイムの発生まで多岐にわたります。

シグナルの一覧

Unixシェフが「もっと塩を加える」、「急いで」、「休憩を取る」という手信号を持つように、Unix/Linuxシステムにはさまざまな目的のシグナルがあります。以下に最も一般的なものを見てみましょう:

シグナル名 シグナル番号 説明
SIGHUP 1 制御ターミナルでのハンガップ検出または制御プロセスの死亡
SIGINT 2 キーボードからのインタラプト(Ctrl+C)
SIGQUIT 3 キーボードからのキュー(Ctrl+\)
SIGKILL 9 キルシグナル(キャッチまたは無視不能)
SIGTERM 15 終了シグナル
SIGSTOP 17, 19, 23 プロセスを停止(キャッチまたは無視不能)

デフォルトのアクション

シグナルがプロセスに送信されると、プロセスは指示が無い限りデフォルトのアクションをとります。これらのデフォルトアクションは、厨房スタッフの本能的な反応に似ています。例えば:

  1. プロセスを終了する
  2. シグナルを無視する
  3. コアダンプを行う
  4. プロセスを停止する
  5. 停止したプロセスを再開する

シグナルの送信

では、これらのシグナルを送信する方法を学びましょう。Unix/Linuxでは、killコマンドを使用してプロセスにシグナルを送信します。名前のとおりに考えないでください - killは必ずしもプロセスを終了するものではありません。シグナルを送信する方法です。

以下のように使用します:

kill -signal_name process_id

例えば、プロセスID 1234にSIGTERMシグナルを送信するには:

kill -SIGTERM 1234

または、シグナル番号を使用して:

kill -15 1234

シグナルのトラップ

もし厨房スタッフがUnixシェフのシグナルに応じて自分でどのように反応するか決められたらどうでしょうか?それがプログラミングにおけるシグナルトラップの概念です。

シェルスクリプトでは、trapコマンドを使用してシグナルをキャッチし、受信時に何をすべきかを指定します。基本的な構文は以下の通りです:

trap command signal(s)

例を見てみましょう:

#!/bin/bash

trap "echo Bonjour!" SIGINT SIGTERM

echo "It's a trap!"
while true
do
sleep 60
done

このスクリプトでは、SIGINTまたはSIGTERMを受け取ると「Bonjour!」と表示します。これは、厨房スタッフに「シェフが停止を信号したら、'Bonjour!'と言うだけで実際には停止しない」と言っているのに似ています。

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

トラップの一般的な用途の1つは、スクリプトが終了する前に一時ファイルをクリーンアップすることです。以下に例を示します:

#!/bin/bash

# 一時ファイルを作成
temp_file=$(mktemp)

# 一時ファイルを削除するトラップを設定
trap "rm -f $temp_file" EXIT

# 一時ファイルを使用
echo "Hello, World!" > $temp_file
cat $temp_file

# スクリプトが終了するときに一時ファイルが自動的に削除されます

このスクリプトは一時ファイルを作成し、書き込んで読み込みます。そして、スクリプトが終了するときに自動的に削除します。

シグナルを無視する

時々、特定のシグナルを無視したいことがあります。厨房のアナロジーで言えば、「シェフが何度も塩を追加する信号を出しても、私は追加しません」と言っているのに似ています。

以下のようにシグナルを無視します:

trap "" SIGINT

これは、スクリプトがSIGINTシグナルを受け取ったときに何も行わないように指示します。

トラップのリセット

シグナルのトラップをデフォルトの動作に戻したい場合はどうしますか?トラップをリセットする方法は以下の通りです:

trap - SIGINT

これでSIGINTのトラップを削除し、デフォルトの動作に戻します。

以下により完全な例を示します:

#!/bin/bash

# 最初にSIGINTをトラップ
trap "echo You can't stop me!" SIGINT

echo "Try to stop me with Ctrl+C..."
sleep 10

# トラップをリセット
trap - SIGINT

echo "Okay, now you can stop me with Ctrl+C..."
sleep 10

echo "If you see this, you didn't stop me!"

このスクリプトはまずSIGINTをトラップし、10秒後にトラップをリセットします。これは、厨房スタッフに「10秒間は停止信号を無視し、その後は通常に戻る」と言っているのに似ています。

そして、皆さん!私たちはUnix/Linuxのシグナルとトラップの地を旅しました。実践は完璧を生みます。自分でスクリプトを書いて、さまざまなシグナルを試してみてください。そして、まもなくあなたもプロセスの指揮者のように become します。ハッピーコーディング!

Credits: Image by storyset