テンポラリファイル

id:shag さんの日記(Perl での secure な一時ファイルの取り扱い - shag の日記, IO::File::new_tmpfile() - shag の日記)と perlfaq5 をベースに私家版まとめ。

テンポラリファイルの作り方 3 選

  1. IO::File の new_tmpfile(割と昔からあるらしい?)
  2. open の 第3引数に undef を指定する(Perl 5.8 以降のフィーチャー)
  3. File::Temp の tempfile(Perl 5.6.1 以降で標準添付)

2 はこんなの↓

open my $tmp, '+>', undef or die $!;

1 と 2 は実質同じ。PerlIO_tmpfile() を下位 xs サブルーチンとして利用しており,

  • win32 の場合 FILE_FLAG_DELETE_ON_CLOSE フラグ付きで開くので close 時に削除される
  • Unix の場合
    • mkstemp() がある場合,ファイル作成直後に unlink するので close 時に削除されるし,作成直後も他人には見えない(セキュリティ向上)
    • mkstemp() がない場合,tempfile() を利用するので close 時に削除される

3 は割と堅実に書いてあって,ファイルハンドル生成時に unlink() ができる環境(Unix 等)だとそのようにすることができるし,無理なら END{} 時にクリーンアップしたり File::Temp::cleanup() で手動でクリーンアップしたりできる*1。残念ながら Win32 で FILE_FLAG_DELETE_ON_CLOSE な感じにはしてくれないけど。


で 1, 2, 3 にしても close 時に自動削除されるようなテンポラリファイルを作る際そのファイル名は得られない。基本そういう用途(その場だけ用)に使いましょう。永続化したいファイルなら File::Temp::tmpnam / tempfile 使うとか。

永続化したくないけどファイル名がいるというシチュエーション(他のモジュールや外部プロセスがファイル名を要するとか)なら

my ($fh, $filename) = tempfile();

Foo::Bar::process($filename);

File::Temp::unlink0($fh, $filename);

みたくすればいいのではないのかなぁ…一度閉じて再 open するほうが安全かもしれない。

*1:File::Temp を mod_perl や SpeedyCGI で使っているなら register_cleanup() に登録した方がいいかも