Perl - 大きいログファイルを処理する
1ファイル数ギガとかあるログファイルを一行ずつ処理したいとき、いくつか fork して、worker1 は 0MB-500MBを処理、worker2 は 500MB-1000MBを処理, .. みたいにやると意外に簡単にできた。
#!/usr/bin/env perl use strict; use warnings; use utf8; use Fcntl qw(:seek); use File::Basename qw(basename); sub process_line { my $line = shift; # do something $line; } my $file = shift; if (!$file || !-f $file) { help(); } my $size = -s $file; my $worker = 5; # number of workers my $per_size = int($size / $worker); my @position = map { $per_size * $_ } 0..($worker - 1); push @position, $size; my %worker; for my $i (0..($worker - 1)) { my $pid = fork; die "fork failed" unless defined $pid; if ($pid) { $worker{$pid}++; next; } my $out_file = join '_', "out", basename($file), $i; open my $fh, "<", $file or die "$file: $!"; open my $out, ">", $out_file or die "$out_file: $!"; my $start = $position[$i]; my $end = $position[$i + 1]; seek $fh, $start, SEEK_SET or die "seek failed: $i"; scalar(<$fh>) if $i != 0; # drop first line while ( (tell($fh) <= $end) && (my $line = <$fh>) ) { my $result = process_line $line; print {$out} $result; } exit; } while (%worker) { if (my $pid = wait) { if (exists $worker{$pid}) { delete $worker{$pid}; } } } sub help { print STDERR <<"HELP"; Usage: % $0 big.log HELP exit 1; }