生產環境 PHP-FMP 子進程頻繁收到 SIGBUS (signal 7) 退出,Nginx 回傳 502。本文記錄完整排查過程:開啟 coredump、gdb 回溯、strace 系統調用追蹤、鎖定 opcache 衝突根因並給出解決方案。
php-fpm.log 大量 child exited on signal 7 (SIGBUS)。# 設定 core 檔案路徑與命名格式 echo "/tmp/core.%e.%p.%h.%t" > /proc/sys/kernel/core_pattern # 允許無限大 core ulimit -c unlimited # 重啟 php-fpm systemctl restart php-fpm
gdb /usr/local/php/sbin/php-fpm /tmp/core.php-fpm.12345 (gdb) bt #0 0x00007f... in lex_scan () from /usr/local/php/lib/php/opcache.so #1 0x00007f... in zendlex () #2 0x00007f... in zendparse () ... # 多個 core 皆停在 lex_scan / zendlex 階段
搜尋 php sigbus lex_scan 直指 PHP 官方 Bug #52752(2010 年開啟,長期未修):
cp/rsync、opcache 重新編譯、框架熱更新)。strace -p-f -o trace.log # 事故瞬間日誌: 11670 lstat("/home/www/cache/default.php", {st_size=68579, ...}) = 0 11670 --- SIGBUS (Bus error) @ 0 (0) ---
確認是讀取快取檔 default.php 時觸發。
rename() 原子替換舊檔,避免讀寫並發。opcache.validate_timestamps=0 # 生產關閉時間戳驗證,手動重啟或 cachetool 刷新 opcache.revalidate_freq=0 # 配合上面 opcache.file_cache_only=1 # 僅用檔案快取,避免共享記憶體衝突 (可選)
/tmp 或獨立目錄,不與代碼目錄混用。調整部署腳本採用 rsync --delay-updates + mv 原子切換,並關閉 validate_timestamps,連續觀察一週無 SIGBUS 復發。
SIGBUS 在 PHP 中幾乎等同於「執行中的腳本檔案被外部修改」。生產環境務必採用**原子性部署**、關閉 opcache 時間戳驗證、隔離可寫快取目錄,從架構層面杜絕此類硬故障。