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

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

概述最近写了几篇关于504和502的文章,涉及了很多nginx、php-fpm、php方面的细微知识,这些理论虽然简单,但对于理解php和http非常重要。熟悉的同学知道,在工作上我主要使用php开发,而开发过程中,调试是非常关键的一个步骤,出现一个问题,快速定位到问题非常关键,所以今天简单区分下nginx、php-fpm

最近写了几篇关于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的默认行为,从日志的角度看,有三个指令很重要。

error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICTdisplay_errors=offerror_log=/var/log/PHPerror.log

当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来说,可以通过以下指令控制访问日志和错误日志,非常的简单:

access_log  logs/access.log  main;error_log  logs/error.log;

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

2018/09/19 21:01:19 [error] 17034#0: *253 upstream timed out (110: Connection timed out) while reading response header from upstream, clIEnt: *.*.*.*, server: www.simplehttps.com, request: "GET /x.PHP http/1.1", upstream: "http://*.*.*.*:80/x.PHP", host: "www.simplehttps.com"

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

2018/10/02 10:50:00 [crit] 29363#0: *122 SSL_do_handshake() Failed (SSL: error:14209102:SSL routines:tls_early_post_process_clIEnt_hello:unsupported protocol) while SSL handshaking, clIEnt: 182.132.25.13, server: 0.0.0.0:443

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

2018/04/18 21:36:31 [error] 31891#0: *55 open() "/usr/local/index.PHP" Failed (2: No such file or dir ectory), clIEnt: 116.62.209.27, server: localhost, request: "GET /index.PHP http/1.1", host: "",

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

PHP-fpm pool 日志

在《什么是SAPI,FastCGI,PHP-FPM?学习PHP的必备知识》这篇文章提到PHP-fpm pool是个非常巧妙的方式,类似于web服务器的虚拟主机,多个PHP进程池之间相互隔离,但是PHP.ini只能有一个,如果某个应用(www.test.com)想打开PHP错误日志(即display_errors指令),而另外个应用(www.test.cn)却想关闭PHP错误日志,怎么办?或者如何在不同的应用之间定义不同的错误日志路径(即error_log),怎么办?

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

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

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

error_log=/var/log/test.com-error.log

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

error_log=/var/log/test.cn-error.log

好处是什么?这样我们能够清晰的区分不同应用的错误,更重要的观点就是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就会记录,比如:

2018/10/03 13:01:55 [error] 908#0: *4 FastCGI sent in stderr: "PHP message: PHP Parse error:  Syntax error, unexpected end of file, expecting variable (T_VARIABLE) or ${ (T_DolLAR_OPEN_CURLY_BRACES) or {$ (T_CURLY_OPEN) in /usr/share/Nginx/HTML/index.PHP on line 7" while reading response header from upstream, clIEnt: 118.207.51.2, server: weiboAPI.newyingyong.cn, request: "GET /index.PHP?ssss http/1.1", upstream: "fastcgi://unix:/run/PHP/PHP7.1-fpm.sock:", host: ""

需要注意点是 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解析器的日志情况。

总结

以上是内存溢出为你收集整理的如何通过nginx、php-fpm、php的日志调试程序全部内容,希望文章能够帮你解决如何通过nginx、php-fpm、php的日志调试程序所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/1166974.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-01
下一篇 2022-06-01

发表评论

登录后才能评论

评论列表(0条)

保存