Virtual hosts massivi con Apache

10 Nov

Piccolo post a lunga distanza sui virtual host massivi, più che altro è un appunto di lavoro di cose fatte recentemente.

Quando si hanno mille mila virtual hosts da gestire su un server, o vogliamo avere un metodo semplice ed efficace di attivare virtuals, il metodo migliore e’ affidarsi al modulo di Apache vhost_alias che ci permette di realizzare in pochi passaggi un sistema per virtual hosts automatici.

Pima cosa abilitare sul vostro Apache il modulo vhost_alias (dipende dalla vostra distro e/o dal vostro modo abituale di configurare Apache)
Poi creiamo un file di configurazione per Apache

<VirtualHost *:80>
       ServerAdmin test@test.com

        UseCanonicalName Off
        VirtualDocumentRoot /var/www/%0/html
        VirtualScriptAlias /var/www/%0/cgi
        <Directory /var/www>
                Options Indexes FollowSymLinks MultiViews
                AllowOverride all
                Order allow,deny
                allow from all

</Directory>
ErrorLog /var/log/apache2/vhosts_error.log

# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn

CustomLog /var/log/apache2/vhosts_access.log combined
</VirtualHost>

Perfetto a questo punto ogni cartella che creeremo dentro /var/www verrà considerata uno spazio per un virtual host. Quindi se facciamo una cartella /var/www/www.test.com al cui interno vi sia una directory chiamata html, quest’ultima, sarà la document root del nostro virtual host.

A questo punto ci rimane solo un problema i logs…. come possiamo separare i logs per i vari virtual host?
Ci vengono in  soccorso i piped logs di Apache e il nostro linguaggio di scripting preferito (io ho usato PHP).

Innanzi tutto rimuoviamo nel nostro file di configurazione la linea

CustomLog /var/log/apache2/vhosts_access.log combined

Ed aggiungiamo

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" Vhost:%V" combined-vhost
CustomLog "|| /etc/apache2/pipedlogs.php " combined-vhost

quindi creiamo il nostro script di separazione pipedlogs.php…….

#!/usr/bin/php -q
<?php
ob_start();

function compressLogs($site){
        foreach (glob("/var/UtentiWeb/".$site."/logs/*.log") as $filename) {
                if(preg_match("/access.".date("Y-m-d").".log$/",$filename)>0)
                        continue;	
                exec("bzip2 ".$filename);
        }
        return true;
}


function write_log($file_log,$log){
        if($file_log)
                $handle = fopen($file_log,"a");
        else
                $handle = fopen("/var/log/apache2/virtuals.access.log","a");
        fputs($handle, $log);
        fclose($handle);
}

if ( isset($_SERVER["argc"]) && $_SERVER["argc"]>1 ) {
  die(var_dump($argv));
  if($argv[1]=="--compress"){
        compressLogs($argv[2]);
        exit(0);
  }
}
set_time_limit (0);
$stdin=  fopen("php://stdin", "r");
while($logline = fgets($stdin)){

        $sitename=trim(preg_replace("/^(.*?)Vhost:(.*)$/","$2",$logline));
        $logline=str_replace(" Vhost:$sitename","",$logline);
        $file_log="/var/www/$sitename/logs/access.".date("Y-m-d").".log";
        if(is_dir("/var/www/$sitename/logs")){
                if(!file_exists($file_log)){
                        write_log($file_log,$logline);
                        exec($_SERVER["SCRIPT_FILENAME"]." --compress ".$sitename." > /dev/null 2>&1 & ");
                }
                else
                        write_log($file_log,$logline);
        }
        else
                write_log(false,$logline);
}
fclose($stdin);
ob_end_clean();
exit(0);
?>

A questo punto nella cartella /var/www/nomedelsito/logs avrete i vostri logs che oltretutto saranno ruotati e compressi automaticamente ogni giorno.

Francesco Giovannini

Pensieri informaltici