AnalizeACSLog.pl

#!/usr/local/bin/perl
# (c)copyleft 2021 : Coded by shun kinoshita / knuhs
# ホームページのアクセスログを解析しプログラムのアクセスカウンター
# の管理情報を得るためのプログラム( AnalizeACSLog.pl )

use  strict;
my   %HashTBL;

my   $Debug = 0;   # =1 なら内部情報を出力する。=0 なら出力しない

     # ログファイルのある場所を定義する
my   $directory1 = "C:/cdatFile/itscom/access-log";

     # アクセスカウンター値を置く場所
my   $directory2 = "C:/cdatFile";


# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# Step1: ログファイルの選択
#
     # ログがある場所を開いてログファイルの名前をすべて読み込む
     opendir(DIR, "$directory1") || die "開けません: $!";

     # 名前をソートしてリストにする
my   @datalist = sort grep(/access\d{8}\.txt/, readdir(DIR));

     # 使用後のログファイを無効にするために用いる
my   $logname ;

     # リスト中の項目の数を調べる
     my $i;
     while( $datalist[$i] ){ $i++; }

     if( $i == 0 )
     {   print "処理可能なログはありません\n"; exit;   }
     else
     {   print "\n未処理のログが $i 個あります。\n時系列で最初のものから処理します\n";   }

     closedir(DIR);

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# Step2: ログファイルの解剖
#

my   $cgi = 0;  # 検出したカウンター情報の総数を記録する
my   $n;        #
my   $Key;      # キーを記憶する
my   $DTname;   # カウンターの変数名を記憶する
my   $STvalue;  # カウンターの初期値を記憶する
my   $Url;      # URL を記憶する
my   $DTtime;   # 日時(Date, Time)を記憶する

     # 英語の月表示を日本の月数に変換する
my   %Manth = ('Jan' => '01', 'Feb' => '02', 'Mar' => '03', 'Apr' => '04',
               'May' => '05', 'Jun' => '06', 'Jul' => '07', 'Aug' => '08',
               'Sep' => '09', 'Oct' => '10', 'Nov' => '11', 'Dec' => '12');

my    $line;

foreach my $fname ( @datalist )   # 一度に処理したいログのリスト
{
     # ログファイルの処理結果を集計する
     $fname =~ m/access(\d{4})(\d\d)(\d\d)\.(txt)/;
     print "\n\n(*)【$1-$2-$3の集計結果】\n";

     $logname = "$1-$2-$3.txt";   # 集計後は(重複使用を避けるため)別名に変える

     # ログファイルを開いて‥‥
     open(LOG, "<$directory1/$fname") || die "開けません: $!";
     # 1行ずつ読み込む
     while( defined( $line = <LOG> ) )
     {
          chomp;   # 最後の改行コードを削除
          # 手がかりとなる部分が行の先頭にあるか調べる
          unless ( $line =~ m/cgi01.itscom.net/ ){ next; }   # 無ければ次の行へ
          $cgi++;   # cgi 関連情報あり(個数をカウントする)
          # 必要な情報を抜き出す
          $line =~ m/\[(.*?)\]((.*?)=f1003240\.)((.*?)\.dat)((.*?)st=(.*?)\|)(.*?)"(http:(.*?))"/;
          print "【$cgi】\n" if $Debug ;   # Debug 中なら出力する
          $DTtime = $1;     # 最初の赤かっこ
          $Key = $5;        # 2番目の赤かっこ
          $DTname = $4;     # 1番目の緑かっこ
          $STvalue = $8;    # 3番目の赤かっこ
          $Url = $10;       # 4番目の赤かっこ
          # 日時表記の変換
          $DTtime =~ s|(\d{2})\/(\w{3})\/(\d{4})(:\d{2}:\d{2}:\d{2}(.*))|\3/$Manth{$2}/\1\4|g;
          # 日時の表記を 14/Nov/2021:10:43:15 +0900 から
          #            2021/11/14:10:43:15 +0900 に変換する
          $STvalue =~ s/(\d+)xxxxx/\1/;   # ct90.dat の整形処理

          print "Key = $Key\n"         if $Debug ;
          print "DTtime = $DTtime\n"   if $Debug ;
          print "DTname = $DTname\n"   if $Debug ;   # Debug 中なら出力
          print "STvalue = $STvalue\n" if $Debug ;
          print "Url = $Url\n"         if $Debug ;

          # 得られた情報を hash 領域に保存する
      my  $i = ++$HashTBL{$Key}[0];       # Key を登録し出現回数を記録する
          $HashTBL{$Key}[1] = $DTname;    # DTname
          $HashTBL{$Key}[2] = $STvalue;   # STvalue
          $HashTBL{$Key}[3] = $Url;       # Uniform Resource Locator
          $HashTBL{$Key}[3+$i] = $DTtime; # Date & Time

     }   # end of while( defined.....
     close(LOG);   # ログファイルの処理が終わったので閉じる

     # 使用済みのログファイルの名前を変えて重複使用しないようにする
     rename( "$directory1/$fname", "$directory1/UpdateDone$logname" );

}   # end of foreach my $fname .....

     print "\nDone! Step2\n" if $Debug ;

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# Step3: アクセスカウンターの管理
#

my   @status = 0;
     $Debug = 0;
my   $max = 1;
my   $k = 0;   # key の個数をカウントする

     print "\nStart Step2\n";

     # hash 領域に集めた情報を整理する
     foreach my $id( keys %HashTBL )
     {
          $n       = $HashTBL{$id}[0];     # 呼ばれた回数(=カウンターの増分となる)
          $DTname  = $HashTBL{$id}[1];     # カウンター変数名(cxxnn.dat)
          $STvalue = $HashTBL{$id}[2];     # カウンターの初期値
          $Url     = $HashTBL{$id}[3];     # 呼び出された場所
          $DTtime  = $HashTBL{$id}[3+$n];  # $n 個分の日時が保管されている

          # 整理した情報を出力する
          $k++;
          print "\n(*)【$k】\n";
          print "(*)\$n       = $HashTBL{$id}[0]\n";
          print "(*)\$DTname  = $HashTBL{$id}[1]\n";
          print "(*)\$STvalue = $HashTBL{$id}[2]\n";
          print "(*)\$Url     = $HashTBL{$id}[3]\n";
          for(my $m = 1; $m <= $n; $m++)
          {     print "(*)\$DTtime  = $HashTBL{$id}[3+$m]\n"; }

          # 管理データを集める
          $status[$n]++;
          $max = $n>$max ? $n : $max ;

          # ファイルを調べる
my   $firstTime = 0;
my  ($left, $right);

          # 個々のファイルを読み込む
          open(IN, "+<$directory2/$DTname");

          $_ = <IN>;
          if ( $_ )
          {    # ファイルあり
               $_ =~ m/((\d)*)(\$+)(.*)/;  # カウンター数($1)と
               $left = $1;                 # 日時情報($4)とは、
               $right = $4;                # '$'で区切られている
               print "\$left = $left\n"  if $Debug ;
               if ( $right == "" )
               {   $right = $HashTBL{$id}[3+$n];   }
               print "\$right = $right\n" if $Debug ;
          }
          else
          {    # ファイルが見つからない
               $firstTime = 1;   # 初めて使われた
               print "(*)ファイルが存在しません。\n";
               # 前ホームページ最後のカウンター数を用いる
               $left = $STvalue;
               $right = '2021/10/28:09:00:28 +0900';   # 前ホームページ最後の日
          }

          if ( $right == "" ){ $right = $HashTBL{$id}[3+$n]; }
          print "(*)カウンター値 = $left\$$right\n";
          close(IN);

          print "\$left = $left\n" if $Debug ;
          print "\$right = $right\n" if $Debug ;

          if ( $firstTime )
          {    $left = $left + $n - 1;     # 初出
               $right = $HashTBL{$id}[3+$n];
          }
          else
          {    $left = $left + $n;         # 既出
               $right = $HashTBL{$id}[3+$n];
          }
          print "\$left = $left\n" if $Debug ;

          # カウンター値をアップデートする
          open(OUT, ">$directory2/$DTname");
          $DTname = "$left\$$right";

          print "(*)加算後の値 = $DTname\n";
          printf OUT $DTname;  # printf を用いる!!
          close(OUT);

     }   # end of foreach my $id( keys %HashTBL )

     print "\n統計データ\n";

     for(my $i=1; $i <= $max; $i++)
     {
          my $value = $status[$i];
          next if $value == 0 ;
          printf "参照回数 %d 回 : %d 組\n", $i, $value;
     }
     print "\nDone! Step3\n" if $Debug ;

exit;