4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[bash] スクリプトを強制終了した場合でも一時ファイルを削除したい

Posted at

bashでスクリプトを書いていると、一時ファイルを作成したくなることがあります。
スクリプトが何の異常もなく、最初から最後まできちんと実行された場合には、
後処理として一時ファイルを削除すればいいわけですが、
実行エラーやCtrl-C等で強制終了したときなど、一時ファイルが削除されず残ってしまう場合があります。

サンプルスクリプト
#!/bin/bash

tmpfile=tmp.$$

echo "test tmp file" > $tmpfile

echo "wait for 5 seconds..."
sleep 5 

rm $tmpfile
echo "clean tmp file($tmpfile)"
実行結果(正常)
$ ./test.sh 
wait for 5 seconds...
clean tmp file(tmp.18758)

$ ls tmp.*
ls: cannot access tmp.*: No such file or directory
実行結果(Ctrl-cで強制終了)
$ ./test.sh 
wait for 5 seconds...
^C

$ ls tmp.*
tmp.19196

*nixでは、特定のイベントが発生するとプロセスに対してシグナルを発行します。
例えばスクリプト実行中にCtrl-Cで強制終了したときにも、内部的には実行プロセスに対して
シグナルが発行されています。

bashではtrapコマンドを利用することで、受け取ったシグナルに対し、ハンドラを定義することができます。
ハンドラ内で一時ファイルを削除する処理を定義すれば、異常終了時にも対応できちゃいます。

サンプルスクリプト(シグナルハンドラ実装版)
#!/bin/bash

tmpfile=tmp.$$
trap "echo 'clean tmp file($tmpfile)'; rm $tmpfile; exit 1" 0 

echo "test tmp file" > $tmpfile

echo "wait for 5 seconds..."
sleep 5 
実行結果(正常終了)
$ ./test.sh 
wait for 5 seconds...
clean tmp file(tmp.19457)

$ ls  tmp.*
ls: cannot access tmp.*: No such file or directory
実行結果(Ctrl-Cで強制終了)
$ ./test.sh 
wait for 5 seconds...
^Cclean tmp file(tmp.19498)

$ ls tmp.*
ls: cannot access tmp.*: No such file or directory

シグナルの仕組みに関する詳細は他に任せるとして、
trapコマンドの末尾にはシグナル番号を記載します。
シグナル番号0は擬似シグナルと呼ばれる特別なシグナルで、
スクリプトが終了するタイミングで発行されるので汎用的に使えます。

これで、気づいたら一時ファイルが量産されていたなんてことも回避できますね。

4
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?