Shell-Tips

【Shell-Tips】シェル中断処理「Trap」を実装する。

システム運用中に「Ctrl+C」で処理を止めたり、予期せぬエラーでスクリプトが中断することは珍しくありません。

こうした中断時に、ログ出力や後処理を安全に実行するために使われるのが「trap」コマンドです。trapを使えば、終了シグナルを検知して任意の処理を呼び出すことができ、ファイル削除やログ記録などを確実に行えます。

本記事では、trapの基本構文と実践的な使い方を最短で理解できるように整理します。

Trapとは何か

シェルスクリプトを動かしていると、途中で強制終了して「中途半端な状態」で止まることがあります。たとえば、作業の途中でCtrl+Cを押したり、メモリ不足などで処理が強制的に止まったときです。

実はその瞬間、Linuxの内部では「カーネル」と呼ばれるOSの心臓部分が、特定の信号(シグナル)を出してプロセスを止めています。これは国際規格「POSIX(ポジックス)」というルールで定められていて、すべてのUNIX系OSがこの仕組みを使っています。

たとえば、ユーザーが手動でCtrl+Cを押すと、カーネルは「2番(SIGINT)」という信号を送ります。逆に「もうこのプロセスを問答無用で消せ」という命令を出すときは「9番(SIGKILL)」という信号が送られます。ベテランエンジニアが「kill −9」と言うのは、この9番シグナルのことです。

このように、Linuxの中では「中断」「終了」「強制停止」といった動作が、すべて“番号付きの信号”として動いています。そしてシェルスクリプトの世界では、この信号を受け取って“どう反応するか”を自由に決められるのが「trap(トラップ)」です。

trapを使えば、「止まる瞬間に何をするか」をスクリプト側で指定できます。
たとえば、途中で止まったときに一時ファイルを削除したり、「中断されました」とメッセージを出したり。つまり、trapとは「シグナルを受け取って最後の仕事をするための保険」です。

拾える主なシグナルは次の通りです。

番号シグナル名意味主な用途
1SIGHUPハングアップ設定ファイルの再読み込みなど
2SIGINT割り込み (Ctrl+C)プロセスの中断
3SIGQUIT終了 (ダンプ生成)プロセス終了とコアダンプ生成
9SIGKILL強制終了プロセスの即時終了
11SIGSEGVセグメンテーション違反メモリアクセス違反
13SIGPIPEパイプ切断書き込み先が閉じられた場合
15SIGTERM終了要求優雅なプロセス終了
18SIGCONT停止から再開一時停止プロセスの再開
19SIGSTOPプロセス停止強制停止 (再開はSIGCONT)
20SIGTSTP端末停止 (Ctrl+Z)一時停止
30,10,16SIGUSR1ユーザー定義シグナル1カスタム処理
31,12,17SIGUSR2ユーザー定義シグナル2カスタム処理
34SIGRTMINリアルタイムシグナル (最小値)リアルタイム処理向け

この仕組みを知っておくと、Linuxの“裏で何が起きているのか”が見えるようになります。

trapは単なるコマンドではなく、「カーネルとシェルの会話を最後まで正しく終わらせるための機能」なのです。

コマンドの書式

trap [アクション] シグナル 

シェルスクリプトが、シグナルに指定した(複数書けます)シグナルを受け取ったとき、どういう処理をするかをアクションのところに指定します。

アクションには、関数名を指定して、シグナル取得時に関数を実行させることが可能です。

Trapの実用例

長時間のバックアップスクリプトを走らせている途中で、誰かがうっかりCtrl+Cを押してしまった。

次に再実行したら、前回の中途半端なファイルが邪魔をして、全部やり直し。そんな経験、ありませんか?

この“人間の手グセ”を防ぐのがtrapです。

スクリプトが止まった瞬間に、「削除」「記録」「通知」など、あなたの代わりに片づけをしてくれる。

言うなれば、trapは「最後の見張り番」です。

ログ出力

システムが途中で止まると、「何が起きたのか」がわからなくなり、復旧には何をすれば良いのか混乱します。

ここでは、特定の処理を実行して「10秒以内に「Ctrl+C」を押してTrapを実行」させてみます。 「Ctrl+C」を入力して処理を途中で止め、Trapが9番のシグナルを拾い処理を中止するようにしてみます。

今回は人手により「Ctrl+C」を使って処理を停止しますが、これはシェルの実行時に特定のエラーが発生した場合にも有効です。

カーネルが拾うシグナルの番号が人でによる「Ctrl+C」とシステムによるエラーで出力される信号が違うだけです。

下記のスクリプトへtrapを仕掛けておけば、止まった瞬間にその記録を残せます。

#!/bin/sh
trap 'echo "$(date) : 中断を検知しました" >> /tmp/trap.log; exit 1' 2 15
echo "バックアップ中..."
sleep 10
echo "完了しました"

【出力例:】処理実行中に「Ctrl+C」を押すと、以下のメッセージを出力して処理が停止されます。

^C  👈 人手による「Ctrl+C」を押すとコンソールに表示される記号
cat /tmp/trap.log
Fri Oct 17 10:00:00 JST 2025 : 中断を検知しました

つまり、このシグナルを受け取り実行されるTrapの仕組みにロジックを仕掛けておけば、エラー発生時に後処理をさせることが可能になるのです

中間ファイル削除

次は、このTrapの仕組みを少し応用してみます。

例えば、特定の中間ファイルが存在する間だけ、処理が実行されてと判定する場合、処理が途中で止まると判定用のファイルがそのままゾンビファイルとして残ってしまうことがあります。

特に初心者のうちはPIDファイルなどがそのままゾンビ化してしまい、再起動が行えずに混乱した方も多いのではないでしょうか

「途中で止まってゴミが残る」──これは運用の敵です。 trapはその瞬間を見逃しません。

#!/bin/sh
trap 'rm -f /tmp/tempfile; echo "中断時に一時ファイルを削除しました"; exit 1' 2 15
touch /tmp/tempfile
sleep 15
echo "処理完了"

【出力例:】処理実行中に「Ctrl+C」を押す。

^C 中断時に一時ファイルを削除しました

Trapがシグナルを受信し場合、「中間ファイルやPIDファイル等を削除する」仕掛けをスクリプトに記述しておけば、その後の再起動で処理実行されないと言ったエラーを防止することができます。

終了メッセージ表示

長い処理が止まったとき、静かなままだと「失敗?中断?」と不安になります。 trapで一言出すだけで、誰が見ても状況がわかります。

Trapが実行された際、必ずそれが運用者にわかるようにメッセージを出力するようにしておきましょう。

#!/bin/sh
trap 'echo "処理が中断されました。安全に終了します。"; exit 1' 2 15
echo "データ変換中..."
sleep 15
echo "正常終了"

【出力例:】処理実行中に「Ctrl+C」を押す。

^C
処理が中断されました。安全に終了します。

Trapは地味な仕組みですが、「壊れた処理を残さない」という点で、 どんな自動化よりも現場を救う力を持っています。

一行のtrapがあるだけで、あなたのスクリプトは“事故に強い”仕事道具に変わります。

Trap活用の応用例

シェルスクリプトの中断処理では、単に「止まった」ことを検知するだけでなく、その後の動作をどう制御するかが重要です。

Trapコマンドを使うと、異常終了の瞬間に自動的にクリーンアップ処理を行わせたり、ログを残したりといった柔軟な制御が可能になります。

ここでは、Trapを使って「中断時の安全な後処理」を行う方法を紹介します。

abort関数を使ったTrapの応用

Trapは、シグナルを受け取った瞬間に指定した関数を呼び出すことができます。

これを利用すれば、中断時にログ出力やリソース開放といった処理を一括で行えます。こ

こでは「abort」関数を定義し、シェルが割り込み信号(SIGINT)を受けた際に自動的に呼び出されるようにします。

#!/bin/sh
# --------------------------------------------------
# abort関数:中断時にログ出力を行う処理
# --------------------------------------------------
abort() {
  echo "$(date) : 中断を検知しました" >> /tmp/abort.log
  exit 1
}

# --------------------------------------------------
# Trap設定:割り込みシグナルを捕捉
# --------------------------------------------------
trap abort 1 2 3 15

echo "バックアップを開始します..."
sleep 10
echo "バックアップが完了しました。"

【出力例:】実行中に「Ctrl+C」を押すと、以下のようにログが出力されます。

^C
cat /tmp/abort.log
Fri Oct 17 10:00:00 JST 2025 : 中断を検知しました

このようにTrapを利用すれば、ユーザーによる中断操作や予期せぬ終了が発生しても、記録を残しながら安全に停止できます。

特にバッチ処理やバックアップスクリプトのような長時間実行系の処理では、途中停止時の痕跡を残すことがトラブル原因の特定に役立ちます。

Trapによる一時ファイル削除の応用

次に、Trapを使って中断時に不要な一時ファイルを削除する方法を紹介します。

処理の途中で停止すると、PIDファイルや中間ファイルが残り、再実行ができなくなるケースがあります。

Trapを使えば、こうした“ゴミ”を自動的に片付けられます。

#!/bin/sh
trap 'rm -f /tmp/tempfile; echo "中断時に一時ファイルを削除しました"; exit 1' 2 15
touch /tmp/tempfile
sleep 15
echo "処理が完了しました。"

【出力例:】処理中に「Ctrl+C」を押すと、以下のようなメッセージが出力されます。

^C
中断時に一時ファイルを削除しました

このように、Trapに削除処理を仕込んでおくことで、スクリプト中断時のクリーンアップを自動化できます。

上記のコマンドをスクリプトにしてみると下記のようになります。

#!/bin/sh
# --------------------------------------------------
# abort関数:中断時にログ出力を行う処理
# --------------------------------------------------
abort() {
rm -f /tmp/tempfile   
echo "$(date) : 中断を検知しました" >> /tmp/abort.log
exit 1
}

# --------------------------------------------------
# Trap設定:割り込みシグナルを捕捉
# --------------------------------------------------
trap abort 1 2 3 9 15

echo "バックアップを開始します..."
sleep 10
echo "バックアップが完了しました。"

【出力例:】処理実行中に「Ctrl+C」を押す。

sh test.sh
バックアップを開始します…
^C
cat /tmp/abort.log
2025年 10月 17日 金曜日 13:48:42 JST : 中断を検知しました

運用現場では「一時ファイルが残って再起動できない」といったトラブルを防ぎ、より安定した処理フローを実現できます。

Trapの応用範囲は広く、ログ出力、クリーンアップ、通知など、システムの安全停止を支えるさまざまな処理に発展させることが可能です。

実務で安定したスクリプトを書くためには、Trapの仕組みを積極的に活用することが重要です。

Trap設定で割り込みシグナルを捕捉する

Trapコマンドは、シェルが受け取る「終了や中断の合図(シグナル)」を検知して、特定の処理を自動で実行する仕組みです。

この設定では、 trap abort 1 2 3 15 と記述することで、下記のシグナルを受け取った際に、abort 関数を呼び出すように指定しています。

シグナル番号

  • 1(再起動要求)
  • 2(Ctrl+Cによる中断)
  • 3(強制終了)
  • 15(通常の終了要求)

これにより、スクリプトが人の操作やシステムの指令によって途中で止められたとしても、Trapがすぐに反応し、ログの出力や一時ファイルの削除などの後処理を安全に行えます。

ただし、ここに 「9(SIGKILL)」 を追加してはいけません。
SIGKILLはカーネルが強制的にプロセスを終了させる信号で、Trapで捕捉できないだけでなく、「誤って人間が手動で停止した場合にもTrap処理が走ってしまう」リスクがあります。

そのため、trap abort 1 2 3 15 のように、必要なシグナルだけを指定するのが安全です。

Trapは“止まったときに何を残すか”を決める仕組みなので、対象シグナルを絞って使うことが安定したスクリプト運用につながります。

Trap活用のポイント

Trapの役割は、スクリプトを途中で止めることではなく「中断しても壊れない構造を作ること」です。

エラーが発生しても、Trapが後処理を担ってくれることで、残骸ファイルや途中ログが運用を妨げることを防げます。

現場で安定したスクリプトを書くには、この“後始末の自動化”を設計段階から組み込むことが欠かせません。

Trapは“設計に組み込む仕組み”

Trapはスクリプトの最後に付け足すものではなく、設計そのものに埋め込む発想が大切です。

ログ出力、ファイル削除、終了通知など、終了時の共通処理をすべてTrap関数にまとめておけば、チーム全体で同じ終わり方を統一できます。

これにより、「止まっても整う」スクリプトが実現できます。どんな処理が途中で中断しても、Trapが後処理を保証し、再実行を阻害しません。

つまりTrapは、エラー耐性を高めるための“最後の安全弁”なのです。

実践環境を整える

ここまで学んだ知識を実際に試すには、Linuxを動かす環境が必要です。手軽に始めるならVPSを利用するのがおすすめです。
VPS徹底比較!ConoHa・さくら・Xserverの選び方



VPSを利用してLinux環境を準備したら、実際の設定は下記の記事が参考になります。
VPSに開発環境を自動構築する方法|Apache+Tomcat+PostgreSQL

よく読まれている記事

1

「私たちが日々利用しているスマートフォンやインターネット、そしてスーパーコンピュータやクラウドサービス――これらの多くがLinuxの力で動いていることをご存じですか? 無料で使えるだけでなく、高い柔軟 ...

2

Linux環境でよく目にする「Vim」という名前。サーバーにログインしたら突然Vimが開いてしまい、「どうやって入力するの?」「保存や終了ができない!」と困った経験をした人も多いのではないでしょうか。 ...

3

ネットワーク技術は現代のITインフラにおいて不可欠な要素となっています。しかし、ネットワークを深く理解するためには、その基本となる「プロトコル」と「レイヤ」の概念をしっかり把握することが重要です。 こ ...

4

この記事は、Linuxについて勉強している初心者の方向けに「Shellスクリプト」について解説します。最後まで読んで頂けましたら、Shellスクリプトはどのような役割を担っているのか?を理解出来るよう ...

5

Javaは世界中で広く使われているプログラミング言語であり、特に業務システムやWebアプリケーションの開発において欠かせない存在です。本記事では、初心者向けにJavaの基礎知識を網羅し、環境構築から基 ...

-Shell-Tips