ARTICLE DETAIL

资讯详情

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

银河麒麟V10内存不释放?用crontab实现定时巡检与自动清理

银河麒麟V10内存不释放?用crontab实现定时巡检与自动清理 简介面向银河麒麟V10这一国产服务器操作系统的运维场景这份资源直击内存不释放内存泄漏问题为系统管理员提供了一套轻量、可定时执行的自动化解决方案。压缩包共3个文件包含2个Shell脚本和1个TXT配置说明两个脚本分别承担内存释放与定时任务调度的功能配置文件则给出环境参数说明和具体部署指引。包体仅2KB下载后即可快速查看与部署。内存泄漏长期累积会导致可用内存减少、性能下降甚至触发OOM该方案通过定时任务提前干预可有效缓解此类风险。目前已有749人学习下载。借助这套方案运维人员可通过cron定时执行内存清理脚本结合free、top等命令观察内存使用趋势并参照说明调整swappiness等内核参数在无需重启服务或系统的前提下缓解内存泄漏影响减少人工干预提升银河麒麟V10的稳定性与运维自动化水平。1. 内存不释放银河麒麟V10运维中最常见的“假故障”单位最近搬进来一批预装银河麒麟V10的服务器配置不低32G内存起步结果跑了不到两周就频繁报警内存使用率飙到95%以上页面响应变慢连SSH都卡得让人抓狂。第一反应是查进程top一看业务进程占的内存明明不高可free里可用内存就剩几百兆——典型的“内存不释放”症状。这个事在Linux系统里其实是个老熟人但放在国产化替代的语境下很多刚接触麒麟系统的运维同事会误判成系统bug或者硬件问题。我花了两天时间把这个问题从现象到原理、从应急到自动化彻底捋了一遍沉淀了一套定时解决的方案。不夸张地说这套东西在银河麒麟V10上实测有效而且改造后内存曲线稳定再也没半夜被值班电话叫起来过。这篇文章适合谁看如果你是单位里负责国产化服务器运维的或者刚接手银河麒麟V10桌面版/服务器版又恰好被内存占用高、系统越用越卡的问题折磨过那这篇能帮你少走至少三天的弯路。我会讲清楚内存为什么不释放、怎么安全地把内存“抢”回来以及最关键的一步——如何用crontab实现全自动的定时巡检和释放顺便把容易踩的坑一并交代掉。2. 先搞清楚“内存不释放”到底是哪块内存有问题2.1 用free命令看清内存的真实分布在动手释放之前必须先搞清楚内存到底去哪了。银河麒麟V10虽然是国产系统但底层依然是Linux内核所以排查思路和CentOS、Ubuntu完全通用。第一件事先跑free -h看整体水位。我遇到的情况是下面这种$ free -h total used free shared buff/cache available Mem: 31G 25G 1.2G 236M 5.6G 5.1G Mem: 31G 9.3G 1.5G 236M 20G 21Gtop里看业务进程加起来也就8G多但used那一栏却标了25Gfree只有1.2G。这时候别急着杀进程要想一下Linux内核会尽量把空闲内存用作page cache页缓存用来缓存磁盘文件和数据这样下次读文件就不用等慢吞吞的磁盘了。所以buff/cache高是好事不是坏事真正让系统卡的是“可用内存available”被压得太低。第一行available只有5.1G说明内存确实吃紧。再看第二行我把cache清了一部分之后buff/cache从20G降到了5.6Gavailable从5.1G回升到21G。这一对比就直观了内存不是被业务吃掉的是被页缓存和文件缓存占用的。这类缓存内核自己是会按需回收的但某些场景下——比如频繁读写大文件、数据库导入导出、资料备份——回收不及时剩余内存就会被压到红线触发OOM甚至系统假死。2.2 为什么银河麒麟V10上“不释放”的现象更明显有些同事反馈同样一套业务在CentOS 7上跑得好好的搬到麒麟V10上就内存报警。这里除了心理作用确实有点客观原因。银河麒麟V10的桌面版默认开启了比较多的图形服务和桌面组件UI进程、文件索引、日志审计这些都常驻内存服务器版相对干净一些但常见的监控代理、安全模块也会增加常驻进程数量。另一方面和系统本身关系不大更多是部署在上面的国产化应用栈的问题。很多单位是在麒麟上跑国产数据库达梦、人大金仓、Java中间件东方通TongWeb、或者自研业务这些应用的开发时对内存管理并不精细长时间运行会产生一些内核无法及时回收的“内存碎片”和不可回收缓存。叠加之下q前系统的available内存就很容易见底。所以我的看法是不要把这个当系统缺陷去“修”而是当运维策略去“管”。管理手段的核心就两条——一条是合理控制可回收的cache水位另一条是尽早发现问题进程别让内存涨到OOM才去救火。3. 应急方案手动释放内存的三种层级3.1 从sync到drop_caches各参数区别要搞清先给出一套应急用的一行命令组合这条命令也是后续定时脚本的基础sync; echo 3 /proc/sys/vm/drop_cachessync的作用是把内存中尚未写回磁盘的脏数据强制落盘确保数据安全之后再清缓存。drop_caches支持三个值1表示释放page cache页缓存2表示释放dentries和inodes目录项和索引节点缓存3表示全部释放。想理解这个机制可以把内存想象成一张办公桌文件缓存就是摊在桌上的图纸归档就是dentries/inodes这类台账桌上图纸太多新任务没法操作时就得先把图纸放回文件柜sync落盘再清理桌面drop_caches。实际维护中我用echo 3的情况最多因为清得最干净整套组合对业务进程本身没有影响它只回收内核可回收的那部分应用占用的内存不会被清掉。这里要特别提醒drop_caches只是清缓存不是杀进程所以不需要担心业务数据丢失。但docker容器场景下要注意容器内执行echo 3只对宿主机全局的cache生效效果取决于宿主机是否允许容器写procfs一般建议在宿主机上执行不要进容器里折腾。3.2 更温和的手段调整vm.vfs_cache_pressure如果生产环境比较敏感不希望频繁大范围清缓存可以尝试调优内核参数sysctl -w vm.vfs_cache_pressure200vfs_cache_pressure这个参数控制内核回收目录项和索引节点缓存的激进程度默认值是100数值越大回收越积极。调到200意味着当内存紧张时内核会更积极地回收这部分缓存而不是等到头破血流才动手。适合那种“不想脚本老介入让系统自己勤快点”的场景。但这个参数不是万能的它只管目录项和inode缓存page cache还是要靠上面的drop_caches。我的经验是vfs_cache_pressure适合设置成100-200之间的一个值长期生效drop_caches则作为应急和定时兜底两者配合使用。3.3 应急手动操作时的顺序和注意点手动释放内存的推荐顺序是先top或ps看一遍有没有内存特别异常的进程有的话优先处理进程问题进程泄漏靠清cache是治不好的。做一次sync确保脏数据落盘。执行echo 3 /proc/sys/vm/drop_caches。用free -h验证available是否回升。观察业务是否正常如果有数据库实例在跑观察慢查询是否增多。顺序很重要尤其第1步不能省。我见过有的同事上来就echo 3结果内存照样爆——因为根本原因是Java堆泄漏清cache是扬汤止沸。先定位是不是cache占大头再考虑清理这是个好习惯能省不少排查时间。4. 定时自动释放给内存加一个“值班保洁”4.1 方案思路为什么不能简单写一条crontab手动清理有了但服务器不会挑你有空的时候出问题。凌晨两三点内存爆掉等早上来上班再看就晚了。所以必须上定时任务。注意没有人建议你每5分钟清一次cache那样太激进会严重拉低缓存命中率反而影响磁盘I/O性能。正确思路是“低频率巡检阈值触发”平时不动只有当内存水位越过红线时才出手。我这边最终落地的策略如下每5分钟执行一次巡检脚本脚本读取当前内存数据和swap使用情况当available内存低于总内存的10%或者swap使用率超过50%时才触发缓存清理清理后写入日志方便事后查看。这样既不会频繁打扰系统又能保证内存水位不会破线。4.2 完整巡检与自动释放脚本可直接抄下面是我在银河麒麟V10上实测过的脚本保存为 /usr/local/bin/mem_guard.sh#!/bin/bash # 内存巡检与自动释放脚本 # 适用系统银河麒麟 V10x86_64 / aarch64 # 建议crontab周期*/5 * * * * # 配置阈值单位百分比整数 AVAILABLE_WARN10 SWAP_WARN50 # 日志路径 LOG_FILE/var/log/mem_guard.log # 当前可用内存百分比和swap使用百分比 read available_total available used \ (free -m | awk NR2{print $2,$3,$7}) # free -m 中 available 字段在第7列老版本free可能没有该列需评估 # 更稳健的写法 mem_info$(free -m) total_mem$(echo $mem_info | awk NR2{print $2}) avail_mem$(echo $mem_info | awk NR2{print $NF}) swap_total$(echo $mem_info | awk NR3{print $2}) swap_used$(echo $mem_info | awk NR3{print $3}) if [ -z $avail_mem ] || [ $total_mem -le 0 ]; then echo $(date %F %T) [ERROR] get memory info failed $LOG_FILE exit 1 fi avail_percent$((avail_mem * 100 / total_mem)) # 如果swap总数为0把swap使用率置为0避免除零错误 if [ $swap_total -le 0 ]; then swap_percent0 else swap_percent$((swap_used * 100 / swap_total)) fi echo $(date %F %T) [INFO] total${total_mem}MB avail${avail_mem}MB avail_percent${avail_percent}% swap_percent${swap_percent}% $LOG_FILE # 判定是否触发清理 if [ $avail_percent -lt $AVAILABLE_WARN ] || [ $swap_percent -gt $SWAP_WARN ]; then echo $(date %F %T) [TRIGGER] available below ${AVAILABLE_WARN}% or swap above ${SWAP_WARN}%, start reclaiming cache... $LOG_FILE sync echo 3 /proc/sys/vm/drop_caches # 如果系统支持同步回收内存碎片 echo 1 /proc/sys/vm/compact_memory 2/dev/null sleep 2 free -h $LOG_FILE echo $(date %F %T) [DONE] cache reclaimed. $LOG_FILE else echo $(date %F %T) [INFO] memory status ok, skip. $LOG_FILE fi这个脚本有几个细节值得单独说明。第一free命令在procps-ng 3.3.10及以后的版本才输出available列银河麒麟V10的free是支持这列的但为了兼容老系统我用NR2{print $NF}取最后一列的方式更稳健。第二脚本里加了一个sysctl接口的compact_memory操作这是触达内核做内存碎片整理的在清理大缓存后执行一次有助于缓解内存碎片化实测在长时间运行的大内存机器上效果明显。第三日志记录是必须的否则定时任务跑没跑、何时触发、当时内存水位是多少全无追溯出问题很难查。路径和权限方面脚本要赋予执行权限并设置crontabchmod x /usr/local/bin/mem_guard.sh crontab -e # 写入以下行 */5 * * * * /usr/local/bin/mem_guard.sh4.3 配置前必看的两个注意事项含数据库场景脚本可以抄但落地前想清楚两件事。第一如果这台服务器上跑着数据库达梦、MySQL、PostgreSQL等清cache要谨慎。数据库通常有自己的buffer pool缓冲池它读过的数据页在内存里是“私有缓存”drop_caches这个命令动不了它。但数据库对性能的敏感度很高清理page cache会让它的磁盘读放大——有些冷数据本来在缓存里能直接返回被清掉后就得重新走磁盘。所以我给跑库的机器设的阈值更保守AVIABLE_WARN调成5%而不是10%宁可少触发也不能因为频繁清理让业务出现性能抖动。如果是金融、生产核心系统建议干脆只用vfs_cache_pressure调优别上自动清理脚本。第二是权限问题。crontab里的脚本以root身份执行echo 3 /proc/sys/vm/drop_caches才能成功。如果服务器上用了sudo白名单机制要确保这个命令不被安全策略拦截否则定时任务会静默失败日志里只留下INFO行却没有TRIGGER行排查时容易被误导。我在银河麒麟V10上还遇到过SELinux或安全模块放行问题表现为手敲命令有效但定时任务无效这时候可以用ausearch -m avc -ts recent检查一下是不是被安全策略拦了。5. 更稳的长期方案再往前走两步5.1 减少Swap使用优先保业务响应先把swap水位纳入巡检指标是有原因的。银河麒麟V10在内存不足时同样会启用swap但如果swap分区本身不够大或者系统已经大量使用swap说明内存是真的不够了清cache只能救急不能治病。我的经验是swap使用率一旦稳定超过50%就要认真考虑扩内存或者把swap分区调大否则OOM Killer迟早会随机挑进程“祭天”。从运维角度看建议把swappiness调低让系统优先使用物理内存避免不必要的换页。编辑 /etc/sysctl.confvm.swappiness10 sysctl -p对桌面应用比较多的银河麒麟V10swappiness调低后明显感觉应用切换更跟手因为进程不被频繁换到磁盘上了。5.2 定位内存大户这五分钟的巡检别浪费定时脚本里有一个附加动作值得做——记录当前内存消耗前5的进程。这样每次巡检完后就算没有触发清理事后也能复盘到底是谁在慢慢吃内存。脚本加一行ps aux --sort-%mem | head -6 $LOG_FILE长期积累这份日志后就能看出规律某个Java服务每天早上九点内存涨一波某个备份脚本每周日凌晨吃满内存等。有了数据支撑后续无论是调JVM参数还是改调度时间都更有依据不用靠猜。提到这我想起一个真实案例。有台麒麟V10的服务器日志里显示内存占用每天涨一点但清cache效果不大。靠上面的ps输出查到是个国产化的文档转换服务启了多线程但内存池没回收机制后来直接给它的启动脚本加了一个周期性的强制GC参数问题解决。没有日志支撑这个问题定位起来相当费劲。5.3 监控与告警别等内存爆了才知道定时清理是防守告警是预警两层配合才能把事故消灭在早期。最简单的方案是在巡检脚本里加一行if [ $avail_percent -lt 5 ]; then echo $(date %F %T) [CRITICAL] memory critically low, please check! $LOG_FILE # 可选curl 一个webhook地址走企业微信/钉钉机器人 fi说实话我自己在单位的做法是给核心节点接了一个简单的webhook告警内存水位红线的时候推送一条消息到手机上这样就可以在业务卡顿之前干预。到了这一步银河麒麟V10的内存治理才算闭环巡检兜底、阈值清理、告警通知、日志复盘四个环节一个不缺。6. 常见问题与排查技巧实录6.1 定时任务没生效命令明明没问题排查的时候先看crontab有没有写对crontab -l grep CRON /var/log/cron检查脚本是否有可执行权限以及脚本里是否用了完整路径。crontab的环境变量和终端登录shell不一致是常见坑比如PATH里没有/usr/local/bin或者脚本里用了相对路径导致找不到文件。银河麒麟V10的cron日志默认在/var/log/cron脚本自己的日志在/var/log/mem_guard.log两头对着看一般情况下十分钟内能定位问题。另外提醒一下如果systemctl status crond发现定时服务没启动那一切都白搭先把crond服务拉起来再谈其他。6.2 清理后内存立刻又满这个问题出现得很频繁原因通常是业务进程内存本身有泄漏清掉的cache只是杯水车薪。快速判断方法是清完cache后过五分钟再free -h如果buff/cache重新涨到很高但available依然很低说明是cache在持续增长——那就看看有没有程序在做大量文件读写如果used直接持续增长那就去看进程八成是内存泄漏。再用top按内存排序找出占比异常的进程用ps -o pid,ppid,rss,vsz,cmd -p PID查看它的内存明细或者用pmap -x PID看具体映射。6.3 手动执行脚本能清定时执行却报权限错误这个基本可以断定是被系统安全机制拦了。银河麒麟V10的一些服务器版本默认带安全加固模块如kysec对procfs的写入权限有限制。验证方式很简单手动执行脚本前先运行id确认是root然后查看/var/log/mem_guard.log和/var/log/audit目录有没有拒绝记录。如果有ace记录就要到安全策略里把drop_caches和compact_memory这两个操作的权限放行。这一步各单位的策略配置不太一样具体界面就不展开了但思路一致。6.4 释放cache后业务卡顿变严重了这种情况在跑数据库的机器上更容易遇到。前面说了清理page cache之后缓存的命中率会暂时下降业务冷读就要等磁盘延迟自然上升。解决思路不是放弃清理而是调整阈值让系统在更高的可用内存水位之下才触发清理。比如正常机子是10%触发数据库机子设成5%甚至3%同时把清理参数从3改成1只清page cache不清dentries/inodes这样既保留了文件索引的加速又释放了大部分缓冲空间。7. 最后一点实际体会银河麒麟V10内存不释放这个问题技术上不算难难在两点一是不少人把它当成玄学一遇到内存高就重启服务器其实绝大多数情况根本不需要二是缺少一套自动化的治理机制出了问题靠人盯永远被动。我上面给的巡检脚本和配套思路在x86架构和ARM架构的麒麟V10上都跑过稳定运行了三个多月日志里再也没有连续多天内存见底的情况。把这个方案内化成一套运维习惯比单纯解决一个bug更有价值——下次无论遇到什么国产系统的性能问题第一反应都能从容面对先看数据再做决策最后上自动化。本文还有配套的精品资源点击获取
返回列表