1

TL;DR

Piping Apache error logs to a custom script doesn't work as expected. Apache sends core meassages to the script. But logs from PHP or authz_core_module still end up in Apache's default logging file.

What I want

I'm using Apache and PHP (via PHP Apache module) for a web space. Currently all error messages of Apache and PHP are logged in /var/log/apache2/error.log. This is the default logging location for Apache under Debian. Also PHP's error_log directive is not set. So PHP is supposed to send its logs to the Apache Logger. This all works so far.

Now there's a functionality of Apache that I'd like to utilize. Piped Logs can be used to pipe access or error logs to a custom script. This custom script can now anonymize IP addresses, display errors in debugging programs, filter messages, write filtered messages to the original log, etc.

What I tried

To implement this I appended the following to my apache2.conf:

ErrorLog "|$php /path/to/script/log.php"
CustomLog "|$php /path/to/script/log.php" common

Custom Log isn't strictly necessary. But for testing purposes I wanted to make sure everything was captured. The content of log.php is as follows:

ob_implicit_flush(true);
while($f = fgets(STDIN))
{
    file_put_contents("/path/to/script/log.txt", $f, FILE_APPEND);
}

What happened

Now some strange thing happened. The access logs were written to log.txt (as expected) and Appache's core errors like¹:

  • [...] [so:warn] [pid 23307] AH01574: module ssl_module is already loaded, skipping
  • [...] [mpm_prefork:notice] [pid 23307] AH00163: Apache/2.4.25 (Debian) OpenSSL/1.0.2l configured -- resuming normal operations

were written to log.txt (as expected). However log messages from most modules are still written to /var/log/apache2/error.log, including¹:

  • [...] [authz_core:error] [pid 40549] [...] AH01630: client denied by server configuration: /var/www/html/webpage/secret
  • [...] [:error] [pid 58611] [...] PHP Parse error: syntax error, unexpected 'foo' (T_STRING) in /var/www/html/webpage/index.php on line 3
  • everything logged by PHP's error_log() function

Is it possible to include these messages in the pipe as well? If so how? And why does Apache only pipe some core messages through my script and not those from the modules?

I know that I could just read the logs with the script. But that makes it harder to filter, anonymize² and/or use them for a live debugging console. I'm just wondering if piped logs (or something similar that is built-in in Apache or PHP) is at all usable for this purpose.

¹ IP addresses and timestamps shortened to [...]

² As far as I know in some countries even saving IP addresses temporarily might not be legal. So piping and anonymizing or entirely leaving out addresses from the log format are the only options.

Some version information (just in case...)

Apache

# apachectl -v
Server version: Apache/2.4.25 (Debian)
Server built:   2017-10-24T14:45:24

PHP

# php -v
PHP 7.0.33-0+deb9u7 (cli) (built: Feb 16 2020 15:11:40) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies
    with Zend OPcache v7.0.33-0+deb9u7, Copyright (c) 1999-2017, by Zend Technologies

Linux/Debian

# uname -a
Linux <servername> 4.9.0-8-amd64 #1 SMP Debian 4.9.144-3 (2019-02-02) x86_64 GNU/Linux

# lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description:    Debian GNU/Linux 9.12 (stretch)
Release:    9.12
Codename:   stretch

1 Answer 1

1

Well it turns out that the mistake was entirely on my side. I somehow was incapable of reading my config files correctly.

There are two config files in /etc/apache2/sites-enabled/. One of them was automatically created by certbot (I think) and heavily edited by me. It contains Virtual Hosts that manage SSL certificates for *:443. I knew that and searched them for anything related to my problem before posting here. But it seems that I was blind when I did that. When I had a look on it half an hour ago for unrelated reasons I saw this inside several Virtual Hosts:

ErrorLog ${APACHE_LOG_DIR}/error.log
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/access.log combined

:facepalm:

Yep. ErrorLog and CustomLog were overridden there. Commenting them out fixed my issue. Now all messages are getting piped through my script.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .