Nginx + AWStats によるアクセス解析

スポンサーリンク

 Nginx への移行で AWStats の Perl スクリプトを実行する所が、面倒でややこしかったのでアクセス解析画面を出すまでを簡単に書く殴ってみる。

はじめに

 ファイルの命名規則は何でも良いけど連携する部分があるので合わせること。
 ドメイン名は慣例的に example.com を使用。

AWStats のインストール

 AWStats オフィシャルサイトより RPM をダウンロードしてくる。中身はスクリプトのみで noarch だからディストリは何でも入るはず。

wget 'http://prdownloads.sourceforge.net/awstats/awstats-7.4-1.noarch.rpm'
rpm -ivh awstats-7.4-1.noarch.rpm

 以後は nginx ユーザー権限で動かすから chown しておく。

chown -R nginx. /usr/local/awstats/wwwroot

Nginx の設定ファイル

 AWStats 専用のサブドメインをローカルからのみアクセス出来る様にしているから、この例はサブドメイン用になる。(内向きにのみ DNS RR を書いている運用)

server {
    listen 80;
    server_name awstats.example.com;
    root /usr/local/awstats/wwwroot;
    index index.html;

    charset UTF-8;

# ===== Logging.
    access_log /var/log/nginx/awstats.example.com/access_log main;
    error_log  /var/log/nginx/awstats.example.com/error_log warn;

# ===== Do not Logging.
    location = /favicon.ico {
        log_not_found off;
        access_log    off;
    }

    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log    off;
    }

    location / {
        rewrite ^/(.*)$ /cgi-bin/awstats.pl?config=$1;
    }

# ===== for Awstats.
    location /icon {
        alias /usr/local/awstats/wwwroot/icon;
    }

    location /css {
        alias /usr/local/awstats/wwwroot/css;
    }

    location ~ ^/cgi-bin/.*\.(cgi|pl|py|rb) {
        gzip off;
        fastcgi_pass  unix:/var/run/php-fpm/php-fpm.sock;
        fastcgi_index cgi-bin.php;
        fastcgi_param SCRIPT_FILENAME    /etc/nginx/cgi-bin.php;
        fastcgi_param SCRIPT_NAME        /cgi-bin/cgi-bin.php;
        fastcgi_param X_SCRIPT_FILENAME  /usr/local/awstats/wwwroot$fastcgi_script_name;
        fastcgi_param X_SCRIPT_NAME      $fastcgi_script_name;
        fastcgi_param QUERY_STRING       $query_string;
        fastcgi_param REQUEST_METHOD     $request_method;
        fastcgi_param CONTENT_TYPE       $content_type;
        fastcgi_param CONTENT_LENGTH     $content_length;
        fastcgi_param GATEWAY_INTERFACE  CGI/1.1;
        fastcgi_param SERVER_SOFTWARE    nginx;
        fastcgi_param REQUEST_URI        $request_uri;
        fastcgi_param DOCUMENT_URI       $document_uri;
        fastcgi_param DOCUMENT_ROOT      $document_root;
        fastcgi_param SERVER_PROTOCOL    $server_protocol;
        fastcgi_param REMOTE_ADDR        $remote_addr;
        fastcgi_param REMOTE_PORT        $remote_port;
        fastcgi_param SERVER_ADDR        $server_addr;
        fastcgi_param SERVER_PORT        $server_port;
        fastcgi_param SERVER_NAME        $server_name;
        fastcgi_param REMOTE_USER        $remote_user;
    }

# ===== Error Page
    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

 更に、AWStats は Perl スクリプトなので普通なら spawn-fcgi やらで実行させる様だが、上手く動かすことが出来ずに禿げ上がりそうだったので PHP で Wrap してしまう手法で逃げた。参考 : Awstats – ArchWiki
 次のファイルを /etc/nginx/cgi-bin.php として作成する。

<?php
$descriptorspec = array(
   0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
   1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
   2 => array("pipe", "w")   // stderr is a file to write to
);
$newenv = $_SERVER;
$newenv["SCRIPT_FILENAME"] = $_SERVER["X_SCRIPT_FILENAME"];
$newenv["SCRIPT_NAME"] = $_SERVER["X_SCRIPT_NAME"];
if (is_executable($_SERVER["X_SCRIPT_FILENAME"])) {
   $process = proc_open($_SERVER["X_SCRIPT_FILENAME"], $descriptorspec, $pipes, NULL, $newenv);
   if (is_resource($process)) {
       fclose($pipes[0]);
       $head = fgets($pipes[1]);
       while (strcmp($head, "\n")) {
           header($head);
           $head = fgets($pipes[1]);
       }
       fpassthru($pipes[1]);
       fclose($pipes[1]);
       fclose($pipes[2]);
       $return_value = proc_close($process);
   } else {
       header("Status: 500 Internal Server Error");
       echo("Internal Server Error");
   }
} else {
   header("Status: 404 Page Not Found");
   echo("Page Not Found");
}
?>

cron に登録

 毎時更新としたかったので、/etc/cron.hourly/0awstats としてスクリプトを設置して chmod 755 しておく。
 if ブロックは別に無くても構わないが、Nginx デフォルトの nginx.conf にあるアクセスログファイル名を見るようにしている。

#!/bin/bash

if [ -f /var/log/nginx/access.log ] ; then
    /bin/perl /usr/local/awstats/tools/awstats_updateall.pl now > /dev/null
fi
exit 0

AWStats の設定ファイル作成

 /etc/awstats 以下に awstats.model.conf というベースとなる設定ファイルがあるので、model の部分を解析するホスト名に置き換えてコピーした上で編集する。

cd /etc/awstats
cp awstats.model.conf awstats.example.com.conf
vi awstats.example.com.conf

 最低限変数する箇所は LogFile= で解析するログのパス、SiteDomain= のホスト名になる。それ以外は取り敢えず設置後追々で良いかなと思う。

...
LogFile=/var/log/nginx/example.com/access_log
...
...
...
SiteDomain="example.com"
...
...

動作確認

 Nginx を起動若しくは再起動を行う前に構文チェックだけしておく。

# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
                                    success 表示なら OK ^^^^^^^^^^
# systemctl restart nginx

 Nginx が起動したらブラウザに http://awstats.example.com/example.com などと打ち込むと解析結果画面が出る。
 本来、「http://awstats.example.com/cgi-bin/awstats.pl?config=example.com」となるのだが、長いので rewrite して簡単にアクセス出来る様にしている。この形式が嫌なら自分で書き換えると良い。
 実際の解析は毎時設定なので、取り敢えず即時解析をしたければ「/etc/cron.hourly/0awstats」を実行する。

おわりに

 AWStats の設定ファイルは結構な量があるから、取り敢えず初歩的な解析をさせた上、後々に特定ホストや LAN 内クライアントを除外するだとか BOT 除外など突き詰めていくと良いかも知れない。

追記事項

  • 2015/12/19 22:41 – Nginx の設定で CSS と ICON に関する alias を書き忘れていたので追加。
スポンサーリンク