某年某月某日,一個(gè)工程師跑來找我說:很多用戶抱怨APP頻繁閃退,他覺得server運(yùn)行正常,找不出原因,請(qǐng)我?guī)兔?/p>
按照流程一路排查下去,發(fā)現(xiàn)Nginx訪問日志里面有大量的http 504 err code
tail -f /var/log/messages
同時(shí)出現(xiàn)大量的類似錯(cuò)誤信息
nginx[1234]: segfault at 0000000000000008 rip 000000000043edf8 rsp 00007fff34a21fa0 error 4
出現(xiàn)segfault那只能用gdb了,這也是Linux做server的好處了,換成微軟平臺(tái),無比的麻煩
解決問題分成4步:
配置系統(tǒng)生成coredump文件,很簡單
ulimit -a
第一行就是關(guān)于core file的設(shè)置,默認(rèn)是不生成coredump文件的,執(zhí)行 ulimit -c 1024 即可,記得調(diào)試完成之后要用ulimit -c 0關(guān)閉,不然你的硬盤很快會(huì)被填滿
gdb調(diào)試,需要debug版本的nginx才能定位到源代碼,于是需要重新編譯一份nginx
首先把現(xiàn)有的nginx bin目錄和conf目錄都備份
然后打印nginx的原始編譯選項(xiàng)
/opt/nginx/sbin/nginx -V
在這個(gè)基礎(chǔ)上加上 --with-debug,重新make一份即可
在${NGINX-SOURCE-DIR}$/objs 目錄中找到編譯好的nginx ,復(fù)制到你的nginx運(yùn)行目錄,切記不要make install ,因?yàn)檫@樣會(huì)覆蓋掉你的nginx.conf文件
重新運(yùn)行nginx,等待core.xxx文件生成。一般是在當(dāng)前目錄下生成
用gdb加載 coredump 文件
gdb --core=core.xxx
gdb> where
很容易就找到了nginx segfault的原因:我們自己寫的一個(gè)nginx modules里面,對(duì)某些參數(shù)沒有做邊界檢查,但外部環(huán)境變化之后,訪問空指針了
收尾:
ulimit -c 0 :關(guān)掉coredump
改完代碼之后,重新編譯一份不帶debug信息的nginx