Bashスクリプトから一時ファイルを作成しています。処理の最後にそれらを削除していますが、スクリプトが非常に長い時間実行されているため、実行中にそれを強制終了するか、単にCTRL-Cを押すと、一時ファイルは削除されません。
これらのイベントをキャッチし、実行が終了する前にファイルをクリーンアップする方法はありますか?
また、これらの一時ファイルの名前と場所について、ある種のベストプラクティスはありますか?
現在、使用するかどうかはわかりません:
TMP1=`mktemp -p /tmp`
TMP2=`mktemp -p /tmp`
...
そして
TMP1=/tmp/`basename $0`1.$$
TMP2=/tmp/`basename $0`2.$$
...
それとも、もっと良い解決策がありますか?
「 trap 」を設定して、終了時に実行するか、control-cで実行してクリーンアップできます。
trap "{ rm -f $LOCKFILE; }" EXIT
別の方法として、私のお気に入りのunix-ismの1つは、ファイルを開き、それを開いたままにしてから削除することです。ファイルはファイルシステムに残り、読み書きできますが、プログラムが終了するとすぐにファイルはなくなります。ただし、bashでどのように行うかはわかりません。
ところで:私はあなた自身のソリューションを使用する代わりにmktempを支持します:ユーザーがあなたのプログラムが巨大な一時ファイルを作成しようとしている場合、彼はTMPDIR
を/ varのようなより大きなどこかに設定したいかもしれません/ tmp。 mktempはそれを認識しますが、手動ロールソリューション(2番目のオプション)は認識しません。私はよくTMPDIR=/var/tmp gvim -d foo bar
、 例えば。
私は通常、すべての一時ファイルを配置するディレクトリを作成し、その後すぐに、スクリプトの終了時にこのディレクトリをクリーンアップするためにEXITハンドラーを作成します。
MYTMPDIR=$(mktemp -d)
trap "rm -rf $MYTMPDIR" EXIT
すべての一時ファイルを$MYTMPDIR
の下に置くと、ほとんどの状況でスクリプトが終了するときにすべての一時ファイルが削除されます。ただし、SIGKILL(kill -9)を使用してプロセスを強制終了すると、すぐにプロセスが強制終了されるため、その場合はEXITハンドラーは実行されません。
trap コマンドを使用して、スクリプトまたはCTRL-Cなどのシグナルの終了を処理します。詳細については、 Greg's Wiki を参照してください。
一時ファイルの場合、basename $0
は、十分な一時ファイル用のスペースを提供するテンプレートを提供するのと同様に、良いアイデアです。
tempfile() {
tempprefix=$(basename "$0")
mktemp /tmp/${tempprefix}.XXXXXX
}
TMP1=$(tempfile)
TMP2=$(tempfile)
trap 'rm -f $TMP1 $TMP2' EXIT
選択した答えはbashism
であることに注意してください。これは、
trap "{ rm -f $LOCKFILE }" EXIT
bashでのみ動作します(シェルがdash
またはクラシックsh
の場合、Ctrl + cをキャッチしません)が、互換性が必要な場合は、トラップするすべてのシグナルを列挙する必要があります。
また、スクリプトが終了すると、シグナル "0"(別名EXIT)のトラップが常に実行されるため、trap
コマンドが2回実行されることに注意してください。
EXITシグナルがある場合、すべてのシグナルを1行にスタックしない理由。
理解を深めるために、変更なしで異なるシステム間で機能する次のスクリプトを見てください。
#!/bin/sh
on_exit() {
echo 'Cleaning up...(remove tmp files, etc)'
}
on_preExit() {
echo
echo 'Exiting...' # Runs just before actual exit,
# Shell will execute EXIT(0) after finishing this function
# that we hook also in on_exit function
exit 2
}
trap on_exit EXIT # EXIT = 0
trap on_preExit HUP INT QUIT TERM STOP PWR # 1 2 3 15 30
sleep 3 # some actual code...
exit
このソリューションは、最終出口(preExit
関数)の直前に実際のシグナルの発生時にコードの一部を実行でき、必要に応じて実際のEXITシグナルでコードを実行できるため、より制御しやすくなります(出口)
予測可能なファイル名を$$で使用する代わりの方法は、セキュリティホールを広げることであり、決して使用することを考えるべきではありません。たとえそれがあなたのシングルユーザーPC上の単純な個人的なスクリプトであっても。それはあなたが得るべきではない非常に悪い習慣です。 BugTraq は「安全でない一時ファイル」インシデントでいっぱいです。一時ファイルのセキュリティ面の詳細については、 here 、 here 、および here を参照してください。
私は当初、安全でないTMP1とTMP2の割り当てを引用することを考えていましたが、2番目の考えではおそらく 良いアイデアではない になるでしょう。
安全な方法で/ tmpにファイルを作成するtempfile
を使用することを好み、その命名について心配する必要はありません。
tmp=$(tempfile -s "your_sufix")
trap "rm -f '$tmp'" exit