6

Whenever we create new Virtual Hosts on our dev servers, we always have to manually specify separate access and error logs:

ErrorLog logs/mysite/dev1-error.log
CustomLog logs/mysite/dev1-access.log "common"

Is there anyway to make Apache automatically split up the logs instead of having to specify them every time?

Jake Wilson
  • 8,814
  • 29
  • 97
  • 125

4 Answers4

3

I feel your pain, as a web developer I have probably over 200 vhosts in my local dev - I personally don't care about the logs & log them all to the main /var/log/apache...

However what I did do was to write a shell script to add/manage all my vhosts - all you need to do is to tweak it to write logs to wherever you like...

#!/bin/bash
ARGS=1
if [ "$1"X = "X" ];
        then
        echo "Must enter domain name"
        exit 0
fi
if [ "$2"X = "X" ];
        then
        echo "Must enter domain suffix"
        exit 0
fi
if [ "$3"X = "X" ];
        then
        echo "you must type "restart" if you want apache restarted "no" if not!"
        exit 0
fi

domain=$1.$2;

#echo $domain;
#exit 0


rm $domain.conf

echo "<VirtualHost *:80>" >> $domain.conf;
echo "        ServerAdmin no-reply@network.local" >> $domain.conf;
echo "        ServerName $1.network.local" >> $domain.conf;
echo "        DocumentRoot /Data/vhome/$1.$2/httpdocs" >> $domain.conf;
echo "        HostnameLookups Off" >> $domain.conf;
echo "        UseCanonicalName Off" >> $domain.conf;
echo "        ServerSignature On" >> $domain.conf;
echo "        ScriptAlias /cgi-bin/ "/Data/vhome/$1.$2/cgi-bin/"" >> $domain.conf;
echo "        ErrorLog /var/log/apache2/error_log" >> $domain.conf;
echo "        CustomLog /var/log/apache2/access_log combined" >> $domain.conf;
echo "    <Directory "/Data/vhome/$1.$2/cgi-bin">" >> $domain.conf;
echo "        AllowOverride All" >> $domain.conf;
echo "        Options +ExecCGI -Includes" >> $domain.conf;
echo "        Order allow,deny" >> $domain.conf;
echo "        Allow from all" >> $domain.conf;
echo "    </Directory>" >> $domain.conf;
echo "    <Directory "/Data/vhome/$1.$2/httpdocs">" >> $domain.conf;
echo "        Options Indexes FollowSymLinks" >> $domain.conf;
echo "        AllowOverride All" >> $domain.conf;
echo "        Order allow,deny" >> $domain.conf;
echo "        Allow from all" >> $domain.conf;
echo "    </Directory>" >> $domain.conf;
echo "       # #XSS prevention" >> $domain.conf;
echo "       # RewriteEngine On" >> $domain.conf;
echo "       # RewriteCond %(REQUEST_METHOD) ^TRACE" >> $domain.conf;
echo "       # RewriteRule .* -[F]" >> $domain.conf;
echo "</VirtualHost>" >> $domain.conf;

if [ "$3" = "restart" ];
        then
        rcapache2 restart;
fi

chmod 666 $domain.conf

cat $domain.conf
echo "Created!";

exit 0

Hope it helps.

-sean

Sean Kimball
  • 869
  • 1
  • 8
  • 24
  • Looks nice, I will try it out. I assume you have to run this script in `/etc/httpd/conf.d/` ? – Jake Wilson Aug 05 '11 at 17:06
  • no I have it in my /etc/apache/vhosts/ - if you move it, just change your paths, or possibly add a path parameter pointing to the apache includes directory... If you wanted to get it real sexy, you could also have it create the virtual host directory structure & jack a cname into your nameserver configs.... – Sean Kimball Aug 05 '11 at 17:28
  • 2
    You could clean that up using a big here document. Variable expansions are still processed inside. – MikeyB Aug 05 '11 at 18:39
  • +1 for MikeyB, those hundred echos hurt my eyes :-P – hmontoliu Aug 05 '11 at 19:32
2

Back when I still used apache, I learned a trick from a coworker. He piped the global access log through an awk script. The awk script in turn would then take care creating the different logfiles.

In httpd.conf:

LogFormat "%V %p %a %l %u %t \"%r\" %s %b \"%200{Referer}i\" \"%200{User-agent}i\" \"%{cookie}n\"" awklogpipe
CustomLog "|/usr/local/bin/apacheawklogpipe" awklogpipe env=!dontlog

The script /usr/local/bin/apacheawklogpipe:

#!/bin/gawk -f

BEGIN {
        months["Jan"] = "01";
        months["Feb"] = "02";
        months["Mar"] = "03";
        months["Apr"] = "04";
        months["May"] = "05";
        months["Jun"] = "06";
        months["Jul"] = "07";
        months["Aug"] = "08";
        months["Sep"] = "09";
        months["Oct"] = "10";
        months["Nov"] = "11";
        months["Dec"] = "12";
}

{
        # HEADS UP: SET THIS!!!!
        LOGBASE="/var/log/httpd/access"

        SSL=""

        # Automagicly set first 
        SITE=tolower($1);
        PORT=$2

        if ($2 == 443)
        {
                SSL="-ssl"
        }

        # Extract all but first two fields (vhostname vhostport to be exactly) into LINE
        LINE=substr($0,index($0,$3));

        # No matter where it is, we will find an apache datestamp.
        match(LINE,/\[[0-9]+\/[A-Z][a-z]+\/[0-9]+:[0-9]+:[0-9]+:[0-9]+[\t ]+[+-][0-9]+\]/);
        split(substr(LINE,RSTART + 1,RLENGTH - 2), ap_log_time, /[\/: ]/);

        #ap_rotatelog= LOGBASE "/" SITE ":" PORT "/access-log" SSL "-" ap_log_time[3] "-" months[ap_log_time[2]] ap_log_time[1];
        ap_rotatelog= LOGBASE "/" SITE  "/access_log" SSL;
        if (system("test -d " LOGBASE "/" SITE ) == 0)
        {
                print LINE >> ap_rotatelog;
                close(ap_rotatelog);
        }
        else
        {
                print SITE "\t" SSL "\t" LINE >> LOGBASE "/w3logrotate-error.log";
                close(LOGBASE "/w3logrotate-error.log");
        }
}

Make sure /usr/local/bin/apacheawklogpipe is executable. All you would need to take care of with this script, is create a directory in /var/log/httpd/access that corresponds to the virtualhostname. I had a script that would create a virtualhost config and create the log directories.

Sgaduuw
  • 1,833
  • 12
  • 16
  • You also can use [split-logfile](http://httpd.apache.org/docs/2.0/programs/other.html) (it can be found in `support` folder when compiling from source) or [vlogger](http://n0rp.chemlab.org/vlogger/) to do this. – quanta Aug 05 '11 at 17:14
  • very nice solution.... – Sean Kimball Aug 05 '11 at 17:25
2

Another options. Don't split them in httpd.conf. Instead, log everything to your main Access Log, and then split them later with a program like split-logfile. This helps to simplify your log configuration.

This is described at http://httpd.apache.org/docs/2.2/logs.html#virtualhost

By adding information on the virtual host to the log format string, it is possible to log all hosts to the same log, and later split the log into individual files. For example, consider the following directives.

LogFormat "%v %l %u %t \"%r\" %>s %b" comonvhost CustomLog
logs/access_log comonvhost

The %v is used to log the name of the virtual host that is serving the request. Then a program like split-logfile can be used to post-process the access log in order to split it into one file per virtual host.

Stefan Lasiewski
  • 23,667
  • 41
  • 132
  • 186
  • That sounds like a nightmare. If I have 30 active sites and I want to look through the log for a single site I have to either sift through a HUGE log file or split it out everytime? Not to mention running a `tail -f` would suck horribly... No thanks. – Jake Wilson Aug 05 '11 at 19:36
  • 1
    To each his own. I wouldn't want 2x30 logfiles sitting around, and this works well with [Simple dynamic virtual hosts](http://httpd.apache.org/docs/current/vhosts/mass.html#simple). The idea here is to handle log processing afterwards. `tail -f access_log | grep www.example.org` works well enough. So does a a central syslog/Splunk server. – Stefan Lasiewski Aug 05 '11 at 20:45
0

Maybe have a look at mod_macro. This has a more general approach, but I guess that this could help you otherwise as well.

Sven
  • 98,649
  • 14
  • 180
  • 226