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