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:
- PHP's syslog destination: Configured but potentially not captured
- PHP-FPM's error log: Only captures FPM process errors
- 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