perl でbzip2圧縮されたテキストファイルのリストを一括処理するサンプル
ログ解析するために、bzip2圧縮された複数のログファイルをbzcatしてperlにパイプでつなげて処理してたらメモリ使用量が増大して困った。(bzcatはメモリ上にガンガン展開しながらconcatenateするため。まあそうなるわな)
んで、対処方法。
bzcatをパイプで標準入力するのをやめて、perlスクリプトの中で.bz2ファイルを展開して一行ずつ処理する。
#!/usr/local/bin/perl use IO::Uncompress::Bunzip2 qw( $Bunzip2Error ); use strict ; use warnings ; main(); sub main { my $filename = $ARGV[0]; my @file_list = getBz2fileList($filename); my $buffer; my $s; foreach my $file (@file_list) { my $gz = new IO::Uncompress::Bunzip2 $file or die "Cannot open $file: $Bunzip2Error\n" ; my $line; while ( defined($line = $gz->getline()) ) { myProcess($line); } $gz->close() ; } } sub myProcess { my ($line) = @_; # 一行ごとに任意の処理を行う } sub getBz2fileList { my ($filename) = @_; my @list; open FN, "<$filename" or die "Cannot open $filename\n"; while (my $line = <FN>) { push @list, $line; } close FN; return @list; }
先に.bz2ファイルを行区切りで記述しておく。
$ cat > bz2_files.txt log0001.bz2 log0002.bz2 log0003.bz2 ^D
こんな感じで、スクリプトの引数にファイルリストを指定して実行する。
$ ./myprocess.pl bz2_files.txt
ログアウトした後、HUPでスクリプトが死んでしまうのを避ける方法
nohup を使う。
$ nohup ./myprocess.pl bz2_files.txt > out.log 2> err.log < /dev/null
nohup をつけて実行して、bg でバックグラウンドプロセスにした後、ログアウトすればよい。
参考:
追記
nohupをつけずに実行したときはバックグラウンドプロセスにした後disownしてやる。%1の1はジョブ番号
disown %1