Ubuntu环境下PHP服务脚本真实内存占用持续增长问题求助
Ubuntu环境下PHP服务脚本真实内存占用持续增长问题求助
你好,针对你遇到的PHP无限循环脚本真实内存持续增长的问题,我来帮你分析下可能的原因和可行的排查解决方向:
先明确两个内存统计参数的差异
首先得搞清楚get_memory_usage()两个参数的核心区别,这能帮你快速定位问题根源:
get_memory_usage(false):仅统计PHP自身用户态分配的内存,这个值稳定说明你的业务代码里没有明显的PHP变量级内存泄漏(比如未释放的变量、循环引用未被GC处理)get_memory_usage(true):统计PHP进程从操作系统实际申请的物理内存(包含PHP内核缓存、扩展占用的内存等),这个值持续增长,问题大概率出在底层资源未释放或操作系统内存分配机制上
可能的原因分析
- 外部资源未彻底释放:你脚本里涉及MySQL存储、外部检查(大概率是HTTP请求),这些操作依赖的底层资源如果没正确回收,会导致操作系统层面的内存占用累积。比如:
- 每次循环新建MySQL连接但未用
mysqli_close()/PDO::null销毁 - curl请求后未调用
curl_close()释放句柄 - 文件操作后未用
fclose()关闭文件描述符
- 每次循环新建MySQL连接但未用
- 操作系统内存缓存机制:Linux会把空闲内存用作缓存,PHP进程申请的内存如果没有主动归还,系统可能会暂时保留在进程地址空间,不过如果内存涨到1GB,肯定不是单纯的缓存问题
- 非PHP原生资源未被GC处理:PHP的垃圾回收只针对自身的对象和变量,像第三方扩展的资源、底层系统句柄这类不在GC范围内,需要手动释放;你调用了
gc_collect_cycles()但没效果,大概率是这类资源的问题
具体排查与解决步骤
1. 强制清理循环内的所有资源
在循环迭代结束后,手动释放所有临时变量和外部资源,示例代码调整如下:
function execute(&$loop, $rep_server){ foreach($rep_server->objetos as $server){ $dates = ...; // 你的业务逻辑代码 // 执行外部检查、MySQL存储等操作后 // 手动释放当前循环内的临时变量 unset($dates); unset($server); // 如果用到了curl/MySQL连接,在这里显式关闭 // 比如 curl_close($ch); 或者 mysqli_close($conn); } // 清理循环引用并触发GC unset($rep_server); gc_collect_cycles(); }
2. 用系统工具定位内存增长区域
- 用
pmap查看进程的内存映射详情:
观察输出里的内存区域大小变化,能快速定位是堆内存、共享库还是缓存区在持续增长pmap -x <你的PHP进程PID> - 用
htop的F2设置里开启SHOW MEMORY PERCENTAGE和SHOW PROCESS TREE,更直观地跟踪进程内存变化
3. 排查PHP扩展与配置
- 暂时禁用所有非必要的第三方扩展(比如监控、调试类扩展),重启脚本后看内存是否还增长,排查是否是扩展存在内存泄漏
- 调整PHP内存相关配置:
- 确认
zend.enable_gc = On(php.ini中) - 减小
realpath_cache_size(默认可能较大,长期运行会累积缓存) - 对于PHP 7+,可以尝试调整
zend.memory_limit限制内核内存分配
- 确认
4. 兜底方案:定时重启脚本
如果以上方法都无法彻底解决,可以用supervisor管理你的PHP服务,配置脚本运行一定时间后自动重启,避免内存持续涨到1GB影响系统稳定性。比如在supervisor配置里添加:
[program:php-monitor-script] command=/usr/bin/php /path/to/your/script.php autostart=true autorestart=true startretries=3 user=www-data stdout_logfile=/var/log/php-monitor.log stderr_logfile=/var/log/php-monitor.err.log stopwaitsecs=10 ; 每24小时重启一次 startsecs=86400
备注:内容来源于stack exchange,提问作者Vitor Lins
相关产品推荐
相关产品推荐

