ApacheのRefererログの解析

postanalogとかanalogurldecode.plとか色々試してみたんだけど、いくつか気に入らない点(集計がいまいちとか文字コードの制約とか)があったのと、decodeに失敗したりするのがイヤで、自前でphpで書いてみた。
ただし、urlエンコードすべきところをhtmlのエンティティか何かにエンコードするブラウザだかがあるようで、その部分の対策はまだですけどね。
使い方としては、crontabで午前1時頃に回すのが良いかと思いますけど、適宜カスタマイズしてください。

<?php
    
//written by rio@rio.st
    //Apacheのcombinedログに対応しています。
    //CustomLog '|/usr/sbin/rotatelogs /var/log/httpd/access_log.%Y%m%d 86400 540' combined
    //上記設定では毎日0:00(JST)にログを回します。
    //analog5.0.2以上(文字コードに関して)

//昨日の日付を取得
function get_yesterday(){
    return
date(DATE_FORMAT, mktime()-86400);
}

    if(!$this = basename($_SERVER[“SCRIPT_FILENAME”])){
        
$this = $_SERVER[“argv”][0];
    }
    
$usage = <<<EOF
Usage : $this [-i path_to_decode] [-o path_to_output] [-D t/y] [-d YYYYMMDD] [-C e/s/j/u]
  -D select ‘t’oday or ‘y’esterday log to decode
  -d log suffix ex. ‘access_log.YYYYMMDD’
  -C EUC-JP/SJIS/JIS/UTF-8

EOF;    define(“DEF_INPUT_FILE”, “/var/log/httpd/access_log”); //デフォルトの入力ファイル
    
define(“DEF_OUTPUT_FILE”, “/var/log/httpd/access_log_decoded”); //デフォルトの出力ファイル
    
define(“DATE_FORMAT”, “Ymd”); //日付の書式=apacheの%Y%m%d
    
define(“FLD_NO”, 10); //combinedログでのリファラフィールドの位置 0 originでカウントします。
    //引数のチェック
    
switch($_SERVER[“argc”]){
    case
1:
    case
3:
    case
5:
    case
7:
    case
9:
    case
11:
        break;
    default:
        exit(
$usage);
    }
    
$option = getopt(“i:o:D:d:C:”);
    
$input = $option[“i”];
    
$output = $option[“o”];
    if(
$day_switch = $option[“D”]){
        if(
$day_switch != “t” && $day_switch != “y”){
            exit(
$this.” : day switch is ‘t’ or ‘y’\n”);
        }
    }
    if(
$date = $option[“d”]){
        
$year = substr($_SERVER[“argv”][3], 0, 4);
        
$month = substr($_SERVER[“argv”][3], 4, 2);
        
$day = substr($_SERVER[“argv”][3], 6, 2);
        if(
checkdate($month, $day, $year)){
            
$date = $year.$month.$day;
        } else {
            exit(
$this.” : illegal time format ‘”.$date.“‘\n”);
        }
    }
    switch(
$char = $option[“C”]){
    case
“”:
        if(
$ret = exec(“analog -settings | grep ‘Language file'”, $res)){
            switch(
basename($res[0])){
            case
“jpe.lng”:
                
$charset = “EUC-JP”;
                break;
            case
“jps.lng”:
                
$char = “SJIS”;
                break;
            case
“jpj.lng”:
                
$char = “JIS”;
                break;
            case
“jpu.lng”:
                
$char = “UTF-8”;
                break;
            default:
                
$charset = ini_get(“mbstring.http_output”);
            }
        } else {
            
$charset = ini_get(“mbstring.http_output”);
        }
        break;
    case
“e”:
    case
“E”:
        
$charset = “EUC-JP”;
        break;
    case
“s”:
    case
“S”:
        
$charset = “SJIS”;
        break;
    case
“j”:
    case
“J”:
        
$charset = “JIS”;
        break;
    case
“u”:
    case
“U”:
        
$charset = “UTF-8”;
        break;
    default:
        exit(
$this.” : selected charset is not supported!\n”);
    }
    if(
$input && $output){ //ファイル名だけで処理 $input -> $output
    
} else if($input && $output && $day_switch){ //ファイル名と当日あるいは昨日を処理 $input.YYYYMMDD -> $output.YYYYMMDD
        
if($day_switch == “t”){
            
$d = “.”.date(DATE_FORMAT);
        } else {
            
$d = “.”.get_yesterday(DATE_FORMAT);
        }
    } else if(
$input && $output && $date){ //ファイル名と日付のsuffixで処理 $input.$date -> $output.$date
        
$d = “.”.$date;
    } else if(!
$input && !$output && $day_switch){ //defineされたファイルと当日あるいは昨日のみで処理
        
$input = DEF_INPUT_FILE;
        
$output = DEF_OUTPUT_FILE;
        if(
$day_switch == “t”){
            
$d = “.”.date(DATE_FORMAT);
        } else {
            
$d = “.”.get_yesterday(DATE_FORMAT);
        }
    } else if(!
$input && !$output && !$day_switch && !$date){ //defineされたファイルのみで処理、昨日のファイルを処理
        
$input = DEF_INPUT_FILE;
        
$output = DEF_OUTPUT_FILE;
        
$d = “.”.get_yesterday(DATE_FORMAT);
    } else {
        exit(
$usage);
    }

    $input .= $d;
    
$output .= $d;

    if(!file_exists($input)){
        exit(
$this.” : file “.$input.” can’t be found!\n”);
    }
    if(!
$fp = fopen($output, “w”)){
        exit(
$this.” : file “.$output.” can’t be created!\n”);
    }

    if($file = file($input)){
        foreach(
$file as $line){
            
$wk = explode(” “, $line);
            
$tmp = urldecode($wk[FLD_NO]);
            if(
$enc = mb_detect_encoding($tmp){
                
$wk[FLD_NO] = strtolower(mb_convert_encoding($tmp, $charset, $enc));
                
fwrite($fp, implode(” “, $wk));
            }
        }
    }
    
fclose($fp);
    
exec(“/usr/bin/analog”);
?>
</code

タイトルとURLをコピーしました