#!/usr/local/bin/perl #!D:/Perl/bin/perl.exe #--------------------------------------------------------------------------------- # AN HTTPD専用ログファイル変換Perlスクリプト(jcode.pmを使用) # URL:http://sakaguch.com 電子メール:http://sakaguch.com/cgi/postmail/ より送信して下さい。 # ファイル名:combined.pl 2003.03.08 作成:鷹の巣 http://sakaguch.com/ #--------------------------------------------------------------------------------- # 改版記録: # 2003.03.08 Rev.1.000 初版で公開。 # 2003.03.13 Rev.1.100 refererとUser Agentの処理内容を訂正。設定項目の削減他。 # 2003.03.15 Rev.1.101 URLからホスト名を抽出する正規表現を変更。 # (URLの最後に/が1つもない時、ホスト名が抽出できないバグに対応) # 2004.03.22 Rev.1.102 AWstats用コードをeuc-jpよりutf-8コードに変更。 # $buffer_line を100より200に変更。 $ver = 'combined.pl Rev.1.102(作成:鷹の巣)'; #--------------------------------------------------------------------------------- # 1.用途 # #  このPerlスクリプトは、フリーソフトです。詳細は、項4をご一読願います。 # #  このPerlスクリプトは、Webサーバー等のログファイルに記録されているIPアドレスを #  ホスト名(FQDN)に変換し、アクセスログ解析用のログファイル様式に変換します。 #  (ログファイルがホスト名で記録されているに場合は、使用する必要はありません。) #   #  ※注意 #   ログファイルの行の先頭は、必ずIPアドレスになっている必要があります。 #   ApacheのNCSA combined/XLF/ELF log formatや #   AN HTTPDのNCSA common/CLF log format では、使用出来ますが、 #   IIS のW3C log formatには、使用できません。 # #   対応していないlog formatには、AWStatsのサイト #    http://awstats.sourceforge.net/ #   から、awstats-XX.zipやawstats-XX.tgzをダウンロードし、toolsディレクトリ内の #   logresolvemerge.plを使用して下さい。(ものすごく遅いです。) #   使用例) #   perl ./logresolvemerge.pl -dnslookup IPアドレスでのログファイル名 > ホスト名でのログファイル名 # #   ログフォーマットの詳細は、AWStatsのサイトのFAQ #    http://awstats.sourceforge.net/docs/awstats_faq.html#PERSONALIZEDLOG #   をご参照願います。 #    #   アクセスログ解析用のcombinedログファイルの生成については、 #   Other Non AWStats contribs/tools (not related to AWStats but related to log analysis) #    http://awstats.sourceforge.net/awstats_contrib.html#DOC #   のaccess_referer_agent2combined.plがありますが、このスクリプトと同様、 #   手抜き処理の連結処理でした。 # #--------------------------------------------------------------------------------- # 2.作成されるファイルの表示例と特徴 # #  アクセスログ解析用AWStatsで、作成されたhtmlファイルの表示例を #  以下のURLに設置しています。 #  http://sakaguch.com/log/2003/200302.html # #  ○利点:月単位での処理をオフラインで処理します。 #      クライアント機で処理することを前提にしている為、 #      アクセス統計処理のサーバーへの負荷を小さく出来る。 # #  ○欠点:処理に時間がかかり過ぎる。データだけで、視覚的ではない。 #      集中的に処理を行うので、クライアント機での処理向き。 #      スクリプトの読みやすさに重点を置いているので、処理速度が #      多少、遅い。 # #--------------------------------------------------------------------------------- # 3.ご注意事項 # #  このスクリプトは、Windows 2000 Professional #  Active Perl 5.8.4.810 built for MSWin32-x86-multi-thread #  jcode.pm ver.0.82 の環境にて、動作確認を行っております。 #  UTF-8のコード変換の為、Active Perl 5.6では、jcode.pmのインストールが必要ですから、 #  ご注意願います。詳細は、http://sakaguch.com/SetJcodePm.html をご参照願います。 # #  また、このスクリプトは、Windows 2000 Professional #  ActivePerl-5.8.4.810-MSWin32-x86.msi の環境にても動作確認を行っております。 #  Active Perl 5.8では、UTF-8のコード変換が標準の組み込みモジュールで #  実現できますので、jcode.pmのインストールは不要のはずですが、この標準モジュールは、 #  現時点では、使用していません。 # #  このスクリプトに対するご質問や不具合がございましたら、電子メールで、 #  webmaster@sakaguch.com まで、お寄せ下さい。 #  また、「鷹の巣」の自宅サーバー掲示板 #  http://sakaguch.com/cgi/bbs/ #  にご投稿して頂いても結構です。 # #--------------------------------------------------------------------------------- # 4.著作権 # #  このスクリプトは、鷹の巣が作成しましたが、著作権は放棄しています。 #  スクリプトの再配布や改造は自由ですが、無償として下さい。 #  いかなる目的であっても、このスクリプトに付加価値をつけて、 #  有償配布してはなりません。 # #--------------------------------------------------------------------------------- # 5.初期設定のログファイルの位置の例 # # D:\www\log\httpd.20030101.log (AN HTTPD のアクセスログファイル) # httpd.20030102.log # | # httpd.20030131.log # # referer.20030101.log (AN HTTPD のリフェラーログファイル) # referer.20030102.log # | # referer.20030131.log # # ua.20030101.log (AN HTTPD のUser Agentログファイル) # ua.20030102.log # | # ua.20030131.log # # 上記のログファイルの配置では、$LOGDIR ="D:/www/log"; と設定します。 # # # 出力ディレクトリ(アクセスログ解析AWStats用ログファイル) # D:\www\edit\awstats\wwwroot\log\2003\combined.200301.log # # 上記のログファイルの配置では、$OUTDIR ="D:/www/edit/awstats/wwwroot/log/2003"; # と設定します。 # #--------------------------------------------------------------------------------- # 6.起動方法 # #  2003年1月のログファイルデータでしたら、コマンドラインから、 #  perl combined.pl -year=2003 -month=01 の様に起動します。 #  引数がない場合は、エラー表示を行い、処理を終了します。 #   #  その他の引数 # -logdir=X ログファイルのディレクトリを指定(X=./でカレントディレクトリ) #   -outdir=X 出力ファイルのディレクトリを指定(X=./でカレントディレクトリ) #   -conv_ipaddr =X ログファイルのホスト名変換処理を指定(X=nで無変換) #   変換処理は、ログファイル自体を直接書き換えます。 #   -conv_combine=X combined log formatへの変換処理を指定(X=nで無変換) # #  AN HTTPDのログのディレクトリに処理対象のログファイルがない場合は、 #  すぐに終了し、サイズ0のファイルが生成されます。 # #--------------------------------------------------------------------------------- # 7.ご注意 # #  combinedログファイルとは、combined log format (NCSA combined/XLF/ELF log format)のことです。 #  生成されたアクセスログ解析用のcombinedログファイルは、アクセスログへの読み込みが #  終了しましたら、削除した方が良いと考えます。 #  このcombinedログファイルは、ログファイル(Access LogとReferer LogとUser Agent Log) #  を連結したものですが、Referer LogとUser Agent LogをAccess Logに適当に連結しています。 #  AWstats以外のアクセスログ解析以外では、検証していませんので、ご注意願います。 # #  生成されるログファイルは、プライベートアドレスが記録されているアクセス行と #  アクセス元の行を除外します。これは、自サイトのLAN内からのアクセス記録を除外することと #  他サイトのLAN内からのアクセス記録を除外することを目的としています。 #  他サイトのLAN内からのアクセス記録を除外するのは、他サイトへのセキュリティ対策です。 # #--------------------------------------------------------------------------------- #--------------------------- #■□■ 基本設定 ■□■ #--------------------------- # ログファイルのディレクトリ(フォルダ)の設定 # コマンドラインから-logdir=XXで、与えられた場合は、引数の値が有効になります。 #$LOGDIR ="D:/www/log"; $LOGDIR ="."; # カレントディレクトリの場合 # 出力ファイルのディレクトリ(フォルダ)の設定 # コマンドラインから-outdir=XXで、与えられた場合は、引数の値が有効になります。 #$OUTDIR ="D:/www/edit/awstats/wwwroot/log"; $OUTDIR ="."; # カレントディレクトリの場合 # ログファイルのホスト名変換処理(y:変換する。n:変換しない。) # コマンドラインから-conv_ipaddr=Xで、与えられた場合は、引数の値が有効になります。 $CONV_IPADDR = "y"; # AccessログとRefererログとUser Agentログを合成して、combined log format # (NCSA combined/XLF/ELF log format)に変換して出力します。(y:変換する。n:変換しない。) # コマンドラインから-conv_combine=Xで、与えられた場合は、引数の値が有効になります。 $CONV_COMBINE = "y"; #------------------------------- #■□■ 基本設定の終わり ■□■ #------------------------------- # refererとuser agentで先読みする行数(5分間程度の最大記録行数を設定) $buffer_line = 200; # Accessログから、プライベートアドレスを除外する。(1:除外する、0:除外しない) $FLAG_OMIT_ACC = 1; # Refererログから、プライベートアドレスを除外する。(1:除外する、0:除外しない) $FLAG_OMIT_REF = 1; #------------------------------- # 設定の終わり #------------------------------- # 主回路 &main; exit; sub main { #--------------------------- # 主回路 #--------------------------- # 処理:アクセスログファイル(httpd.yyyymmdd.log)に記録されているIPアドレスをホスト名(FQDN)に変換する。 # その後にアクセスログ解析用のcombinedログファイルの生成処理を行います。 #    combinedログファイルとは、combined log format (NCSA combined/XLF/ELF log format)のことです。 # # 入力:月日単位のperlコマンドライン引数$ARGV[0]と$ARGV[1] 例.2003年1月だったら、2003 01 # 出力:毎日のhttpdログファイルと月単位のcombinedログファイル # 改版番号の表示 print "$ver\n\n"; # コマンドライン引数の処理 if ( !$ARGV[0] ) { &help; } &hikisuu; if ( $HIKISUU{'conv_ipaddr'} ) { $CONV_IPADDR = $HIKISUU{'conv_ipaddr'}; } if ( $HIKISUU{'conv_combine'} ) { $CONV_COMBINE = $HIKISUU{'conv_combine'}; } if ( $CONV_COMBINE eq "y") { # 日本語コード変換jcode.pmモジュールの使用を宣言する。 eval 'use Jcode;'; if ( $@ ) { &error ( "jcode.pmモジュールが必要です。追加インストールして下さい。" ); } } # 月単位のログファイルのホスト名変換処理を行なう。 &conv_month_log ( $YEAR , $MONTH ); print "\n処理が終了しました。\n\n"; # 改版番号の表示 print "$ver\n"; } sub conv_month_log { #---------------------------------------- # 月単位のログファイルのホスト名変換処理 #---------------------------------------- # 処理:月単位のログファイルに含まれるIPアドレスをホスト名(FQDN)に変換する。 # # 入力:ログファイルの$year年と$month月 # 出力:毎日のhttpdログファイルと月単位のcombinedログファイル my ( $year , $month ) = @_; my ( $Fname , $INfile , $OUTfile ); $FnameM = sprintf( "%04d%02d" , $year , $month ); $combine_log = "$OUTDIR/combined.$FnameM.log"; open (OUT_COMBINE , ">$combine_log" ); for ( 1..31 ) { # 引数には、200301の様な月単位の数値が入るので、これを20030101?20030131の日付に変更する。 $Fname = $FnameM . sprintf( "%02d" , $_ ); # ログディレクトリのhttpd.20030101.log?httpd.20030131.logというファイル名にする。 $INfile = "$LOGDIR/httpd.$Fname.log"; $OUTfile = $INfile . ".hostlog"; # ファイルの存在を検査。 if ( -e "$INfile" ) { # 日単位のログファイルのホスト名(FQDN)変換処理を行なう。 if ( $CONV_IPADDR eq "y" ) { &conv_day_log ( $INfile , $OUTfile ); # 一時ファイルの消去 unlink ( $INfile ); rename ( $OUTfile , $INfile ); } if ( $CONV_COMBINE eq "y" ) { # AccessログとRefererログとUser Agentログを合成して、combined log formatに変換して出力します。 $access = "$LOGDIR/httpd.$Fname.log"; $referer = "$LOGDIR/referer.$Fname.log"; $user_agent = "$LOGDIR/ua.$Fname.log"; &conv_combine_log ( $INfile , $referer , $user_agent , $combine_log , OUT_COMBINE ); } else { # AccessログのコードをEUCにして、出力します。 &join_log ( $INfile , $combine_log , OUT_COMBINE ); } } } close (OUT_COMBINE ); } sub conv_day_log { #---------------------------------------- # 日単位のログファイルのホスト名変換処理 #---------------------------------------- # 処理:日単位のログファイルに含まれるIPアドレスをホスト名(FQDN)に変換する。 # # 入力:ログファイル$filenameIn # 出力:ログファイル$filenameOut my ( $filenameIn , $filenameOut )= @_; my ( $line , $host ); my $line_count = 0; # 記録ファイルから読み込み open ( OUT , ">$filenameOut" ) || &error ( "Open Error : $filenameOut" ); open ( IN , "<$filenameIn" ) || &error ( "Open Error : $filenameIn" ); print "$filenameInを処理中です。\n"; while ( $line = ) { # IPアドレスをホスト名(FQDN)に変換する。 $newline = &conv_ip_to_host ( $line ); print OUT "$newline"; $line_count++ ; if ( !( $line_count % 5000 ) ) { $| = 1; print "$line_count "; $| = 0; } } close(IN); close(OUT); print "$line_count\n"; } sub conv_ip_to_host { #--------------------------- # ホスト名(FQDN)変換処理 #--------------------------- # 処理:ログファイルの記録行の行先頭のIPアドレスをホスト名(FQDN)に変換する。 # # 入力:ログファイルの記録行 # 出力:ログファイルの記録行 my ( $logline ) = @_; my ( $error_count , $host , $newlogline ); # 最初の区切り符号であるスペースの位置を検出する。 $point = index( $logline , " " ); # IPアドレスを切り出す。 $ip = substr ( $logline , 0 , $point ); # 逆引き出来なかったIPアドレスは、ホスト名をIPアドレスにする。 $host = $ip; if ( $ip =~ m/^[0-9\.]+$/ ){ # IPアドレスが記録されていれば、IPアドレスをホスト名(FQDN)に変換する。 # IPアドレスの後ろのデータを切り出す。 $data = substr ( $logline , $point + 1 ); # 直前に処理したIPアドレスかどうかを調べる。 if ( $ip eq $prev_ip ) { # ホスト名は、前回変換したホスト名と同じにする。 $host = $prev_host; } else { # 逆引き出来なかったIPアドレスかどうかを調べる。 $flag_no_host = 0; foreach ( @no_host ) { if ( $_ eq $ip ) { $flag_no_host = 1; last; } } # 逆引き出来なかったIPアドレスでなければ、ホスト名に変換する。 if ( $flag_no_host ) { } else { # IPアドレスをホスト名(FQDN)に変換する。 $host = gethostbyaddr ( pack ( 'C4' , split ( /\./ , $ip ) ) , 2 ); if (!$host) { # 逆引き出来なかったIPアドレスは、ホスト名をIPアドレスにする。 $host = $ip; # 逆引き出来なかったIPアドレスを配列に記録する。 unshift ( @no_host , $ip ); # 逆引き出来なかったIPアドレスを標準出力に出力する。 # print "$host*"; } } } # 変換したホスト名で、変換後のログ記録行を作成する。 $newlogline = "$host $data"; } else { # ホスト名(FQDN)が記録されていれば、変換しない。 $newlogline = $logline; } # 今回処理したIPアドレスとホスト名を広域変数に保持する。 $prev_ip = $ip; $prev_host = $host; # 変換後のログ記録行を戻り値に設定する。 return $newlogline; } sub conv_combine_log { #--------------------------- # combinedログの生成処理 #--------------------------- # 処理:AccessログとRefererログとUser Agentログを1つのログファイルにまとめる。 #    combined log format (NCSA combined/XLF/ELF log format)に変換して出力する。 # # 入力:ログファイル名($access_logと$referer_logと$user_agent_logと$combine_log)と出力ファイルハンドル($out_combine) # 出力:出力ファイルハンドルにログファイルを生成 my ( $access_log , $referer_log , $user_agent_log , $combine_log , $out_combine ) = @_; my ( $access_line , $url , $flag , @referer , $referer_utf8 , @user_agent , $user_agent_utf8 ); my @referer_utf8 = (); my @referer_to = (); my @user_agent_utf8 = (); my @user_agent_to = (); print "$access_log と $referer_log と $user_agent_log を合成して、$combine_logに出力中\n"; open( IN_REFERER , "<$referer_log" ); open( IN_USERAGENT , "<$user_agent_log" ); open( IN_ACCESS , "<$access_log" ); # accessログデータの読み込み while ( $access_line = ) { # 行末改行コードの削除 chomp ( $access_line ); # accessログデータのアクセス先URLの切り出し $access_line =~ /(.*)\"(.*)\s(.*)\s(.*)\"(.*)/; # CGI引数部分の削除 ( $url ) = split /\?/ , $3 ; # アクセス元URLとアクセス元User Agentを初期化する。 $referer_utf8 ="-"; $user_agent_utf8 ="-"; # refererログデータの読み込み $flag = 0; for ( 0..$#referer_to ) { # アクセス先ファイルがバッファ内にあれば、アクセス元URLを付加する。 if ( $url eq $referer_to[$_] ) { $referer_utf8 = $referer_utf8[$_]; # アクセス先ファイルをバッファ内から削除する。 splice(@referer_utf8 , $_ , 1 ); splice(@referer_to , $_ , 1 ); $flag = 1; last; } } # アクセス先ファイルがバッファ内になければ、refererファイルから読み込む。 if ( !$flag ) { while ( $_ = ) { # 行末改行コードの削除 chomp ( $_ ); # アクセス元URLとアクセス先URLの切り出し @referer = split /\s->\s/, substr ( $_ , 25 ); # AN HTTPDの処理に特化 if ( $url eq $referer[1] ) { # アクセス先URLが一致したら、アクセス元URLを付加する。 $referer_utf8 = &conv_utf8 ( $referer[0] ); last; } else { # アクセス先URLが一致しなければ、アクセス元URLと共に配列に格納する。 if ( $#referer_to > $buffer_line ) { last; } push ( @referer_utf8 , &conv_utf8 ( $referer[0] ) ); push ( @referer_to , $referer[1] ); } } } # User Agentログデータの読み込み $flag = 0; for ( 0..$#user_agent_to ) { # アクセス先ファイルがバッファ内にあれば、アクセス元User Agentを付加する。 if ( $url eq $user_agent_to[$_] ) { $user_agent_utf8 = $user_agent_utf8[$_]; # アクセス先ファイルをバッファ内から削除する。 splice(@user_agent_utf8 , $_ , 1 ); splice(@user_agent_to , $_ , 1 ); $flag = 1; last; } } # アクセス先ファイルがバッファ内になければ、User Agentファイルから読み込む。 if ( !$flag ) { # User Agentログデータの読み込み while ( $_ = ) { # 行末改行コードの削除 chomp ( $_ ); # アクセス元User Agentとアクセス先URLの切り出し @user_agent = split /\s->\s/, substr ( $_ , 25 ); # AN HTTPDの処理に特化 if ( $url eq $user_agent[1] ) { # アクセス先URLが一致したら、アクセス元User Agentを付加する。 $user_agent_utf8 = &conv_utf8 ( $user_agent[0] ); last; } else { # アクセス先URLが一致しなければ、アクセス元User Agentと共に配列に格納する。 if ( $#user_agent_to > $buffer_line ) { last; } push ( @user_agent_utf8 , &conv_utf8 ( $user_agent[0] ) ); push ( @user_agent_to , $user_agent[1] ); } } } # combined log format (NCSA combined/XLF/ELF log format)に変換して出力する。 $flag = 0; # 自サイト内プライベートアドレスからのアクセスを検査 if ( $FLAG_OMIT_ACC ) { $flag = &is_private_addr( $access_line ); } # アクセス元がプライベートアドレスの場合のアクセス元を検査 if ( !$flag && $FLAG_OMIT_REF ) { $referer_utf8 =~ /(.*):\/\/([^:\/]*)/; $flag = &is_private_addr( $2 ); } # combined log formatを出力 if ( !$flag ) { print $out_combine "$access_line \"$referer_utf8\" \"$user_agent_utf8\"\n"; } } close( IN_ACCESS ); close( IN_USERAGENT ); close( IN_REFERER ); } sub join_log { #--------------------------- # 1ヶ月単位のログ生成処理 #--------------------------- # 処理:Accessログより自サイト内IPアドレスを除去して、コードをEUCに変換し、1ヶ月単位のログ生成を行なう。 # # 入力:ログファイル名($access_logと$out_log)と出力ファイルハンドル($out) # 出力:出力ファイルハンドルにログファイルを生成 my ( $access_log , $out_log , $out ) = @_; my ( $flag ); print "$access_log を $out_logに出力中\n"; open( IN_ACCESS , "<$access_log" ); while ( ) { # 行末の改行コードを除去 chomp ( $_ ); $flag = 0; # 自サイト内プライベートアドレスからのアクセスを検査 if ( $FLAG_OMIT_ACC ) { $flag = &is_private_addr( $_ ); } # アクセス元がプライベートアドレスの場合のアクセス元を検査 if ( !$flag && $FLAG_OMIT_REF ) { $_ =~ /(.*):\/\/([^:\/]*)/; $flag = &is_private_addr( $2 ); } if ( !$flag ) { # コードをEUCに変換して出力する。 $_ = &conv_utf8 ( $_ ); print $out "$_\n"; } } close( IN_ACCESS ); } sub is_private_addr { #------------------------------------ # 行頭のプライベートアドレス判定処理 #------------------------------------ # 処理:Accessログ行頭が自サイト内プライベートアドレスを含むかどうかを検出する。 # # 入力:Accessログ行($line) # 出力:戻り値は、プライベートアドレスで1、プライベートアドレス以外で0 my $line = $_[0]; my ( $ip_addr ) = split /\s/ , $line ; if ( $ip_addr =~ /(^127\.0\.0\.1|^10\.|^192\.168\.)/ ) { return 1; } if ( $ip_addr =~ /^172\.(\d+)\.(\d+)\.(\d+)$/ ) { if ( $1 > 18 && $1 < 32 ) { return 1; } } return 0; } sub conv_utf8 { #--------------------------- # 拡張UNIXコード変換処理 #--------------------------- # 処理:URLデコードし、漢字コードを拡張UNIXコードに変換する。 # # 入力:変換前文字列 # 出力:変換後文字列 my $moji = $_[0]; my $moji_utf8 = $moji; # URLデコード $moji_utf8 =~ tr/+/ /; $moji_utf8 =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; # タグの処理 $moji_utf8 =~ s/<//g; $moji_utf8 =~ s/&/&/g; $moji_utf8 =~ s/"/"/g; # jcode.pm モジュールを使用(Perl 5.6以前とPerl 5.8でも必要) # # 文字コードの種類を調べる # Jcode::convert ( \$moji_utf8 , $code ); # シフトJISコードに変換(半角カナを全角カナに変換) # Jcode::convert ( \$moji_utf8 , 'utf8' , $code , "z" ); # 拡張UNIXコードに変換(半角カナを全角カナに変換) $moji_utf8 = jcode ( $moji_utf8 ) -> h2z -> utf8 ;# ************ 2004.03.22 eucよりutf8コードに変更。************ # 変換したrefererを戻り値に設定する。 return $moji_utf8; } sub hikisuu { #--------------------------- # 引数処理 #--------------------------- # 処理:コマンドラインの引数をURLデコードし、漢字コードを拡張UNIXコードに変換する。 # # 入力:コマンドライン引数 例.$ARGV[0] = '-year=2003' , $ARGV[1] = '-month=1',・・・$ARGV[n] # 出力:引数の値      例.$HIKISUU{'year'} = 2003 , $HIKISUU{'month'} = 1 ,・・・ my ( @pairs , $pairs); my $buffer = ""; # コマンドライン引数の連結 for ( 0..$#ARGV ) { $buffer .= $ARGV[$_]; } # 引数の分解 @pairs = split( /-/ , $buffer ); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); # 引数の変数を小文字に変換 $name =~ tr/[A-Z]/[a-z]/; # 引数に含まれる\を/に置換する(Windowsのディレクトリ用) $value =~ s|\\|/|g; # 引数の値の末尾の/を除去(ディレクトリ用) $value =~ s|/$||; # 連想配列に格納 $HIKISUU{$name} = $value; } # 西暦年データの矯正 if ( $HIKISUU{'year'} ) { $YEAR = $HIKISUU{'year'}; } if ( $YEAR < 1000 ) { $YEAR = $YEAR + 2000; } # 月データの矯正 if ( $HIKISUU{'month'} ) { $MONTH = $HIKISUU{'month'}; } if ( $MONTH >= 1 && $MONTH <= 12 ) { $MONTH = sprintf ("%02d" , $MONTH ); } else { error("$MONTH月の数値が不正です。"); } # ログファイルのフォルダ(ディレクトリ)の検査 if ( $HIKISUU{'logdir'} ) { $LOGDIR = $HIKISUU{'logdir'}; } if ( !( -d $LOGDIR ) ) { error("ログファイルのフォルダ(ディレクトリ)$LOGDIRがありません。"); } # 出力ファイルのフォルダ(ディレクトリ)の検査 if ( $HIKISUU{'outdir'} ) { $OUTDIR = $HIKISUU{'outdir'}; } if ( !( -d $OUTDIR ) ) { error("出力ファイルのフォルダ(ディレクトリ)$OUTDIRがありません。"); } return $#ARGV; } sub help { print "このスクリプトは、WWWサーバーのログのIPアドレスをホスト名に変換し、combined log formatに変換します。\n\n"; print "例.2003年1月のログデータの場合、\n"; print " perl combined.pl -year=2003 -month=01\n"; print " perl combined.pl -year=2003 -month=01 -logdir=D:/www/log -outdir=./\n"; print " perl combined.pl -year=2003 -month=01 -logdir=D:\\www\\log -outdir=.\\\n"; print " として下さい。\n\n"; print "その他-logdir=X ログファイルのフォルダ(ディレクトリ)を指定(X=./でカレントディレクトリ)\n"; print " -outdir=X 出力ファイルのフォルダ(ディレクトリ)を指定(X=./でカレントディレクトリ)\n"; print " -conv_ipaddr =X ログファイルのホスト名変換処理を指定(X=nで無変換)\n"; print " 変換処理は、ログファイル自体を直接書き換えます。\n"; print " -conv_combine=X combined log formatへの変換処理を指定(X=nで無変換)\n"; exit; } sub error { # エラーの内容を表示して終了する。 print "$_[0]\n"; exit; }