Debugging PHP-FPM Error Logging in Nginx: Where Do E_NOTICE and E_WARNING Messages Go?


3 views

When running PHP applications with Nginx and PHP-FPM, error logging can become surprisingly complex due to multiple configuration layers. The core issue stems from having three separate systems that each handle logging differently:

1. Nginx (web server)
2. PHP-FPM (process manager) 
3. PHP runtime itself

Based on your setup, here are the key areas to verify:

# In php.ini:
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT  # For production
log_errors = On
error_log = /var/log/php/error.log  # Explicit path recommended

# In php-fpm pool config:
catch_workers_output = yes
php_admin_value[error_log] = /var/log/php-fpm/php-error.log
php_admin_flag[log_errors] = on

Your current configuration uses syslog, which creates several challenges:

  • PHP-FPM doesn't natively support syslog logging
  • Messages get tagged differently than expected
  • System log rotation may affect visibility

Instead of syslog, consider this more reliable approach:

# Remove from php.ini:
; error_log = syslog

# Add to php-fpm pool config:
access.log = /var/log/php-fpm/$pool.access.log
slowlog = /var/log/php-fpm/$pool.slow.log
request_slowlog_timeout = 10s
php_admin_value[error_log] = /var/log/php-fpm/$pool.error.log

Here's how to test if your logging is working properly:

<?php
// test.php
error_reporting(E_ALL);
ini_set('display_errors', 0);
ini_set('log_errors', 1);

// Generate different error types
$undefined->test(); // E_ERROR
$undefined_var;     // E_NOTICE
strpos();           // E_WARNING

After running this script through Nginx, check all potential log locations:

# Check PHP-FPM error log
tail -f /var/log/php-fpm/error.log

# Check PHP error log
tail -f /var/log/php/error.log  

# Check Nginx error log
tail -f /var/log/nginx/error.log

The most common reason for missing logs is permission issues. Ensure:

# Set correct ownership
chown -R www-data:www-data /var/log/php*

# Verify permissions
find /var/log/php* -type f -exec ls -la {} \;

# Test writability
sudo -u www-data touch /var/log/php-fpm/test.log

For better debugging, implement JSON-formatted logs:

php_admin_value[error_log_format] = "{\"time\":\"%t\", \"level\":\"%s\", \"message\":\"%m\", \"file\":\"%f\", \"line\":\"%l\"}"

This produces logs that are easier to parse and analyze with tools like ELK or Graylog.


When running PHP applications through Nginx + PHP-FPM, error messages can sometimes vanish into the void. Here's what's happening in this specific configuration:

// Current PHP error reporting settings
error_reporting  =  E_ALL
display_errors = Off
log_errors = On
error_log = syslog

Your setup has three potential logging channels that need examination:

  1. PHP's syslog destination: Configured but potentially not captured
  2. PHP-FPM's error log: Only captures FPM process errors
  3. Nginx error logs: Only shows HTTP-level errors

Here's a working configuration that ensures all PHP errors are properly logged:

// php.ini adjustments
log_errors = On
error_log = /var/log/php_errors.log  // Direct file logging is more reliable

// php-fpm.conf additions
catch_workers_output = yes
php_admin_value[error_log] = /var/log/php-fpm/php_errors.log
php_admin_flag[log_errors] = on

Create a test script to verify error logging:

<?php
// test_error.php
trigger_error("This is a test warning", E_WARNING);
// Should appear in your logs
?>

Check all potential log locations after accessing this script:

# System logs
grep -r "test warning" /var/log/

# Specific log files
tail -n 50 /var/log/php_errors.log
tail -n 50 /var/log/php-fpm/error.log
journalctl -xe | grep php

For better analysis, consider JSON-formatted errors:

// In your PHP application bootstrap
ini_set('error_log', '/var/log/php_errors.json');
register_shutdown_function(function() {
    $error = error_get_last();
    if ($error) {
        file_put_contents(
            ini_get('error_log'),
            json_encode($error) . "\n",
            FILE_APPEND
        );
    }
});
  • Permission issues on log files (www-data/user mismatch)
  • Multiple error_log directives conflicting
  • PHP-FPM pools overriding global settings
  • Log rotation scripts not restarting services