PHP调试总卡壳?16年日志老炮3步揪出90%隐藏Bug
|
去年六月份,凌晨四点,机房空调啸叫得像只快断气的猫——我蹲在IDC三号架下面,手抖着往PHP-FPM配置里塞log_level=4,就为看一眼那该死的“failed to write session data”到底卡在哪一层。对面老张正啃冷掉的肉夹馍,腮帮子一鼓一鼓,手机突然震,他扫了眼短信抬头说:“告警又来了,还是session write fail。”我没接话,只把笔记本合上,听见监控大屏左下角那个红框又开始频闪,三秒亮一次,跟心电图似的。 PHP调试卡壳?呵。我干这行十六年,前十年写采集脚本、后六年调日志管道,见得最多的就是PHP同学捧着Xdebug跑断腿,结果Bug早写在error_log最后一行没被刷出来——不是不报,是压根没人开。你们还信xdebug_step_into?我原以为它能救命,结果上次跟小王联调,他开了xdebug,本地一切正常,一上生产,所有断点全飘在空气里,最后发现是opcache把debug符号全优化掉了。他当场把键盘拍得嗡嗡响,而我盯着屏幕右下角浏览器开着三十七个标签页:四个phpinfo、两个tail -f /var/log/php/error.log、一个curl测试页、还有二十六个各项目后台…对,我数过,二十六个。 第一步,别碰代码。先翻error_log——不是你写的那一行,是你配的那一行。ini里log_errors=On开了没?syslog.facility设成local0了没?有没有人偷偷把error_log路径指向/dev/null还写了注释“防止磁盘写满”?这种操作我见了至少七回。最绝的是上个月,一个站长改完php.ini重启fpm,结果日志全吐到/var/log/messages里混进内核消息,他追着dmesg查三天,最后发现只是error_log没指定绝对路径,php默认往当前工作目录写——而那个workdir是/tmp,系统每小时清一遍。我敢打包票:你机器上现在至少有两个php-fpm进程,一个在用旧配置,一个在用新配置。不信?ps aux|grep fpm,再看看启动时间戳。 第二步,别信$_SERVER['HTTP_REFERER']。信tcpdump。上月那个“用户登录总失败”的case,前端传参明明白白,后端却说密码为空。我们仨蹲在跳板机上,老李用strace挂php-cgi,小刘在nginx access log里搜POST /login,我在另一台机器上tcpdump -i eth0 port 80 -A | grep -E "(password|passwd)"。抓了十二分钟,发现所有POST体都被截断在1023字节——原来是客户那边代理服务器开了body_size_limit 1k。而他们PHP里写的if (empty($_POST['pwd'])),根本没机会执行,因为$_POST压根就是空数组。这个我说不准是nginx转发时丢包还是代理截断,但我知道tcpdump第一眼就打脸了全部PHP堆栈分析。
文章配图,仅供参考 第三步,关掉所有缓存。不是opcache,是你的脑子。我桌上那盒凉透的黄焖鸡米饭已经结膜了,筷子插在饭里没动过。窗外天黑得发青,不是晚上那种黑,是暴雨前的淤青色。这时候你得承认一件事:90%的PHP Bug根本不是逻辑错,是环境错配——dev环境用date_default_timezone_set('Asia/Shanghai'),prod忘了设,结果strtotime("now")返回负数;或者composer autoloader加载顺序被require_once硬覆盖;再或者mysql连接超时后PDO抛异常,你catch住了,但transaction状态早废了,后续commit直接静默失败。这种事,你看一百遍代码不如tail -f /var/log/mysql/error.log三分钟。老张刚走过来,把最后一口肉夹馍咽下去,顺手把我桌上那杯枸杞茶喝了一口——水温刚好,他啧了一声:“你这茶泡太久了,都涩了。”我说嗯,转头继续敲tail -f /var/log/php/error.log。其实我漏了一件事没说:上周五下午,有个项目突然500,查了半天是swoole_http_server里use了mysqli扩展,但fpm池没关,两套资源冲突。这事我没写进三步里,因为……它不算隐藏Bug,是明摆着的自杀式配置。但你要真去翻文档,swoole官方连warning都没标粗。所以我说优胜劣汰站得住——活下来的,不是调得最好的,是日志敢开、敢看、敢信的那批人。至于剩下那些还在xdebug单步的?随他们吧。我耳机里还挂着grafana告警语音:“alert php_fpm_active_processes high”,但我不点开。等它再响第三次,我才去。 对了,刚才小刘在隔壁喊,说他们新买的日志平台UI做得太花,搜索框要等两秒才出提示。我瞄了一眼——他浏览器地址栏输的是https://log.internal/v3/search,后面还挂着?from=now-15m&to=now&query=error。我低头继续敲命令,没回他。有些东西,换界面不换本质。 (编辑:PHP编程网 - 金华站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


PHP调试总卡壳?9年容器运维师揭秘3个被忽略的断点技巧


浙公网安备 33038102330481号