|
记一次systemd进程内存占用高的解决方法
场景:某天巡检发现应用访问异常,报数据库连接错误,登陆服务器排查,重启数据库失败,日志显示内存不足。进一步排查内存情况,吓一跳,systemd占用达到1G,这是很不正常的行为。
接下来是排查阶段:
1.首先查看systemctl版本,有些版本可能有内存泄漏的风险,如果本身系统运行时间过长,就会导致这种情况发生。
systemctl --version
2.查看是否有大量排队作业:
systemctl list-jobs
如果有大量未完成的作业,可能导致 systemd 内存膨胀。
排查并未发现有作业在运行。
3.统计管理的单元数量
systemctl list-units --all | wc -l
如果单元数量异常多(例如数千个),可能是由于某些服务频繁生成瞬时单元(如用户会话),需要进一步分析。
排查为200多个,还算正常。
4.查看 systemd 内存详细分布
# 查看进程内存映射中较大的区域
cat /proc/1/smaps | grep -E "Pss|Name" | grep -B1 -E "Pss:\s+[0-9]{6,}"
这可以找出哪些内存段占用较大。如果发现某个匿名映射或堆占用了大量内存,可能是内存泄漏点。
根据排查信息,确认 systemd(PID 1)的物理内存占用集中在单个巨大的内存段,而其他方面(共享库、作业队列、单元数量)均正常。强烈指向 systemd 内部存在内存泄漏或长期运行积累的碎片。
5.检查是否有异常库注入
# 查看进程加载的共享库
lsof -p 1 | grep '\.so'
cat /proc/1/maps | grep '\.so'
如果出现非系统路径的 .so 文件,需警惕。
解决:
根据排查,基本锁定为内存泄漏,尝试重新执行 systemd(不重启系统)
systemctl daemon-reexec
# 稍等片刻,再次查看内存
cat /proc/1/smaps | grep -i pss | awk '{sum+=$2} END {print "Total PSS: " sum " KB"}'
恢复正常
注意:如果执行systemctl daemon-reexec后,内存占用还是居高不下,那就需要准备重启系统了。
|