perl で複数のプロセスからログを吐くときは :unix layer で開いてもいい
File::RotateLogs
が大変便利でよく使っているのだが、これはファイルへ書き込むときに print
を呼んでいる。
一方
によると長いログを吐くときは syswrite
にしないと混ざるとある。
よって File::RotateLogs も実は混ざることがあるのかなと思い、複数プロセスから長いログを吐きまくってみたが一向に混ざらなかった。
いろいろ調べた結果、open layer に最も低級な layer である :unix
を指定すれば
print
時も 1 つの write(2) になるようだった。
> cat test.pl
open my $fh, ">:unix", "test.txt";
print $fh "a" x (1024 * 100);
> strace perl test.pl 2>&1 | grep write
write(3, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"..., 102400) = 102400
そして、File::RotateLogs はしっかりと :utf8:unix
で open していた。流石である。
まとめ
perl で複数のプロセスからログを吐くときは syswrite, もしくは open layer を :unix にすべき。
余談
標準 open layer は大抵の場合 :unix:perlio
のため、:perlio
を外すという意味で
open my $fh, ">:pop", "file";
としてもよさそうではある。