Jít na obsah Jít na navigaci Jít na vyhledávání

Awstats rychle a jednoduše

Awstats je skript v Perlu, který zpracovává logy (nejen) webserveru a ve výsledku vyplivne pěknou statistiku přístupů. Dnes si ukážeme, jak Awstats lehce a efektivně nastavit.

Awstats

Standardní konfigurace Awstats se nachází v adresáři /etc/awstats, kde je i ukázkový soubor awstats.conf. Jelikož konfigurace podporuje funkci Include, využijeme tento soubor jako základ pro naše vlastní konfigurace.

Vytvoříme nový soubor awstats.domain.tld.conf:

# hlavní config, nejprve jej vhodně nastavíme (formát logů, pluginy atd.)
Include "/etc/awstats/awstats.conf"
# log soubor Apache (v mém případě)
LogFile="/home/www/logs/domain.tld.log"
# doména, povinný parametr, který se spíše uplatní při použití spojeného logu (o tom později)
SiteDomain="domain.tld"
# aliasy pro SiteDomain, doporučuji tento formát
HostAliases="REGEX[domain\.tld$]"

Apache 2

Nastavíme Apache, aby logoval. Direktiva CustomLog se může nacházet uvnitř i vně direktivy <VirtualHost>, podle toho, co všechno chceme logovat.

Jeden log pro každou doménu

Direktivu přidáme do odpovídajícího VirtualHosta:

<VirtualHost *:80>
    ServerName domain.tld
    ...
    CustomLog /home/www/logs/domain.tld.log combined
</VirtualHost>

Jeden log pro celý server

Přidáme mimo VirtualHost:

# vlastní formát logu, prefixem je jméno VirtualHosta
LogFormat "%{Host}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" cplus
CustomLog /home/www/logs/server.log cplus

V případě této konfigurace musíme Awstats říct o novém formátu logu, což provedeme přímo v konfiguraci awstats.conf úpravou řádky LogFormat:

LogFormat="%virtualname %host %other %logname %time1 %methodurl %code %bytesd %refererquot %uaquot"

Další nastavení

Alias /awstats-icon/ /usr/share/awstats/icon/
<Directory /usr/share/awstats/icon>
    Options None
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>

Namapuje adresář s obrázky Awstats do URL adresy /awstats-icon/.

Zpracování

K periodické aktualizaci dat nastavíme cron (pokud již tak distributor neudělal):

*/15 *  * * *   root    /home/bin/awstats_updateall.pl now --excludeconf=awstats.conf > /dev/null 2>&1

Skript awstats_updateall.pl a dalších pár šikovných skriptů nalezneme v adresáři /usr/share/doc/awstats/examples. Tento skript zpracovává všechny konfigurační soubory, takže aktualizuje všechny domény.

Máme-li správně nastavené CGI, což ve výchozí konfiguraci obvykle bývá, nalezneme webový frontend awstats na adrese http:domain.tld/cgi-bin/awstats.pl?con­fig=domain.tld//. Kromě řešení na bázi Perl frontendu a awstats_updateall.pl skriptu je však možné využít awstats_buildstaticpages.pl, který přímo vygeneruje HTML soubory do adresáře zadaného v parametru. Toto řešení převážně využívám na webhostingách, má však tu nevýhodu, že není možné zobrazit statistiky za jiná období a zákazník vždy vidí pouze aktuální měsíc.

Vylepšení

Napsal jsem rewrite, který podstatně zkrášluje adresu a parametr předávaný skriptu /cgi-bin/awstats.pl na webu:

RewriteEngine On
RewriteRule ^/?([^/]+)/$ /cgi-bin/awstats.pl?config=$1 [PT,L,QSA]

Výše zmíněný kód je vhodné aplikovat na určitou subdoménu, např. stats. Statistiky pak nalezneme na adrese http://stats.anotherdomain.tld/domain.tld/.

Statistiky subdomén

Awstats se samozřejmě dá nastavit tak, aby u určité domény logoval i každou subdoménu. Tento přístup kombinuje a upravuje formáty logů popsané výše. Každá subdoména musí mít svůj VirtualHost a definovaný log, v optimálním případě budou logy pro každou doménu zvlášť a v nich spojené logy subdomén s upraveným formátem (viz. jeden log pro celý server).

Štítky:

Vlastní chybové hlášky v Apachi a PHP

Standardní chybové hlášky v Apachi jsou z informativního charakteru naprosto dostačující, avšak z toho estetického nikoli. Kdekoho posléze napadne, jak tyto chybové hlášky přenastavit. Na tom samozřejmě není nic těžkého, stačí vhodná úprava do souboru .htaccess typu:

ErrorDocument 404 /neexistuje.html

Mít pro každý kód chyby jinou stránku je pak zbytečně komplikované. Naštěstí existuje řešení, jak různé kódy efektivně zpracovat na úrovni PHP. Základní zjednodušené nastavení souboru .htaccess pak bude vypadat obdobně:

ErrorDocument 400 http://400.dragonjake.net
# speciální hack pro 401 Authorization Required
Alias /401/ /var/www/html/
ErrorDocument 401 /401/index.php

ErrorDocument 403 http://403.dragonjake.net
ErrorDocument 404 http://404.dragonjake.net
ErrorDocument 500 http://500.dragonjake.net

Ve svém řešení využívám externí http:// adresy pro jednotlivé kódy zvlášť, v Apachi nastavené zhruba takto:

<VirtualHost *:80>
        ServerName dragonjake.net
        ServerAlias 400.dragonjake.net 403.dragonjake.net 404.dragonjake.net 500.dragonjake.net
        DocumentRoot /var/www/html
</VirtualHost>

V adresáři /var/www/html se nachází nejočekávanější soubor, skript index.php, který chybové kódy zpracovává. Klíčová je superglobální proměnná $_SERVER['REDIRECT_STATUS'], která vrací HTTP stavový kód, podle kterého následně skript rozlišuje typ chyby.

Bohužel pro chybu 500 nevrátí proměnná z nepochopitelných důvodů nic. Skript používám i jako výchozí lokaci pro požadavky, které neodchytne žádný <VirtualHost>, např. když někdo zadá přímo IP adresu do prohlížeče. Zjištění chyby jsem tedy oprasil díky URL přes regulární výraz.

if (empty($code)) {
        preg_match('~(\d+)\.dragonjake\.net$~', $_SERVER['HTTP_HOST'], $m);
        $code = $m[1];
}

Úmyslně ve své implementaci nepoužívám žádný výpis URL adresy, která se běžně u podobných chybových hlášení objevuje. Zvědavcům napovím, že se jedná o proměnné $_SERVER['REQUEST_URI'] a $_SERVER['REDIRECT_URL']. Na závěr přikládám celý kód „chybového“ skriptu.

# determine status code, 500 does not work :(
if (empty($code)) {
        preg_match('~(\d+)\.dragonjake\.net$~', $_SERVER['HTTP_HOST'], $m);
        $code = $m[1];
}

# set text by status code
switch ($code) {
        case 400:
                $h = '400 Bad Request';
                $t = 'Err... what did you say?!';
                break;
        case 401:
                $h = '401 Authorization Required';
                $t = 'You haven\'t given me a gold!';
                break;
        case 403:
                $h = '403 Forbidden';
                $t = 'Step back before you get eaten!';
                break;
        case 404:
                $h = '404 File Not Found';
                $t = 'Are you looking for something?!';
                break;
        case 500:
                $h = '500 Internal Server Error';
                $t = 'Whops! Something got wrong!';
                break;
        default:
                $h = '';
                $t = 'Server is up and running.';
}

# send header
if (!empty($h))
        header($_SERVER['SERVER_PROTOCOL'] . ' ' . $h, TRUE, $code);
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xml:lang="cs" lang="cs" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta http-equiv="content-language" content="cs" />
<meta name="author" content="Dragon Jake; e-mail: admin@dragonjake.net" />
<meta name="copyright" content="© 2006 Dragon Jake" />
<meta name="robots" content="noindex,nofollow" />
<link rel="stylesheet" type="text/css" href="/401/main.css" />
<link rel="shortcut icon" type="image/x-icon" href="/401/favicon.ico" />
<title><?php if (!empty($h)) echo $h . ' | '; ?>Dragon's Server</title>
</head>
<body>
<div id="logo"></div>
<h1><?php echo htmlspecialchars($t); ?></h1>
<a href="http://www.dragonjake.net">www.dragonjake.net</a>
</body>
</html>

Štítky: