« Firesheepと無線LANカードの相性 | トップページ | 日本語キーボードを英語配列で使うカスタマイズ »

2010年11月26日

Linuxログファイル全世代を連結するスクリプト(PowerShell、Perl)

Linuxのログファイル(messagesなど)は、一定条件を満たすと、世代を表す拡張子(.0、.1)を付加してgzipで圧縮される。これがひとつのテキストファイルになっていた方がログを解析に都合がいいときがある。DOSプロンプトのcopyコマンドなら、

copy messages.3 + messages.2 + messages.1 + messages.0 + messages messages.txt

のように「+」でファイルを連結できる。欠点は、システムやログファイルによって世代数が変わるので、いちいちファイル名を入力しなければならないことだ。タブキーでファイル名を補完すればキータイプ回数を減らせるが、それでも面倒だ。スクリプトで自動化してみた。

DOSプロンプトのバッチファイルは「過去の遺物」であるので、PowerShellで作ってみた。正規表現やforeachが使えるのが非常によい。


# messages*ファイルを収集して、世代番号を配列に入れる。
$files = Get-ChildItem messages*| Where-Object {$_.Extension -match ".[0-9]+"} | foreach ($_) {$_.extension -replace "\.", ""}

#配列内の世代番号を数値型に変換する。
for ($i = 0; $i -le $files.Length - 1; $i++) { $files[$i] = $files[$i] -as [Int32] }

#世代数(世代番号の最大値)を求める。
$max = $files[0]
for ( $i=1; $i -le $files.Length; $i++) { if ($files[$i] -gt $max) { $max = $files[$i] } }

#一番古いものから順番にmessages.txtファイルへ書き出す。
#ログファイルはASCII文字だけという前提。日本語を含む場合はUnicodeを指定する。
for ($i=$max; $i -ge 0; $i--) { Get-Content "messages.$i" | Out-File messages.txt -Encoding ASCII -Append}

#最新世代のファイルを連結する
Get-Content messages | Out-File messages.txt -Encoding ASCII -Append}

Unicodeで出力した場合、英数字もUnicodeに変換され、ファイルサイズがオリジナル総計の約2倍になる。また改行文字もLinuxのLFからLF+CRに変換される。

ついでにPerlで書いてみた(注)。


use strict;
use utf8;

# messages*ファイルを収集して

my @files = do {
  opendir my $dir, '.' or die ("Cannot open the current directory");
  my @f = grep /messages\.[0-9]+/, readdir($dir);
  closedir $dir;
  @f;
};

# 世代番号を配列に入れる。
foreach my $gen (@files) {
	$gen =~ s/messages\.//g;
}

# 拡張子の最大を求める。

my $max = $files[0];

for (my $i = 0; $i < @files; $i++) {
	if ($files[$i] > $max) {
		$max = $files[$i];
	}
}

#一番古いものから順番にmessages.txtファイルへ書き出す。

open (OUT, ">messages.txt");

for ( my $i = $max; $i >= 0; $i--) {
	open (IN, "messages.$i");
	while (

) {
print OUT;
}
close IN;
}

#最新世代のファイルを連結する
open (IN, "messages");
while (

) {
print OUT;
}
close IN;
close OUT;

これもやはり改行文字がLinuxのLFからLF+CRに変換される。メッセージ本文はオリジナルの文字コードのままである。

(注)ファイル収集の処理は小飼弾氏のコードをお借りした。

perl - glob,readdir, and regexp
http://blog.livedoor.jp/dankogai/archives/51058540.html

|

« Firesheepと無線LANカードの相性 | トップページ | 日本語キーボードを英語配列で使うカスタマイズ »

コメント

コマンドラインで
$ cat `ls message.* | sort -k 2nr -t.` message > message.txt
とでもすればいいだけの話では無いのでしょうか?

投稿: メロン | 2010年11月26日 20時29分

メロンさん

私はWindowsが作業マシンで、ログファイルだけメールなどで受け取ることが多いのです。スクリプトの勉強も兼ねて(というかより、こちらが主たる目的ですが)、作ってみました。

投稿: raven | 2010年11月27日 08時09分

$ cat `ls messages.* | sort -k 2nr -t.` > message.txt

投稿: | 2011年1月 6日 13時00分

コメントを書く



(ウェブ上には掲載しません)


コメントは記事投稿者が公開するまで表示されません。



« Firesheepと無線LANカードの相性 | トップページ | 日本語キーボードを英語配列で使うカスタマイズ »