PHP调试总卡壳?3步精准定位90%隐藏Bug
|
去年高考期间,我在机房盯三台PHP-FPM子进程,空调坏了,风扇声像老式服务器背板在抖。王磊端着半杯冷掉的美式进来,把杯子搁我键盘右边——正好压住ESC键。我按了三次没反应,低头看见杯底一圈水渍正漫过F12。那时候我就知道,又得重走一遍那三步。
文章配图,仅供参考 第一步:关掉Xdebug,开error_log=stderr,让所有Notice全喷到STDERR里。不是为了看报错,是看它喷的顺序。你见过一个array_merge()失败后,紧接着冒出来十七行“Undefined index: status”的吗?那不是逻辑错,是某个foreach里提前return了,但上层try-catch吞掉了throw,只留个空数组往下传。我敢打包票,上周三下午四点十七分那个订单状态丢失,就是这路数。那天雨下得特别沉,雨滴砸在机房西侧玻璃上不是响,是闷哼,一声接一声,像心跳失同步。 第二步:不dump,不print_r,用debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS )截十层栈,然后 grep “/app/Models” —— 别碰vendor,别碰Laravel Facade,就盯自己写的类。张薇当时在我隔壁工位突然站起来,抄起桌上半盒凉透的麻辣香锅往茶水间走,筷子还插在盖子里晃。她一走,我就发现backtrace第4层有个App\\Models\\Order::getLatestStatus(),而第6层调用它的却是个叫SyncOrderStatusCommand的artisan命令——但这个命令,根本没在schedule里注册。谁手动跑的?什么时候跑的?我翻log发现它每十八秒触发一次。我原以为是supervisor的cron配置漏了,结果扒出来是运维老陈改完nginx.conf顺手 reload了php-fpm,顺手把重启脚本里一行注释给反注释了。这种事你写文档?写不完。写一百遍都漏掉那一行分号后面多出的空格。 第三步最脏:把opcache.revalidate_freq设成0,再在index.php最顶上加一句file_put_contents('/tmp/php_debug_tick', microtime(true)."\ 优胜劣汰?对。真正在生产环境活下来的,从来不是语法最优雅、类型最严谨、测试覆盖率最高的那套。是那些被线上日志烫过七次、被监控报警吵醒五次、被客户骂到凌晨两点还坚持在error_log里加一行file_put_contents的人写的代码。它们长得歪,变量名带拼音缩写,注释里写着“别动这行,动了就崩单点登录”。它们熬下来了,因为bug卡壳的时候,人不会等你重构完再爆发。 不过说实话,上周五看到新来的实习生在.env里把APP_DEBUG=true提交到Git,我还真没吼他。倒不是脾气好——是我昨天刚删掉自己三个月前写的那个curl_init()里忘了关ssl_verify的补丁,就藏在app/Services/PaymentClient.php第87行。现在想想,可能根本没生效,因为PHP 8.1之后那函数默认禁了。我说不准。反正那补丁已经灰了。 对了,刚才王磊又进来了,这次换了一次性纸杯,杯壁印着“XX教育高考护航行动”,蓝底白字。他放下的时候手抖了一下,一滴水落在键盘右上角,顺着Enter键的缝隙流进去。我没擦。反正待会儿要重启fpm。反正今天不下雨了。 你现在手上那段跑不通的代码,先去/tmp/里找找有没有叫php_debug_tick的文件。有,就open它;没有,就去把php.ini里的error_reporting设成E_ALL & ~E_NOTICE。别管为什么。就做。做完再说。 (编辑:站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


PHP调试总卡壳?3个90%新手忽略的断点技巧
写代码前没理清这三大逻辑?90%的Bug源于导航断层
