ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

银河麒麟V10内存不释放?用阈值脚本和定时任务精准清理缓存

银河麒麟V10内存不释放?用阈值脚本和定时任务精准清理缓存 简介一份面向银河麒麟V10服务器运维场景的实用资源聚焦系统运行中常见的内存不释放内存泄漏问题提供可落地的定时清理应对方案。资源体量精简仅包含3个文件以Shell脚本为主2个sh并附1个txt配置说明压缩包大小2KB轻量且便于直接部署。脚本可用于设置定时任务自动回收不再使用的内存说明文档则对参数配置与执行注意事项做了梳理适合需要快速缓解内存占用持续增长问题、保障业务稳定性的系统管理员与运维人员参考。目前已有773人学习下载资源虽小但针对性明确通过脚本加说明的组合帮助用户在不中断业务的前提下实施内存清理操作并结合系统监控、日志分析等常规手段提升银河麒麟V10的长期运行可靠性。1. 银河麒麟V10内存不释放先分清对象缓存堆积与真泄漏定时方案才有意义银河麒麟V10常见于 V10 SP1/SP3 的服务器或桌面版跑上几天后free显示可用内存在一路往下掉应用卡得像睡着了重启就能缓过来。很多人第一反应是“内存不释放得做定时清理”但清理前没分清对象清完可能更卡。这里直接说结论Linux 下大部分“内存不释放”只是 page cache 或 inode 缓存变大它们随时可以被内核回收真正的麻烦是不可回收的进程内存和内核 slab 在持续增长。下面先教你怎么从free、/proc/meminfo、ps判断该清哪些再给一个带阈值判断的定时释放脚本以及 crontab / systemd timer 两种挂法最后是麒麟 V10 上我踩过的几个坑。适合维护长期不关机服务器、在虚拟机里跑银河麒麟或者接手这类环境的人。2. 用 free、drop_caches、ps 确认内存失守点判据与边界不先把对象搞清楚就直接写定时任务大概率会在运维群里翻车。这个章节我们做三件事看懂free -h的可用内存口径把“能回收的缓存”和“不能回收的业务内存”分开再给你一条命令判断当前是否真的需要人工介入。2.1 看 free 的第一眼内存“不释放”不等于内存“不够”在银河麒麟 V10 上执行free -h你会看到类似这样的输出total used free shared buff/cache available Mem: 62G 1.2G 480M 121M 59G 55G Swap: 15G 0B 15Gfree这一列只有 480M但available是 55G。系统实际可用的内存是available不是free。buff/cache里绝大部分是读文件、写日志留下的页缓存内核会在需要时自动回收。很多人误以为“内存不释放”是因为free太小其实只要available还有余量业务就不会真的缺内存。反直觉的地方在于你越频繁读取文件、写入日志、加载程序buff/cache就涨得越猛free越小但这是 Linux 内存管理刻意为之的不是缺陷。要观察的是走势连续一周里available是否每天都在稳步下降而不是看某一时刻的数字。2.2 分清哪类内存能“被定时任务释放”继续往下看/proc/meminfo里的细分字段grep -E ^(MemTotal|MemFree|MemAvailable|Buffers|Cached|SReclaimable|SUnreclaim|Committed_AS) /proc/meminfo对照下面这张表定位你机器上的内存到底属于哪种类型内存类型典型来源drop_caches 能否回收关键指标页缓存Buffers/Cached读写文件产生的缓存能echo 1 / echo 3Cacheddentry/inode 缓存文件系统元数据能echo 2 / echo 3SReclaimable进程匿名内存RSS应用自身堆栈不能只能重启或释放ps 里的 RSS内核不可回收 slab驱动、内核模块不能SUnreclaimtmpfs 临时文件系统挂载在内存里的 /tmp 等不能但可删文件挂载点 usedecho 3 /proc/sys/vm/drop_caches能清掉的是前两类第三、四类它管不了。所以“内存不释放”里至少有三种完全不同的问题缓存里“可回收但不回收”、进程把内存越吃越多、内核组件泄漏。定时清理脚本能稳定解决的只有第一种后面两种需要用别的办法兜底。2.3 用一条命令判断是不是“真泄漏”以及为什么必须看趋势快速定位业务进程的内存占用ps -eo pid,ppid,rss,comm,args --sort-rss | head -n 12再配合下面这个字段判断系统“承诺”给进程的内存总量grep -E ^Committed_AS|^MemAvailable|^SUnreclaim /proc/meminfoCommitted_AS是内核对所有进程承诺过的虚拟内存量。如果它持续接近或超过物理内存总量说明进程锚定的虚拟内存太多单纯清缓存没有意义。SUnreclaim如果连续几天只增不减则要怀疑内核模块或驱动泄漏。判断动作应该是这样的先把free -h和ps打出来记一次基线隔 6 小时再看一次连续看两到三天。只有available稳定下降、SUnreclaim不大动、业务 RSS 也没有明显增长时才值得用定时drop_caches兜底。否则先解决进程本身。这个“先看趋势再动手”的习惯比任何脚本都重要。3. 定时内存回收脚本落地阈值判断、crontab 排程与参数选择确认问题属于可回收缓存积压后就可以写一个可靠的定时释放脚本。核心原则是不无脑清缓存而是等内存紧张到阈值以下才动手并且每次执行前先sync避免脏页回写风暴。3.1 先按阈值写回收脚本而不是无脑 echo 3我在生产环境里长期使用的脚本如下路径放在/usr/local/bin/kylin_mem_release.sh#!/bin/bash # 银河麒麟V10内存回收脚本仅当可用内存低于阈值时清理缓存 # 依赖 /proc/meminfo无需额外工具 MEM_TOTAL_KB$(awk /MemTotal/{print $2} /proc/meminfo) MEM_AVAILABLE_KB$(awk /MemAvailable/{print $2} /proc/meminfo) AVAILABLE_PERCENT$((MEM_AVAILABLE_KB * 100 / MEM_TOTAL_KB)) # 阈值默认 20可按业务容忍度调整单位是百分数 THRESHOLD20 echo [$(date %F %T)] before release, available${AVAILABLE_PERCENT}% /var/log/kylin_mem_release.log if [ $AVAILABLE_PERCENT -lt $THRESHOLD ]; then # 先把脏页写回磁盘避免清理时造成长时间IO停顿 sync # 1页缓存2inode/dentry缓存3两者都清 echo 3 /proc/sys/vm/drop_caches echo [$(date %F %T)] drop_caches done /var/log/kylin_mem_release.log else echo [$(date %F %T)] memory available enough, skip /var/log/kylin_mem_release.log fi逻辑说明脚本从/proc/meminfo里取MemTotal和MemAvailable计算当前可用内存百分比。只有低于THRESHOLD才执行sync和drop_caches。这样每天定时执行也不会反复清缓存避免磁盘 IO 无故抖动。参数说明THRESHOLD建议第一次设置为 20跑一周看日志再调。如果机器长期可用内存就在 10% 左右但业务正常降成 10 或 8 更合适如果业务对磁盘 IO 敏感建议设成 30让清理更早发生。echo 3是同时清页缓存和 inode 缓存如果你的主要问题是 Slab 里的SReclaimable偏高只写echo 2即可。脚本必须用 root 运行否则/proc/sys/vm/drop_caches没有写权限。3.2 把脚本放进 root 的 crontab选低峰时段麒麟 V10 自带的 cron 服务是 crond先确认它在运行systemctl status crond systemctl enable --now crond然后写入定时任务crontab -e内容为0 4 * * * /usr/local/bin/kylin_mem_release.sh /var/log/kylin_mem_release.log 21这里选了凌晨 4 点大多数业务在凌晨 2 点到 6 点访问量最低适合做这类“抢内存”的操作。如果你的业务夜间反而有批量任务就把时间改到批处理结束后的第一个小时比如上午 9 点。两个参数值得注意一个是脚本路径必须写绝对路径一个是把日志重定向追加到文件免得 cron 把输出投递给 root 邮箱造成误报。3.3 手动先跑一遍验证阈值是否合理配置完成后不要干等第二天先手动执行一次chmod x /usr/local/bin/kylin_mem_release.sh bash /usr/local/bin/kylin_mem_release.sh cat /var/log/kylin_mem_release.log free -h执行后检查两点脚本是否真的触发了清理清理前后的free -h变化是否合理。如果发现清理后available提升不大说明你的问题不在可回收缓存回到上一章的ps和SUnreclaim继续排查。如果日志里显示 available 一直在阈值以下、每次都会执行清理那就把阈值再往下调给系统留出更多缓存空间而不是让它每隔几小时就被清一次。4. 让内核“少堆积”sysctl、日志上限与业务进程的独立回收路径定时清理是治标真正让内存不堆积要从内核参数和运行环境下手。这个章节给出三个层面的调优脏页写回参数、日志上限、业务进程重启策略。三者结合定时清理脚本的工作量会小很多。4.1 调 dirty 参数降低“写缓存堆积再集中落盘”银河麒麟 V10 的内核参数承袭了 Linux 4.x/5.x 的内存管理逻辑。写文件时数据先落在 page cache 里由内核后台写回磁盘一直积到某个阈值才开始抢占式回写。默认vm.dirty_background_ratio10、vm.dirty_ratio20意味着写缓存可以占到内存的 10% 到 20%。对日志服务器、文件服务器这类持续写磁盘的机器缓存容易堆得又高又久。推荐先创建配置文件cat /etc/sysctl.d/98-memory-release.conf EOF vm.dirty_background_ratio 3 vm.dirty_ratio 10 vm.vfs_cache_pressure 200 EOF sysctl --system参数逻辑说明dirty_background_ratio3让内核在脏页达到内存 3% 就开始后台回写比默认更积极dirty_ratio10是进程写入受阻的上限压到这个值能有效避免sync时一次性回写大量脏页造成的 IO 尖峰。vfs_cache_pressure200是让内核更积极地回收 dentry/inode 缓存把SReclaimable压在更低水平。参数边界这三个值不是越小越好。dirty_background_ratio降到 1 会让磁盘写入过于频繁机械盘环境下吞吐反而下降vfs_cache_pressure超过 200 会带来额外的 CPU 开销因为缓存反复被回收又反复重建。如果机器内存很大、磁盘吞吐也不紧张保持默认即可。调整后观察一周free -h和/proc/meminfo的Dirty字段确认脏页回落速度。4.2 给 journald 日志设上限避免日志缓存把内存顶到高位银河麒麟 V10 上的系统日志默认由 systemd-journald 管理日志文件增长过快会让系统持续读指标并把大量文件数据留在 page cache 里。很多人问“银河麒麟V10系统清理日志”其实核心不是删文件而是让日志有上限、自动滚动。先看当前日志占用journalctl --disk-usage然后设置上限mkdir -p /etc/systemd/journald.conf.d cat /etc/systemd/journald.conf.d/99-size.conf EOF SystemMaxUse2G SystemMaxFileSize64M MaxRetentionSec7d EOF systemctl restart systemd-journald journalctl --vacuum-size2G参数说明SystemMaxUse2G是系统日志总计不超过 2GBSystemMaxFileSize64M是单个日志文件轮转大小MaxRetentionSec7d只保留 7 天。配置后 journald 会自动滚动旧日志你不再需要每周手动清一次。同理如果应用日志写在 /var/log 下且不滚转也要在 logrotate 里配好轮转否则读日志导致的 page cache 积压会一直存在。4.3 业务进程内存泄漏用“重启策略”定时兜底定时释放脚本对业务进程的无用内存无能为力。对于无法快速定位的进程侧泄漏常见做法是在 systemd service 里配重启策略用重启换内存复位。优先级要比定时清理高因为进程不重启清理缓存只是把压力往后推。检查当前有没有异常进程systemctl --failed journalctl -u your-service --since 7 days ago -p warning确认服务能接受重启后在 service 文件里加[Service] Restartalways RestartSec60改完后systemctl daemon-reload systemctl restart your-service注意这个策略只适合无状态或自带恢复机制的服务数据库、消息队列这类有状态服务不能随便设置Restartalways。如果服务本身写入了本地缓存文件重启后还要确认缓存是否被正确清理。5. 定时内存清理常见问题避坑5 个现象、根因与解决这部分是我的血泪经验。定时释放方案本身很简单真正的坑都藏在边界条件里每一条都按“现象 → 原因 → 解决”给出来方便直接对照排查。5.1 现象清完缓存业务比之前还卡原因drop_caches并不是零成本的。清理页缓存前必须把脏页写回磁盘如果脏页很多sync过程会把磁盘 IO 打满数据库和文件服务的请求就得排队。结果缓存是降下来了业务延迟却上去了。解决保证脚本只在低峰期执行用sync前置但不代表能完全避免尖峰更关键的是把THRESHOLD调低不要频繁触发。对数据库主机如果不是内存严重不足我一般宁可不跑清理而是优先调vm.dirty_*参数。5.2 现象脚本正常运行内存还是隔几天就没了原因脚本清掉的是可回收缓存但你不用命令确认哪些不可回收的内存。业务流程里如果有 Java 堆、Python 长驻对象或容器内共享内存这些部分持续增长清理脚本每天都跑也看不见效果。解决搭配ps -eo pid,rss,comm --sort-rss | head -10定位占用大户。如果确定是某个服务在涨优先调整它的-Xmx、连接池或缓存容量再给 systemd 配重启策略。5.3 现象明明配了 crontab定时任务却没跑原因麒麟 V10 上有几个隐蔽点crond服务没开机自启、系统时间源没同步导致“凌晨 4 点”实际在白天、脚本第一行没有#!/bin/bash或使用了crontab不认识的命令路径。这些都让任务静默失败。解决先确认systemctl status crond是 active再检查timedatectl是否打开了 NTP 同步。脚本里尽量用绝对路径把echo日志路径写清楚第二天去看日志文件是否存在。只要脚本有输出失败原因基本都能从日志里找到。5.4 现象执行 drop_caches 后/proc/meminfo 里 Slab 还是很高原因drop_caches对SUnreclaim无效。这个字段代表内核中不可回收的 slab通常是网卡驱动、存储驱动或文件系统模块在持续分配内存。反复执行清理等于对着一个内核自身的问题反复做无用功。解决记录SUnreclaim的数值如果随时间线性增长优先排查有没有异常驱动、第三方内核模块或监控 Agent。必要时重启主机让内核 slab 重新初始化比堆清理任务有力得多。5.5 现象在虚拟机里跑银河麒麟清理后宿主机内存还是被占着原因虚拟机里看到的free -h是 Guest 内的内存视角宿主机还要看 KVM/VMware 的 ballooning 是否生效。Guest 中清理缓存不等于宿主机能立刻回收内存两者之间存在一层同步。解决在虚拟机内依然可以跑这个定时脚本但要意识到它更多是避免 Guest 内部触发 OOM而不是让宿主机内存立刻释放。宿主机层面要确认 virtio-balloon 驱动已加载且虚拟机允许内存热解绑。这样清完缓存后宿主才能逐步把闲置内存收回去。6. 用 systemd timer 收尾带趋势记录的内存回收定时器crontab 能完成基本定时但漏跑、补跑和状态不可视的问题明显。最后这个技巧是把定时清理改成 systemd timer同时把每次执行前后的内存指标落成趋势文件一周后就能看出方案到底有没有用。先创建 service 单元路径/etc/systemd/system/mem-release.service[Unit] DescriptionKylin V10 memory release Afternetwork.target [Service] Typeoneshot ExecStart/usr/local/bin/kylin_mem_release.sh再创建 timer 单元/etc/systemd/system/mem-release.timer[Timer] OnCalendar*-*-* 04:00:00 Persistenttrue Unitmem-release.service [Install] WantedBytimers.target启用并查看systemctl daemon-reload systemctl enable --now mem-release.timer systemctl list-timers mem-release.timer与原脚本配套我建议把趋势记录也补进脚本末尾追加到/var/log/mem-release-trend.tsvprintf %s\t%s\t%s\n \ $(date %F %T) $MEM_TOTAL_KB $MEM_AVAILABLE_KB \ /var/log/mem-release-trend.tsv一周后用 awk 汇总看可用内存的均值、最大值和最小值awk -F \t {sum$3; if($3max) max$3; if($3min || min) min$3} END {print avg sum/NR, max max, min min} /var/log/mem-release-trend.tsv如果 min 不再跌到阈值以下说明定时清理和内核参数调整的组合已经生效。如果平均值还在缓慢下降说明问题出在业务进程侧需要回头查进程。这套方案我最早也用过 crontab但漏跑过两次后才换成 systemd timer。现在我的习惯是每个月看一眼趋势文件同时确认 timer 还挂着省心很多。希望帮到你。本文还有配套的精品资源点击获取
返回列表