☰
银河麒麟V10内存不释放排查与定时释放脚本实战
2026/10/20 13:36:54 网站建设 项目流程

简介:这份资源面向银河麒麟V10服务器操作系统的运维人员与系统管理员,聚焦内存不释放(内存泄漏)这一常见性能问题,提供定时排查与释放的实用方案。资源包共3个文件,包含2个sh脚本与1个txt说明文档,压缩包仅2KB,轻量易部署,其中脚本可用于定时检测与释放内存,说明文档则交代配置方法与使用要点。内容围绕内存监控、泄漏定位、日志分析、参数调优及服务重启等思路展开,帮助读者在不影响业务的前提下逐步排查问题,提升系统维护效率。目前已有781人学习下载,适合需要快速落地内存治理方案、减少人工巡检成本的运维人员参考使用。

1. 银河麒麟V10内存不释放:一个让运维半夜爬起来的坑

凌晨两点收到告警,某台跑着银河麒麟V10的生产服务器内存使用率冲到 95%,SSH 勉强能连上,但敲个ls都要等三秒。第一反应是哪个进程内存泄漏了,结果top一看,排前面的进程 RSS 加起来还不到物理内存的一半。free -h却显示 available 只剩几百兆,buff/cache 高得离谱。这种“内存不释放”的故障在银河麒麟V10上不算罕见,尤其是长期运行的业务机、数据库中间件、日志采集节点。它折腾人的地方在于:进程没崩、CPU 不高、磁盘也没满,但系统就是越来越卡,最后 OOM Killer 随机杀进程,业务直接抖一下。这篇笔记面向正在被同类问题卡住的运维和开发,把报错现象、根因定位、定时释放的落地脚本一次讲清楚,照着命令走就能复现和解决。

2. 先别急着重启:内存不释放的三种典型现象与根因

2.1 free 显示 available 很低但进程 RSS 正常

这是最容易误判的一种。你登录上去执行:

free -h

看到类似输出:

total used free shared buff/cache available Mem: 62Gi 18Gi 1.2Gi 356Mi 43Gi 40Gi Swap: 8.0Gi 512Mi 7.5Gi

注意available其实还有 40Gi,这种情况不是故障。Linux 会把空闲内存拿去做页缓存(buff/cache),需要时自动回收。真正要警惕的是available低于总内存 10%,同时buff/cache居高不下且不下降。判断标准很简单:连续观察 5 分钟,如果available持续走低、buff/cache只增不减,才进入下一步排查。

常见做法是先用vmstat看回收行为:

vmstat 1 10

重点看si、so两列。如果si/so长期为 0,说明系统还没开始换页,问题可能出在 slab 或者被某类内核对象占住;如果si/so频繁非零,说明物理内存真的不够,已经在拿 Swap 硬撑。

2.2 slab 占用异常:内核对象没释放

银河麒麟V10基于较新的内核,slab分配器管理内核对象。某些驱动或文件系统模块在长期运行后会出现 slab 只增不减。执行:

slabtop -o | head -20

如果看到dentry、inode_cache、kmalloc-*某一项占了几个 G,基本可以锁定是内核缓存没回收。这类问题的根因通常是:某个目录下有海量小文件被反复扫描,dentry 缓存无法释放;或者某个内核模块存在引用计数泄漏。解决方向不是重启,而是先手动触发回收:

sync echo 3 > /proc/sys/vm/drop_caches

sync先把脏页刷盘,避免丢数据;echo 3表示同时回收 pagecache、dentries 和 inodes。执行后再看free -h,如果 available 明显回升,说明是缓存类占用,可以纳入定时任务处理。

注意:drop_caches是即时操作,生产环境执行前确认业务低峰,虽然它本身安全,但回收瞬间大量 IO 可能造成短时抖动。

2.3 透明大页与内存碎片导致释放失败

还有一种更隐蔽的情况:free显示 free 内存不少,但申请大块连续内存失败,或者drop_caches执行后 available 几乎没变化。这往往和透明大页(THP)以及内存碎片有关。检查:

cat /sys/kernel/mm/transparent_hugepage/enabled cat /proc/buddyinfo

如果 THP 是[always],且buddyinfo里高阶块(order 8 以上)几乎为 0,说明内存碎片严重,内核无法合并出连续大页,导致部分内存“看着空闲却用不上”。对于数据库类应用,常见做法是把 THP 调成madvise或never:

echo madvise > /sys/kernel/mm/transparent_hugepage/enabled

这个设置重启会失效,需要写进开机脚本或 systemd 服务。改完后配合定时drop_caches,多数“内存不释放”的假象会消失。

3. 定时释放怎么做:从 crontab 到 systemd timer 的落地脚本

3.1 用 crontab 写一个带日志的释放脚本

最直接的方式是写一个 shell 脚本,由 cron 定时触发。脚本不能只写echo 3 > drop_caches,那样出问题你连什么时候执行的都不知道。我一般会加上时间戳、执行前后内存快照和阈值判断:

#!/bin/bash # /usr/local/sbin/mem_release.sh # 银河麒麟V10 定时内存回收脚本 LOG=/var/log/mem_release.log THRESHOLD=15 # available 低于总内存 15% 才触发 TOTAL=$(free -m | awk '/Mem:/{print $2}') AVAIL=$(free -m | awk '/Mem:/{print $7}') PERCENT=$((AVAIL * 100 / TOTAL)) echo "$(date '+%F %T') total=${TOTAL}M avail=${AVAIL}M percent=${PERCENT}%" >> $LOG if [ $PERCENT -lt $THRESHOLD ]; then sync echo 3 > /proc/sys/vm/drop_caches echo "$(date '+%F %T') triggered drop_caches" >> $LOG free -m >> $LOG fi

逻辑说明:free -m取 MB 为单位,第 7 列是 available;THRESHOLD=15表示只有可用内存低于 15% 才动手,避免无脑回收影响性能。sync保证脏页落盘,drop_caches释放缓存。日志里记录触发前后的内存状态,方便回溯。给脚本加执行权限:

chmod +x /usr/local/sbin/mem_release.sh

然后加入 crontab,每 30 分钟检查一次:

crontab -e

写入:

*/30 * * * * /usr/local/sbin/mem_release.sh

参数怎么改:如果业务对延迟敏感,可以把阈值调到 10;如果机器内存大、缓存命中率高,调到 20 更积极。日志文件记得配 logrotate,否则一年下来能撑满/var。

3.2 systemd timer 替代 cron 的写法

银河麒麟V10默认支持 systemd,用 timer 比 cron 更好管理依赖和日志。先建 service:

# /etc/systemd/system/mem-release.service [Unit] Description=Memory release task for Kylin V10 After=network.target [Service] Type=oneshot ExecStart=/usr/local/sbin/mem_release.sh

再建 timer:

# /etc/systemd/system/mem-release.timer [Unit] Description=Run memory release every 30 minutes [Timer] OnBootSec=10min OnUnitActiveSec=30min Unit=mem-release.service [Install] WantedBy=timers.target

启用并启动:

systemctl daemon-reload systemctl enable --now mem-release.timer systemctl list-timers | grep mem-release

OnBootSec=10min表示开机 10 分钟后首次执行,避开启动高峰;OnUnitActiveSec=30min是间隔。用journalctl -u mem-release.service看每次执行输出,比翻日志文件更集中。两种方式选哪个:临时救急用 cron,长期规范运维用 timer。

3.3 释放后仍不下降怎么办:检查泄漏进程

如果脚本按时执行、日志显示drop_caches也写了,但 available 还是往下掉,说明有进程在持续吃内存。用下面这条命令按 RSS 排序找嫌疑:

ps -eo pid,ppid,comm,rss --sort=-rss | head -15

找到可疑 PID 后,观察它的 RSS 是否随时间单调递增:

pidstat -r -p <PID> 5 12

pidstat每 5 秒采样一次,共 12 次,看RSS和%MEM列。如果持续上涨不回落,基本是应用层内存泄漏,定时drop_caches救不了,得从代码或配置入手。常见做法是给该服务加MemoryMax限制(systemd)或配 OOM 优先级,先保住整机,再排应用。

4. 避坑记录:定时释放内存时最容易翻车的五件事

4.1 无阈值无脑 drop_caches 导致业务抖动

现象:脚本每 5 分钟执行一次echo 3,业务方反馈接口 P99 延迟周期性升高。原因:频繁回收 pagecache,热点文件每次都要重新从磁盘读,IO 压力陡增。解决:加 available 百分比阈值,只在低于 15% 时触发,并把间隔拉到 30 分钟以上。

4.2 忘记 sync 导致脏页丢失

现象:某次释放后数据库报文件损坏。原因:脚本直接写drop_caches,没有先sync,部分脏页还在内存就被丢弃。解决:任何drop_caches前必须sync,这是血泪经验,别省这一行。

4.3 THP 没关,drop_caches 后 available 几乎不变

现象:执行脚本后free的 available 只涨了几百兆,和 buff/cache 下降量对不上。原因:透明大页占用的内存不计入常规缓存回收路径。解决:把 THP 设为madvise,并写进/etc/rc.local或 systemd unit,重启后确认cat /sys/kernel/mm/transparent_hugepage/enabled生效。

4.4 日志文件把 /var 撑满

现象:运行三个月后/var/log/mem_release.log超过 10G,系统盘告警。原因:脚本每次执行都追加free -m输出,没有轮转。解决:配 logrotate:

/var/log/mem_release.log { weekly rotate 4 compress missingok notifempty }

4.5 在容器里执行宿主机命令无效

现象:在 Docker 容器内跑脚本,提示/proc/sys/vm/drop_caches只读。原因:容器默认没有权限修改宿主机内核参数。解决:释放操作必须在宿主机执行,容器内只做监控和告警。如果业务跑在容器里,把脚本放到宿主机 cron,通过docker stats或 cgroup 指标判断是否触发。

5. 快速定位内存不释放:一套五分钟排查路径

遇到告警别慌,按下面顺序走,五分钟内能判断是缓存假象、内核占用还是真泄漏。

第一步,看全局:

free -h && cat /proc/meminfo | grep -E 'MemAvailable|Cached|Slab|SReclaimable'

MemAvailable是内核估算的可用内存,比free列更准。如果它还有总内存 20% 以上,先不用动手。

第二步,看缓存构成:

slabtop -o | head -15

SReclaimable高说明可回收,SUnreclaim高说明不可回收,后者要警惕内核模块问题。

第三步,看回收行为:

vmstat 1 5

si/so非零说明在换页,物理内存真紧张;全零但 available 低,回到 slab 和 THP。

第四步,看进程:

ps -eo pid,comm,rss --sort=-rss | head -10

RSS 总和远小于 used,问题在内核侧;接近 used,问题在应用侧。

第五步,验证释放:

sync && echo 3 > /proc/sys/vm/drop_caches && free -h

available 明显回升,纳入定时任务;不回升,查 THP 和泄漏进程。

现象优先检查常用命令
available 低但 buff/cache 高是否缓存假象free -h、/proc/meminfo
slab 某项占几个 G内核对象泄漏slabtop -o
drop_caches 后无变化THP / 碎片cat /sys/kernel/mm/transparent_hugepage/enabled
某进程 RSS 单调涨应用内存泄漏pidstat -r -p PID 5 12
容器内执行失败权限隔离宿主机执行

从那以后我每次上架银河麒麟V10的机器,都会先把 THP 调好、把带阈值的释放脚本和 logrotate 一起配进去,再挂上 available 低于 10% 的告警。这套习惯帮我省掉了至少三次半夜爬起来重启的折腾。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询