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