如何通过nginx、php-fpm、php的日志调试程序

最近写了几篇关于504和502的文章,涉及了很多nginx、php-fpm、php方面的细微知识,这些理论虽然简单,但对于理解php和http非常重要。熟悉的同学知道,在工作上我主要使用php开发,而开发过程中,调试是非常关键的一个步骤,出现一个问题,快速定位到问题非常关键,所以今天简单区分下nginx、php-fpm、php三者之间的访问日志(access.log)错误日志(error.log),理解它们,后续开发的时候会更加顺利。

通过下图,我们能够了解到这三者之间可能有四种错误日志,如果不理解这张图的结构,可以看下我以前写的文章。

在这四个层面(nginx、php-fpm主进程、php-fpm pool工作进程、php)都有与日志有关的指令,接下去分别描述。

php.ini

每一个php解析器都有一个php.ini,该文件定义了很多php的默认行为,从日志的角度看,有三个指令很重要。

当display_errors=off的时候,php解析的时候如果出现错误(语法错误、异常等),则不会在页面或命令行中不会打印错误,在生产环境中,一般将该指令设置为off,否则出现错误的时候,访问者体验很不好,更严重的时候,泄漏了很多隐私数据,比如打印出数据库的用户名和密码。

display_errors关闭的时候,我们怎么知晓php产生了那些错误呢?此时可以借助error_log,该指令指定了一个文件,如果发生错误的时候,就会将错误输出到这个文件中。

error_reporting则指定了输出那些类型的错误,E_ALL表示输出所有错误,而E_ALL & ~E_DEPRECATED表示除了E_DEPRECATED级别的错误不输出,其他错误全部输出,关于这个指令,也够我们学一阵子的,但这不是本文的重点。

需要指出的是,如果display_errors=on,一旦产生php错误或异常,nginx(包括其他web服务器)会返回200 http状态码,并且在页面中输出错误;但如果display_errors=off的时候,产生php错误或异常的时候,nginx会直接返回500 http错误码。

nginx

对于nginx来说,可以通过以下指令控制访问日志和错误日志,非常的简单:

对于一个web服务器来说,nginx通过fastcgi连接后端php-fpm的时候,如果产生fastcgi协议级别的错误(比如以前文章中谈到的504、502),会记录在error.log中,比如:

当nginx在内部处理的时候,遇到一些错误(比如ssl异常),也会记录在error.log中,比如:

当nginx访问一个后端不存在的程序时,也会记录在error.log中,比如:

读者可能会想,php输出的错误能够记录到nginx日志中吗,答案是可以的,具体等会说。

php-fpm pool 日志

聪明的php-fpm想到了一个办法,具体的指导策略还是隔离,既然php pool可以分为多个,那么每个pool可以继承和覆盖php.ini的指令,是否可行?

可以的,某些php.ini指令可以覆盖,但某些指令不可以(全局的),对于本文要描述的php三个指令,都可以覆盖重载。

比如 fpm/pool.d/www.test.com.conf 文件定义如下:

而 fpm/pool.d/www.test.cn.conf 文件定义如下:

好处是什么?这样我们能够清晰的区分不同应用的错误,更重要的观点就是pool继承了php.ini,每个pool的php配置(php.ini)是独一无二的。

接下去的是重点,php-fpm pool 还多了一些php.ini没有的指令,nginx和php-fpm 工作进程(pool)之间通过fastgcgi协议交互,php-fpm为了增加灵活度,增加了一些指令,本文讲解的就是 catch_workers_output,查看该指令的定义:

; Redirect worker stdout and stderr into main error log. If not set, stdout and

; stderr will be redirected to /dev/null according to FastCGI specs.

; Note: on highloaded environement, this can cause some delay in the page

很简单,该指令默认是关闭的,一旦关闭,php的错误输出会定向到 /dev/null,如果想通过fastcgi协议告知nginx,那么可以打开该指令,这样nginx的access.log就能捕获到php的输出(比如php错误或异常)。重要的是,该指令一旦打开,会影响性能。

打开该指令后,如果遇到php错误,nginx的error.log就会记录,比如:

需要注意点是 nginx(user 指令)和php-fpm pool(user指令)的属主文件权限要一致,否则不会产生日志。

另外php-fpm pool还可以记录access日志(access.log)和慢日志(slowlog),比较简单就不阐述了。

php-fpm 日志

刚才说的php-fpm都说的是worker进程,即pool工作进程,php-fpm主进程(root)也可以配置error.log(在php-fpm.conf文件中配置),就像在

《什么是SAPI,FastCGI,PHP-FPM?学习PHP的必备知识》

文章说的一样,我从没发现该日志有内容,即使pool配置文件配置错误,也没有发现日志有内容,所以暂时可以忽略了,也就是说本文讨论了nginx、php-fpm工作进程、php解析器的日志情况。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181003G0RNVY00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券