= 一時ファイルの作成と削除(シェルプログラミング) = <> == 一時ファイルの作成 == {{{ tmpfile=$(mktemp 一時ファイルテンプレート名) }}} * mktemp(1) コマンドは以下の条件を満たすユニークなファイル(or ディレクトリ)を作成および、そのファイル(or ディレクトリ)名を得ることができます。 * ファイル(ディレクトリ)作成時にレースコンディションを起こしません。 * シンボリックリンクを含む、既ファイル(ディレクトリ)名ではありません。 * ファイル(ディレクトリ)名がユニークであること(後述)。 * umask の設定に寄らず、デフォルトパーミッションは 0600(0700)になります。 * シェルプログラミングレベルで、もっともセキュアな手順で作られた一時ファイル(ディレクトリ)であることが保証されています。 * とは言え、究極的にセキュア、というわけではありません。 * 一時ファイルは以下のルールにより作成されます。 * 「X」という文字は置き換え対象となります(テンプレート)。 * 「X」は英数字(大文字・小文字・数字)の62文字からなるランダムに選択された文字です。 * よって連続した「X」の数を増やせば増やすほど、ユニーク性が高まります(衝突確率が減ります)。 == 一時ファイルの削除 == {{{ rm -f "$tmpfile" }}} 実際にはこれでは不十分で、全ての終了前ルートに仕込む必要があります。 == 異常時の一時ファイルの削除 == {{{ trap 'rm -f "$tmpfile"' HUP INT QUIT TERM USR1 USR2 }}} * 異常時といっても典型的なシグナルを受けての削除処理です。 * エラーハンドリングをしなくて良いわけではありません。エラーハンドリングはちゃんとすること。 == 終了時に一時ファイルの削除 == {{{ trap 'rm -f "$tmpfile"' EXIT }}} * 「trap」には「終了時」を意味する疑似シグナル「EXIT」が使用可能です。 * これによりあらゆる状況での終了時に削除してくれます(嘘)。 == そのあたりまとめて削除する手順 == * trap EXIT は通常終了する範囲では仕事してくれるけど、シグナル受信時は仕事してくれない。 * trap SIGNAL では仕事してくれるけど、今度はシグナル処理後の EXIT 「でも」仕事してしまう。 * そのあたり手間を含めて「終了時処理」というイレギュラーなフローは関数にしてまとめてしまうこと。 {{{ atexit () { trap - EXIT rm -f "$tmpfile" } trap atexit EXIT HUP INT QUIT TERM USR1 USR2 }}} == 参考文献 == * [[https://fumiyas.github.io/2013/12/06/tempfile.sh-advent-calendar.html|安全な一時ファイルの作成と削除の方法 - 拡張 POSIX シェルスクリプト]] * [[http://qiita.com/takuyachallenge/items/f7203e0b43924451fdaf|シェルスクリプトで一時ファイルを安全に扱う3つのコツ]]