文章目录
- 一、阐述问题
- 二、开始排查
- 1.执行代码展示
- 2.PHP层面排查问题
- 3.系统层面排查问题
- 1. 分析系统日志
- 2. core dump 分析
- 2.1 core dump 是什么
- 2.2 core dump 配置 并 生成 core 文件
- 2.3 gdb 解析 core 文件
- 4. 问题解决
- 三、赠送内容
- 四、总结
一、阐述问题
这个问题花了我起码10个小时,必须得总结一下。
问题是这样的,我在laravel 里面连接了一下sqlserver的数据库,然后页面直接就报502
。去项目下的日志看,也没有任何报错。
二、开始排查
1.执行代码展示
$serverName = '192.168.116.180\messyna'; //数据库服务器地址
$connectionInfo = array("UID" => "mssa", "PWD" => "12345677", "Database" => 'test111');
$conn = sqlsrv_connect($serverName, $connectionInfo);
if($conn == FALSE){echo "连接失败!";var_dump(sqlsrv_errors());exit;
}else{echo "链接成功";
}
echo "连接成功!";
exit;
这就是普通的连接sqlserver的代码。只要执行这段代码,直接就报 502!
Sqlserver
的配置肯定没问题,前一天还是可以执行的。而且有其他的机器能执行。
2.PHP层面排查问题
经过一段时间的乱碰,觉得还是看一下php-fpm
的错误日志。
找到php-fpm的配置,找到错误日志路径。
终于看到报错信息:
deepseek
的回答结果如下:
WARNING: [pool www] child 4542 exited on signal 11 (
SIGSEGV
) after 542.345727 seconds from start
-
含义:www 进程池中的子进程 4542 在运行 542秒(约9分钟) 后,因
信号 11(SIGSEGV)
崩溃退出。-
SIGSEGV(分段错误)
:表示进程试图访问非法内存地址,常见原因包括:-
PHP 扩展(如 Redis、Opcache 等)存在 bug。
-
PHP 代码中存在
内存溢出
(如无限递归、大数组操作)。 -
服务器内存不足或配置错误(如 pm.max_children 设置过高)。
-
硬件问题(如内存条故障,但概率较低)。
-
-
我的分析测试:
硬件问题可以排除,最近我都没动过什么配置之类的。而且是虚拟主机,不可能。PHP 代码中存在内存溢出可以排除。就一个连接,能有什么溢出内存不足,我将虚拟主机加大了2G内存, 结果还是502,说明不是内存问题。扩展问题,感觉有点像
- mysql的连接是正常的,就sqlserver 不正常
- 重新安装 pdo_sqlsrv 和 sqlsrv 两个扩展,结果依然是502,跟扩展没关系重装php8.2,结果测试,还是502
经过以上的测试,差不多可以知道,应该不是php的问题。应该是centos系统的问题。不管怎么测试。指向的都是 分段错误
3.系统层面排查问题
1. 分析系统日志
dmesg | grep php
在系统日志中筛选与 “php” 相关的信息
取一条日志出来看看:
[65062.298372] php-fpm[1288]: segfault at 0 ip 00007fc555571fd6 sp 00007fff26f52bb8 error 4 in libc-2.17.so[7fc555433000+1c4000]
经过查资料分析:
这个错误提示表明 PHP-FPM 进程发生了段错误(segfault
),这通常是由内存访问违规引起的严重错误。
segfault at 0
:程序尝试访问内存地址 0x0(空指针),这通常是由于未初始化的指针或内存损坏导致的。
libc-2.17.so
:错误发生在 C 标准库中,这是系统核心组件,可能由以下原因触发:
- PHP 扩展与 libc 不兼容。
- PHP 本身存在内存管理漏洞。
- 系统库文件损坏。
error 4
:表示 SEGV_ACCERR(访问权限错误),即程序尝试访问没有权限的内存区域。
总体上来说,应该是读取内存地址无效。但是没有具体的信息,过于笼统,还需要进一步的调试。
又经过了漫长的查资料,终于查到了一点方向,core dump
2. core dump 分析
2.1 core dump 是什么
-
core dump 是什么?
core dump(核心转储) 是操作系统在程序异常终止(如崩溃、段错误、非法指令等)
时,将进程当时的内存状态、寄存器内容、程序计数器值等关键信息写入到一个文件中的过程。这个文件被称为 core 文件,它本质上是进程运行时状态的 “快照
”。 -
core dump 的作用
-
调试程序错误
开发人员可以通过分析core 文件
,定位程序崩溃的具体位置(如哪行代码引发错误)、变量值、函数调用栈等信息,从而快速排查内存越界、空指针引用、段错误等问题。 -
系统故障分析
在服务器环境中,core dump 可用于分析长期运行的服务(如 Web 服务器、数据库)突然崩溃的原因,避免问题反复出现。 -
性能优化参考
虽然 core dump 主要用于错误定位,但也能间接反映程序的内存使用模式,为性能优化提供线索。
-
-
core dump 的触发场景
当程序遇到以下情况时,系统通常会生成 core dump:- 访问非法内存地址(如空指针解引用、数组越界)
- 执行非法指令(如除以 0、无效的 CPU 操作码)
- 收到无法处理的信号(如 SIGSEGV、SIGABRT)
- 内存不足或被系统强制终止(如 OOM Killer 触发)
正和我意,触发场景正好能解决我的问题。
2.2 core dump 配置 并 生成 core 文件
-
设置 core 文件大小为无限制(unlimited):
//临时调试 ulimit -c unlimited//调试完最后记得关闭 core dump ulimit -c 0
-
执行 php 代码,报错 502。 此时在项目的根目录下,会生成一个 core 文件。
这几个core 文件就记录了 内存读取失败的相关情况,那接下来就是读取这个core 文件了
2.3 gdb 解析 core 文件
GDB(GNU Debugger) 是 Linux/Unix 系统下最常用的 代码调试工具
,主要用于分析和修复程序崩溃、死锁、内存泄漏
等问题
1. 安装 gdb
yum install gdb
2. 生成 GDB 回溯信息
gdb php core.2134
(gdb) bt full # 获取完整的堆栈回溯
3. 文件内容如下:
4. 经过deepseek分析:
4. 问题解决
根据 GDB
完整堆栈回溯信息,问题的根源已经很明显了
OpenSSL库版本冲突 ,有两个库版本,ODBC驱动尝试初始化SSL连接时,不同版本的OpenSSL库发生冲突,导致内存访问异常
确实是有两个,而且那个还是前一天我安装 python 时候产生的。
直接删除openssl111
,因为openssl111 安装前,一直是正常的。肯定是 openssl111 安装了,导致出问题
删除后,执行代码,一切正常。终于解决
三、赠送内容
以下是监控 PHP-FPM 主进程,然后程序崩溃时,可以查看具体情况
# 附加到 PHP-FPM 主进程
sudo gdb -p $(pgrep -o php-fpm)# 当崩溃发生时,输入以下命令抓取堆栈
(gdb) bt full # 查看完整调用栈
(gdb) info threads # 查看所有线程状态
(gdb) quit # 退出
四、总结
整个过程非常艰辛,由什么问题都不知道一直到解决,查了很多资料。走了很多的弯路。
一些工具都是第一次使, core dump,gdb
以前基本上没使用过。
需要持续的学习,持续的踩坑,才能到达最终的彼岸 =》保安