error_log這個指令在nginx的配置文件nginx.conf、php-fpm的配置文件php-fpm.conf以及php.ini三者中都存在,本文試圖簡要說明下這三個配置之間的區別和聯繫。
php.ini
error_log
string設置腳本錯誤將被記錄到的文件。該文件必須是web服務器用戶可寫的。如果特殊值 syslog 被設置,則將錯誤信息發送到系統日誌記錄器。在Unix以及類似系統上,使用的是 syslog(3) ,而在 Windows NT 類系統上則爲事件日誌。Windows 95上不支持系統日誌記錄。參見: syslog(). 如果該配置沒有設置,則錯誤信息會被髮送到 SAPI 錯誤記錄器。例如,出現在Apache的錯誤日誌中,或者在CLI中發送到 stderr。
php-fpm.conf
error_log
string錯誤日誌的位置。默認:#INSTALL_PREFIX#/log/php-fpm.log。 如果設置爲 "syslog",日誌將不會寫入本地文件,而是發送到 syslogd。
nginx.conf
Syntax: error_log
file
[level
];Default: error_log logs/error.log error;
Context: main
,http
,stream
,server
,location
Configures logging. Several logs can be specified on the same level (1.5.2). If on the
main
configuration level writing a log to a file is not explicitly defined, the default file will be used.The first parameter defines a
file
that will store the log. The special valuestderr
selects the standard error file. Logging to syslog can be configured by specifying the “syslog:
” prefix. Logging to a cyclic memory buffer can be configured by specifying the “memory:
” prefix and buffersize
, and is generally used for debugging (1.7.11).The second parameter determines the
level
of logging, and can be one of the following:debug
,info
,notice
,warn
,error
,crit
,alert
, oremerg
. Log levels above are listed in the order of increasing severity. Setting a certain log level will cause all messages of the specified and more severe log levels to be logged. For example, the default levelerror
will causeerror
,crit
,alert
, andemerg
messages to be logged. If this parameter is omitted thenerror
is used.
從上面的文檔初步可以看出 php.ini 中 error_log 優先級較高,下面依次實驗這些配置的組合,讓我們來看看它們的優先級,
測試報錯使用以下簡單的php代碼:
<?php
throw new Exception('foobar');
其中各個error_log的配置值如下:
nginx:error_log /var/log/nginx/error.log;
php-fpm:error_log = /var/log/php-fpm/error.log
php.ini:error_log = /var/log/php/error.log
1、當三個值同時配置時,php的錯誤日誌會寫入php.ini中error_log指定的文件
[21-Apr-2019 22:19:13 Asia/Shanghai] PHP Fatal error: Uncaught Exception: foobar in /usr/share/nginx/html/error.php:5
Stack trace:
#0 {main}
thrown in /usr/share/nginx/html/error.php on line 5
但如果這個error_log指定的文件沒有可寫權限時會怎樣呢,會不會記錄到nginx或者php-fpm的error_log文件中呢?答案是否定的,此時報錯信息會因爲無法寫入而丟失。
2、不配置php.ini 中的error_log,同時配置 nginx.conf 和php-fpm.conf 中的error_log,此時錯誤日誌會寫入到nginx的error_log文件中
2019/04/21 22:33:04 [error] 2031#0: *102 FastCGI sent in stderr: "PHP message: PHP Fatal error: Uncaught Exception: foobar in /usr/share/nginx/html/error.php:5
Stack trace:
#0 {main}
thrown in /usr/share/nginx/html/error.php on line 5" while reading response header from upstream, client: 127.0.0.1, server: _, request: "GET /error.php HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "127.0.0.1"
3、由於nginx的error_log不支持關閉,所以無法比較 nginx.conf 和 php-fpm.conf 中 error_log 的優先級,實際上 php-fpm.conf 中的error_log並不用來記錄php的報錯信息,而用來記錄php-fpm進程本身的一些運行時信息。
4、雖然php-fpm.conf 中的error_log 不會記錄php的報錯信息,但是在php-fpm.conf 中可以用 php_value/php_flag 或 php_admin_value/php_admin_flag 配置來覆蓋php.ini中的配置:
還可以在爲一個運行池傳遞附加的環境變量,或者更新 PHP 的配置值。可以在進程池配置文件中如下面的配置參數來做到:
Example #1 給運行池傳遞環境變量和設置 PHP 的配置值
PHP配置值通過 php_value 或者 php_flag 設置,並且會覆蓋以前的值。請注意 disable_functions 或者disable_classes 在 php.ini 之中定義的值不會被覆蓋掉,但是會將新的設置附加在原有值的後面。env[HOSTNAME] = $HOSTNAME env[PATH] = /usr/local/bin:/usr/bin:/bin env[TMP] = /tmp env[TMPDIR] = /tmp env[TEMP] = /tmp php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f [email protected] php_flag[display_errors] = off php_admin_value[error_log] = /var/log/fpm-php.www.log php_admin_flag[log_errors] = on php_admin_value[memory_limit] = 32M
使用 php_admin_value 或者 php_admin_flag 定義的值,不能被 PHP 代碼中的 ini_set() 覆蓋。
例如,在php-fpm.conf 中配置 php_admin_value[error_log] = /var/log/php-fpm/www-error.log , 同時配置php.ini 中的error_log,會發現php報錯信息會寫入 /var/log/php-fpm/www-error.log文件中
總結:
error_log優先級:php-fpm.conf 中的 php_value[error_log] / php_admin_value[error_log]
大於 php.ini 中的 error_log
大於 nginx.conf 中的 error_log
而 php-fpm.conf 中的error_log 跟記錄php運行時報錯信息無關。
而最簡單的獲取php的錯誤日誌記錄的地方就是查看phpinfo() 信息,看其中的error_log 的值,如果有值,則錯誤日誌就是記錄在這個值指定的地方,沒有則記錄在nginx的error_log中。
有的框架使用set_exception_handler 和 set_error_handler 以及 register_shutdown_function重新設置了異常處理和報錯處理,可能把錯誤日誌寫到另外一個地方,所以在開發環境下還是臨時打開 display_errors 吧,這是最快速的定位錯誤的方法。
That's all