Nginx
nginx 記錄 php-fpm 的 stderr 輸出在看似隨機的位置被截斷
自從我開始使用產生長呼叫鏈的 PHP 庫以來,調試由它引起的問題就變得越來越困難,因為我的錯誤日誌最終包含如下輸出:(某些值已使用 被清除
*
)2017/08/23 10:47:26 [error] 13057#13057: *206119 FastCGI sent in stderr: "PHP message: PHP Fatal error: Uncaught ActiveRecord\DatabaseException: PDOException: SQLSTATE[22P02]: Invalid text representation: 7 ERROR: invalid input syntax for integer: "" in /var/www/********/vendor/php-activerecord/php-activerecord/lib/Connection.php:337 Stack trace: #0 /var/www/********/vendor/php-activerecord/php-activerecord/lib/Connection.php(337): PDOStatement->execute(Array) #1 /var/www/********/vendor/php-activerecord/php-activerecord/lib/Table.php(237): ActiveRecord\Connection->query('SELECT * FROM "...', Array) #2 /var/www/********/vendor/php-activerecord/php-activerecord/lib/Table.php(219): ActiveRecord\Table->find_by_sql('SELECT * FROM "...', Array, false, NULL) #3 /var/www/********/vendor/php-activerecord/php-activerecord/lib/Model.php(1666): ActiveRecord\Table->find(Array) #4 /var/www/********/vendor/php-activerecord/php-activerecord/lib/Model.php(1605): ActiveRecord\Model::find_by_pk('', Array) #5 /var/www/********/includes/classes/Models/NSModel.php(11): ActiveRecord\Model::find(''" while reading response header from upstream, client: **.***.***.***, server: ***********, request: "POST /************************************ HTTP/1.1", upstream: "fastcgi://unix:/run/php/php7.1-fpm.sock:", host: "***********", referrer: "************************************************************"
注意在最後一行 FastCGI stderr 輸出是如何在
ActiveRecord\Model::find(''"
. 另一個例子:2017/08/22 17:20:53 [error] 13057#13057: *193907 FastCGI sent in stderr: "PHP message: PHP Fatal error: Uncaught TypeError: Argument 1 passed to App\DeviantArt::isImageAvailable() must be of the type string, null given, called in /var/www/********/includes/classes/ImageProvider.php on line 138 and defined in /var/www/********/includes/classes/DeviantArt.php:357 Stack trace: #0 /var/www/********/includes/classes/ImageProvider.php(138): App\DeviantArt::isImageAvailable(NULL) #1 /var/www/********/includes/classes/ImageProvider.php(21): App\ImageProvider->setUrls('*******') #2 /var/www/********/includes/classes/Posts.php(207): App\ImageProvider->__construct('******************', Array) #3 /var/www/********/includes/classes/Controllers/PostController.php(334): App\Posts::checkRequestFinishingImage('***************...') #4 /var/www/********/includes/classes/RouteHelper.php(11): App\Controllers\PostController->action(Array) #5 /var/www/********/includes/do.php(27): App\RouteHelper::App\{closure}(Array) #6 /var/www/********/www/index.php(1): require('/var/www/******...') #7 {main} t" while reading response header from upstream, client: **.***.***.***, server: ***********, request: "POST /*************************** HTTP/1.1", upstream: "fastcgi://unix:/run/php/php7.1-fpm.sock:", host: "***********"
這裡 stderr 輸出在 之後被切斷
t
,留下了足夠的資訊來找到問題,但它仍然不是完整的消息。我在輸出的長度和它被切斷的時間之間找不到任何模式。我在 Debian Stretch 上使用 nginx 版本 1.10.3 和 PHP 版本 7.1.8。我還嘗試在其中設置以下值
nginx.conf
(因為我過去曾查找過此問題的解決方案),但上面的範例是在這些設置已經生效的情況下生成的。fastcgi_buffers 256 4k; client_max_body_size 20M;
根據在類似問題下找到的答案,即使我以某種方式繞過 php-fpm 的字元限制,nginx 也會截斷輸出,可能導致資訊失去。
為了完全消除這種風險,我選擇使用Monolog來處理應用程序級別的日誌記錄,它可以與文件輸出一起使用,以寫入任意長的錯誤消息和堆棧跟踪。這個問題可能對任何想要做同樣事情的人有所幫助。