- 發現問題
最近發現服務器頻繁出現core.xxx文件,並且php-fpm.log有類似這樣的記錄
WARNING: [pool www] child 2930 exited on signal 7 (SIGBUS - core dumped) after 22458.193927 seconds from start
說明有php-fpm進程異常退出了,業務側的表現就是某些功能第1次打開異常(如顯示空白),再點擊又正常,這種現象的原因該php-fpm進程異常退出了。
- 分析問題的的原因
最直接的辦法就是用gdb工具對core.xxx進行分析了。
gdb /usr/local/php56/sbin/php-fpm -c /tmp/core.4522
輸入命令bt
,會列出退出前的堆棧信息,如
#0 lex_scan (zendlval=zendlval@entry=0x7ffc0ef65bb8) at Zend/zend_language_scanner.c:1082
#1 0x0000000000705642 in zendlex (zendlval=zendlval@entry=0x7ffc0ef65bb0) at /usr/local/src/php-5.6.32/Zend/zend_compile.c:6919
#2 0x00000000006e0256 in zendparse () at /usr/local/src/php-5.6.32/Zend/zend_language_parser.c:3732
#3 0x00000000006e5a08 in compile_file (file_handle=<optimized out>, type=2) at Zend/zend_language_scanner.l:586
#4 0x00000000005ab802 in phar_compile_file (file_handle=<optimized out>, type=<optimized out>) at /usr/local/src/php-5.6.32/ext/phar/phar.c:3370
#5 0x00007fb2962aebb4 in compile_and_cache_file (file_handle=file_handle@entry=0x7ffc0ef682f0, type=type@entry=2,
key=key@entry=0x7fb2964cbafc <accel_globals+380> "/webroot:./Application/Runtime/Cache/VendorApi/48b1f9c30fb6cceae8315a38de289ddd.php:/webroot/ThinkPHP/Library/Think/Storage/Driver:A", key_length=166, op_array_p=op_array_p@entry=0x7ffc0ef681e0,
可以看到最開始一條記錄,是函數lex_scan
異常退出了,lex是屬於詞法分析的zend方法,往下看也可以發現業務側的代碼,如/webroot:./Application/Runtime/Cache/VendorApi/48b1f9c30fb6cceae8315a38de289ddd.php
,根據上述代碼可以知道是分析這個文件時出錯了,打開這個文件看看是什麼內容:
<?php if (!defined('THINK_PATH')) exit();?><?xml version="1.0" encoding="utf-8"?>
<response>
<state>
<code><?php echo ($result["code"]); ?></code>
<message><?php echo ($result["message"]); ?></message>
</state>
</response>
嗯,一個thinkphp的xml模板文件,看到這個文件基本可以定位原因了,是由<?xml version="1.0" encoding="utf-8"?>
這個標籤php無法正確進行語法解析, 進而導致php-fpm整個進程退出了。剩下的解決辦法就好處理了,結合業務側把<?xml version="1.0" encoding="utf-8"?>
先從模板裏刪除,或移動到其它地方再輸出。更新代碼後,刪除此目錄下的緩存文件Application/Runtime/Cache/VendorApi/
讓thinkphp重新生成。
上面的分析方法,因爲有業務側的代碼顯現,還比較容易定位問題,否則就要藉助php提供的.gdbinit
腳本了,它能將更高層的業務跟蹤代碼顯示出來,.gdbinit
文件的位置一般是在/usr/local/src/php-5.6.30/.gdbinit
目錄下(php後的版本號根據你的環境修改,或者通過find方法搜索,或在這下載https://github.com/php/php-src/blob/master/.gdbinit
)。 仍停留在上面的gdb交互環境裏,執行命令source /usr/local/src/php-5.6.30/.gdbinit
,再執行命令zbacktrace
,則會打印更多業務側的代碼,如下
(gdb) source /usr/local/src/php-5.6.30/.gdbinit
(gdb) zbacktrace
[0x7fb2a45a4a38] load() /webroot/ThinkPHP/Library/Think/Storage/Driver/File.class.php:80
[0x7ffc0ef68560] Think\Storage\Driver\File->load("./Application/Runtime/Cache/VendorApi/48b1f9c30fb6cceae8315a38de289ddd.php", array(1)[0x32adaf8], NULL, "tpl")
[0x7fb2a45a4900] call_user_func_array(array(2)[0x32c7e28], array(4)[0x32c7c60]) /webroot/ThinkPHP/Library/Think/Storage.class.php:37
[0x7ffc0ef68860] Think\Storage::__callstatic("load", array(4)[0x32c7dc8])
[0x7fb2a45a4798] Think\Storage::load("./Application/Runtime/Cache/VendorApi/48b1f9c30fb6cceae8315a38de289ddd.php", array(1)[0x32adaf8], NULL, "tpl") /webroot/ThinkPHP/Library/Think/Template.class.php:77
[0x7fb2a45a4620] Think\Template->fetch("./Application/VendorApi/View/Lvmama/push_product_change_info.html", array(1)[0x32adaf8], "") /webroot/Application/Runtime/common~runtime.php:1
[0x7fb2a45a44c8] Behavior\ParseTemplateBehavior->run(array(4)[0x32aebf8]) /webroot/Application/Runtime/common~runtime.php:1
也可以發現php-fpm是在處理./Application/Runtime/Cache/VendorApi/48b1f9c30fb6cceae8315a38de289ddd.php
後失敗就結束了。
觀察一段時間後沒再出現core dump,到此,問題得到解決。
如果要調用運行中的進程,可以gdb --pid=xxx
或gdb -p xxx
。
參考:
- https://blog.csdn.net/belllab/article/details/78673823
- https://www.vckai.com/shi-yong-gdb-diao-shi-php-core-dump
- https://www.cnblogs.com/GreenForestQuan/p/10972021.html
- https://derickrethans.nl/what-is-php-doing.html
- https://wiki.swoole.com/wiki/page/p-gdb.html
@author:[email protected]