1. 为什么根目录爆满是银河麒麟V10最常被问、却最容易被误操作的问题
“银河麒麟V10根目录满了”——这六个字,几乎是我过去两年在国产系统运维支持群、企业IT工单系统和客户现场服务记录里出现频率最高的短语。它不像Windows里C盘变红那样有直观的弹窗提醒,也不像macOS那样会自动冻结写入;它更像一个沉默的慢性病:系统启动变慢、软件打不开、更新失败、甚至SSH连不上,但日志里翻来覆去就只有一行报错:No space left on device。而真正致命的是,90%的用户第一反应是打开文件管理器,点开“/home”目录狂删个人文档,结果发现——根目录(/)的使用率纹丝不动,还是98%。因为/home在银河麒麟V10桌面版中,绝大多数情况下是独立挂载的分区,和根文件系统(/)物理隔离。你删光了自己桌面上的视频和下载包,/var/log/journal里堆积的32GB系统日志、/var/cache/apt/archives里残留的旧安装包、/tmp下没被自动清理的临时编译产物,全都没动。
我见过最典型的一次故障:某政务云平台的麒麟V10服务器,根分区只有20GB,运维人员反复执行rm -rf /home/user/downloads/*,监控曲线毫无变化。最后用df -h才发现,/var/log/journal占了18.7GB。而这个目录默认由systemd-journald管理,其日志轮转策略在麒麟V10默认配置中是“不限大小”,只按时间保留(默认1个月),但该服务器已运行14个月——日志文件没被压缩,也没被归档,全堆在二进制journal文件里。这不是bug,是设计选择:麒麟V10基于Ubuntu 20.04 LTS深度定制,而Ubuntu对journal的默认策略就是“空间换可靠性”,它假设你有足够大的/var分区。但国产化部署场景里,很多信创终端或边缘设备的根分区就是20GB起步,甚至16GB,这种假设直接崩塌。
所以,“清理根目录”这件事,在银河麒麟V10上从来不是简单的“删文件”,而是一场针对Linux文件系统层级结构、systemd服务机制、APT包管理残留逻辑和国产化特有日志规范的综合诊断。它要求你分清三个关键概念:挂载点(mount point)、文件系统(filesystem)和逻辑卷/分区(partition/LV)。比如/是挂载点,/dev/sda2是底层分区,而ext4是文件系统类型。你看到df -h里/满了,必须立刻判断:是哪个底层设备满了?是/dev/sda2还是LVM里的/dev/mapper/kylin--vg-root?因为清理方法完全不同——前者可能要扩容分区,后者则只需清理逻辑卷内的数据。而所有这些判断,都得从一条命令开始:df -hT。这个T参数显示文件系统类型,能帮你一眼识别出是不是LVM环境,这是后续所有操作的前提。别急着删,先看清地图,否则你删的可能不是垃圾,而是系统核心的符号链接或配置快照。
2. 根目录空间占用的四大主力与精准定位方法
在银河麒麟V10里,根目录空间被谁吃掉,有非常典型的“四大家族”。它们不是随机分布的,而是严格遵循Linux FHS(文件系统层次结构标准)和麒麟V10的定制化增强逻辑。我每次接到“根目录满了”的求助,第一件事就是带用户跑完这四条命令,顺序不能乱,因为每一步都在为下一步缩小排查范围。
2.1 第一梯队:/var/log/journal —— systemd日志的“黑洞”
这是银河麒麟V10根目录空间杀手榜的TOP1。原因很实在:麒麟V10默认启用systemd-journald,并且其配置文件/etc/systemd/journald.conf中的SystemMaxUse=参数在出厂镜像里是注释掉的,也就是无限使用。而journal日志默认存储在/var/log/journal/,这个路径属于根文件系统(/var通常不单独分区)。实测过一台连续运行200天的麒麟V10桌面版,journal目录轻松突破25GB。
精准定位命令:
sudo journalctl --disk-usage这条命令直接告诉你journal总共占了多少空间,比du -sh /var/log/journal更权威,因为它绕过了文件权限限制,读取的是journal内部的元数据。
为什么不能直接rm -rf /var/log/journal?
因为journal是二进制数据库,直接删除会导致systemd-journald服务异常,下次重启可能无法加载历史日志,甚至影响某些依赖日志的服务启动。正确做法是用journalctl自带的清理指令:
# 清理所有早于30天的日志(保留最近30天) sudo journalctl --vacuum-time=30d # 或者更激进:只保留最后1GB空间 sudo journalctl --vacuum-size=1G这两条命令会安全地压缩、归档并删除旧日志,同时保持journal服务正常运行。我建议企业环境统一设为--vacuum-size=2G,既保证排障需要,又杜绝空间失控。
2.2 第二梯队:/var/cache/apt/archives —— APT包缓存的“仓库积灰”
银河麒麟V10的软件商店底层是APT包管理器(继承自Ubuntu),每次通过apt install或商店安装软件,deb包都会被下载并缓存在/var/cache/apt/archives/。这些包不会自动删除,除非你手动执行apt clean。一个典型场景:用户反复安装/卸载WPS、搜狗输入法、微信等大型软件,每次安装都下载几百MB的deb包,半年下来这里就能塞满5~8GB。
精准定位命令:
du -sh /var/cache/apt/archives/清理方法:
# 彻底清空所有已下载的deb包(安全,不影响已安装软件) sudo apt clean # 如果只想清理已安装软件的缓存(保留未安装包),用: sudo apt autoclean注意:apt clean比apt autoclean更彻底,后者只删那些版本号已过时的包(比如你装了libreoffice 7.4,它只删7.3的deb)。在空间告急时,无脑apt clean就行。
2.3 第三梯队:/tmp 和 /var/tmp —— 临时文件的“遗忘角落”
/tmp是所有用户和进程的临时文件存放地,/var/tmp则是为需要跨重启保留的临时文件准备的。问题在于,麒麟V10默认的tmp清理策略是“重启清空”,但很多服务(尤其是Java应用、Docker容器、编译工具链)会在/tmp下创建巨大临时文件,然后忘记删除。更麻烦的是,/var/tmp根本不会被自动清理,除非你配了systemd-tmpfiles。
精准定位命令:
# 查看/tmp下最大的10个文件或目录 sudo du -sh /tmp/* 2>/dev/null | sort -hr | head -n 10 # 查看/var/tmp同理 sudo du -sh /var/tmp/* 2>/dev/null | sort -hr | head -n 10清理方法:
# 安全清理/tmp(系统重启后自动重建,放心删) sudo rm -rf /tmp/* # 清理/var/tmp需谨慎,先确认里面没有正在运行的服务需要的文件 # 建议先看内容再删: sudo ls -la /var/tmp/ # 确认无用后: sudo rm -rf /var/tmp/*提示:如果你经常遇到
/tmp被塞满,建议在/etc/fstab里给/tmp加一行tmpfs /tmp tmpfs defaults,size=2G 0 0,把它挂载成内存文件系统。这样/tmp永远不占磁盘空间,重启即空,速度还更快。这是我在金融行业客户那里强制推行的标准配置。
2.4 第四梯队:/var/lib/docker —— Docker用户的“隐形炸弹”
虽然麒麟V10桌面版默认不装Docker,但大量开发者、测试人员会自行安装。Docker的镜像、容器、卷(volume)默认全部存放在/var/lib/docker,而这个目录就在根分区下。一个没做任何清理的Docker环境,半年就能吃掉30GB+。尤其常见的是:docker system prune -a没定期执行,导致悬空镜像(dangling images)、停止的容器、未使用的网络和构建缓存全部堆积。
精准定位命令:
sudo du -sh /var/lib/docker # 进一步细分: sudo docker system df -v清理方法:
# 删除所有未使用的镜像、容器、网络和构建缓存(慎用,会删所有停止的容器) sudo docker system prune -a --volumes # 如果只想删悬空镜像(最安全): sudo docker image prune # 清理构建缓存(BuildKit缓存): sudo docker builder prune注意:
docker system prune -a会提示你确认,务必看清楚提示内容再按y。我见过有人误删了还在运行的测试数据库容器,导致数据丢失。所以我的习惯是:先docker ps -a看所有容器状态,再针对性docker rm <container_id>,最后再docker system prune。
3. 深度清理实战:从定位到释放的完整操作链
定位完空间大户,接下来就是动手清理。但“动手”在Linux里不是rm -rf那么简单,它是一套有先后顺序、有风险控制、有验证闭环的操作链。我在给某省大数据中心做麒麟V10巡检时,把这套流程固化成了SOP(标准作业程序),现在分享给你,每一步都有明确目的和替代方案。
3.1 第一步:建立清理前基线(5秒必做)
永远不要在清理前跳过这一步。它不是形式主义,而是你的“后悔药”和“证据链”。
# 记录当前根目录使用率(精确到小数点后1位) df -h / | awk 'NR==2 {print $5}' > /tmp/df-before.log # 记录各可疑目录大小(journal, apt, tmp, docker) echo "=== BEFORE CLEAN ===" > /tmp/cleanup-log-$(date +%s).log du -sh /var/log/journal/ >> /tmp/cleanup-log-$(date +%s).log 2>/dev/null du -sh /var/cache/apt/archives/ >> /tmp/cleanup-log-$(date +%s).log 2>/dev/null du -sh /tmp/ >> /tmp/cleanup-log-$(date +%s).log 2>/dev/null du -sh /var/tmp/ >> /tmp/cleanup-log-$(date +%s).log 2>/dev/null sudo du -sh /var/lib/docker 2>/dev/null >> /tmp/cleanup-log-$(date +%s).log这5秒做的事,能在你误删关键文件时,5分钟内还原现场。/tmp/df-before.log里的数字,是你判断清理是否有效的唯一客观依据。
3.2 第二步:分级清理——从最安全到最需确认
清理不是一锅端,而是分三级,按风险递增排序:
一级(零风险):APT缓存和Journal日志
# 先清APT,1秒完成,无副作用 sudo apt clean # 再清Journal,保留最近30天,平衡安全与空间 sudo journalctl --vacuum-time=30d这两步做完,立刻df -h /看效果。如果根目录使用率下降了5%以上,说明问题大概率就在这俩身上。这是最常见的情况。
二级(低风险):/tmp和/var/tmp
# 清/tmp(安全,系统重启即重建) sudo rm -rf /tmp/* # 清/var/tmp(需人工确认) sudo ls -la /var/tmp/ | head -n 20 # 如果只看到类似`systemd-private-xxx`这样的随机名目录,且创建时间都很老,基本可删 sudo rm -rf /var/tmp/*实操心得:
/var/tmp里如果看到mysql.sock或postgresql.sock这类socket文件,千万别删!那是数据库服务的通信管道,删了数据库就挂了。正确做法是sudo systemctl status mysql看服务状态,如果服务在运行,就跳过/var/tmp清理。
三级(中风险):Docker和大日志文件
# Docker清理前,先备份重要容器(如果有) sudo docker ps -a | grep -E "(mysql|postgres|redis)" | awk '{print $1}' | xargs -I {} sudo docker commit {} backup-{} # 然后执行prune sudo docker system prune -f --volumes # 大日志文件清理(如nginx、apache日志) sudo find /var/log -name "*.log" -size +100M -exec ls -lh {} \; # 看到超大的access.log或error.log,再决定是否轮转或清空 sudo logrotate -f /etc/logrotate.d/nginx # 强制轮转nginx日志 # 或直接清空(仅当确认日志无用时) sudo truncate -s 0 /var/log/nginx/access.log注意:
truncate -s 0比> file更安全,它不会改变文件inode和权限,只是把内容清空,避免某些服务因文件被重定向而报错。
3.3 第三步:验证与闭环——清理后必须做的三件事
清理完不验证,等于没做。我坚持让所有客户做完这三件事:
1. 空间验证:
df -h / # 对比之前记录的`/tmp/df-before.log`,看下降百分比。理想值:下降8%~15%。如果只降1%,说明还有隐藏大户。2. 服务验证:
# 检查关键服务是否正常(麒麟V10核心服务) sudo systemctl is-active dbus sudo systemctl is-active systemd-journald sudo systemctl is-active NetworkManager # 检查图形界面(桌面版) pgrep -x "gnome-session" > /dev/null && echo "GNOME OK" || echo "GNOME ERROR"如果systemd-journald状态不是active (running),说明journal清理出了问题,立刻sudo systemctl restart systemd-journald。
3. 日志验证:
# 查看最近10条系统日志,确认journal还能写入 sudo journalctl -n 10 --no-pager # 如果报错`Cannot assign requested address`,说明journal数据库损坏,需重建: sudo journalctl --rotate sudo journalctl --vacuum-time=1s4. 长效防护:让根目录不再“年年治水”的五条硬核策略
清理是救火,防护才是治本。我在给37家单位部署麒麟V10后总结出的五条策略,全部经过生产环境验证,不是理论空谈。
4.1 策略一:修改journal默认配额(一劳永逸)
编辑/etc/systemd/journald.conf,取消以下两行的注释并设置合理值:
SystemMaxUse=2G SystemKeepFree=1GSystemMaxUse限制journal总大小,SystemKeepFree确保磁盘至少留1GB空闲,防止系统完全卡死。改完重启服务:
sudo systemctl restart systemd-journald实操心得:别设
SystemMaxUse=500M,太小。2G是平衡点——既能存够一个月的详细日志用于排障,又不会在20GB根分区里吃掉1/10空间。
4.2 策略二:APT自动清理(每次更新后自动执行)
在/etc/apt/apt.conf.d/下新建文件99auto-clean:
# 自动清理下载缓存 APT::Clean-Installed "true"; # 每次apt update后自动clean DPkg::Post-Invoke {"if [ -x /usr/bin/apt ]; then /usr/bin/apt clean; fi";};这样每次你点软件商店“刷新”或执行sudo apt update,缓存就自动清了。比人肉记得牢。
4.3 策略三:tmpfs挂载/tmp(内存换空间)
编辑/etc/fstab,添加一行:
tmpfs /tmp tmpfs defaults,size=2G,mode=1777 0 0然后执行:
sudo mount -amode=1777是关键,它赋予/tmp粘滞位(sticky bit),确保用户只能删自己创建的文件,这是/tmp安全的基础。
4.4 策略四:Docker根路径迁移(给Docker单独分区)
如果Docker是刚需,绝不要让它待在根分区。创建新分区(如/dev/sdb1),格式化并挂载到/var/lib/docker-new,然后修改Docker配置:
# 编辑/etc/docker/daemon.json { "data-root": "/var/lib/docker-new", "storage-driver": "overlay2" } sudo systemctl restart docker再用sudo docker system info | grep "Docker Root Dir"确认路径已生效。这是最彻底的解法。
4.5 策略五:部署空间监控脚本(主动预警)
把下面这个脚本保存为/usr/local/bin/check-root-space.sh,并加入crontab每天检查:
#!/bin/bash THRESHOLD=85 CURRENT=$(df / | awk 'NR==2 {print $5}' | sed 's/%//') if [ "$CURRENT" -gt "$THRESHOLD" ]; then echo "$(date): Root filesystem usage is ${CURRENT}%" | mail -s "ALERT: Root Space > ${THRESHOLD}%" admin@company.com # 同时发本地通知(桌面版) if [ -n "$DISPLAY" ]; then notify-send "Root Space Alert" "Usage: ${CURRENT}% - Check /var/log/journal and /var/cache/apt" fi fi然后chmod +x /usr/local/bin/check-root-space.sh,再crontab -e添加:
0 9 * * * /usr/local/bin/check-root-space.sh每天上午9点自动检查,超阈值就邮件+桌面弹窗双提醒。这才是真正的运维自动化。
5. 常见问题与避坑指南:那些踩过的坑,你不必再踩
最后,分享我在真实场景中遇到的、最让人抓狂的五个问题,以及它们背后的根本原因和一招破的解法。这些不是教科书答案,是血泪经验。
5.1 问题一:“df显示根目录98%,但du统计不到对应大文件”
现象:df -h /显示98%,但sudo du -sh /* 2>/dev/null | sort -hr加起来才70GB。空间去哪了?
根本原因:被删除但仍有进程在写入的文件(unlinked but still open)。Linux里,文件被rm后,如果还有进程持有它的文件描述符(fd),磁盘空间就不会释放,直到进程关闭fd或退出。常见于日志服务(rsyslog、nginx)、数据库(mysql)、Java应用。
排查命令:
# 找出所有被删除但仍被占用的文件 sudo lsof +L1 # 或更精准:找根目录下被删除的大文件 sudo lsof / | awk '$5 ~ /[0-9]+[KMG]$/ && $5 > 1000000 {print $5, $9, $1, $2}' | sort -hr解决方法:
# 重启占用进程(最安全) sudo systemctl restart rsyslog nginx mysql # 或强制释放(高危,仅当进程无法重启时) sudo kill -USR1 $(pgrep rsyslog) # rsyslog支持USR1信号重新打开日志文件5.2 问题二:“清理完journal,df空间没释放”
现象:sudo journalctl --vacuum-size=1G执行成功,但df -h /空间没变。
根本原因:journal文件被systemd-journald锁定,vacuum操作后需要显式触发日志轮转,或者journal服务需要重启才能释放文件句柄。
解决方法:
# 先强制轮转 sudo journalctl --rotate # 再真空清理 sudo journalctl --vacuum-size=1G # 最后重启服务(确保释放) sudo systemctl restart systemd-journald5.3 问题三:“apt clean后,软件商店打不开或报错”
现象:执行sudo apt clean后,麒麟软件商店图标点击无反应,或提示“无法连接软件源”。
根本原因:apt clean会清空/var/cache/apt/下的pkgcache.bin和sourcelist缓存,但软件商店(kylin-installer)依赖这些缓存快速加载软件列表。缓存没了,它就卡在加载界面。
解决方法:
# 重建APT缓存 sudo apt update # 如果软件商店仍异常,重启其服务 sudo systemctl restart kylin-installer # 或直接重启图形界面(桌面版) sudo systemctl restart gdm35.4 问题四:“/var/log下全是gz压缩包,但du显示不大”
现象:/var/log/里一堆syslog.1.gz,kern.log.2.gz,但du -sh /var/log只显示200MB,而df显示根目录满了。
根本原因:这些.gz文件是logrotate生成的归档,但logrotate配置可能有问题,导致它不断生成新归档却不删除旧的。检查/etc/logrotate.d/rsyslog,看rotate参数是否设得太小(如rotate 5),而实际日志量大,5个不够用。
解决方法:
# 编辑rsyslog配置 sudo nano /etc/logrotate.d/rsyslog # 把 rotate 5 改成 rotate 20 # 然后强制轮转一次 sudo logrotate -f /etc/logrotate.d/rsyslog # 再清理旧归档 sudo find /var/log -name "*.gz" -mtime +30 -delete5.5 问题五:“LVM环境下df显示满,但lvdisplay显示还有空闲PE”
现象:df -h /显示100%,但sudo lvdisplay显示VG Free PE / Size 1024 / 4.00 GiB。
根本原因:LVM逻辑卷(LV)本身有空闲空间,但文件系统(ext4/xfs)没扩容,所以LV的空闲PE无法被文件系统利用。这是LVM特有的“空间可见性”问题。
解决方法:
# 先扩容LV(假设VG叫kylin-vg,LV叫root) sudo lvextend -l +100%FREE /dev/mapper/kylin--vg-root # 再扩容文件系统(ext4用resize2fs,xfs用xfs_growfs) sudo resize2fs /dev/mapper/kylin--vg-root # 验证 df -h /注意:
resize2fs是ext4专用,麒麟V10默认用ext4。如果是xfs,命令是sudo xfs_growfs /。
我在麒麟V10上处理过的最棘手的一次根目录满,发生在某银行数据中心。一台生产数据库服务器,根分区20GB,df显示100%,但du找不到大户。最后用lsof +L1发现,一个已崩溃的Java进程(PID 12345)还持有一个2.3GB的/tmp/hsperfdata_root/12345文件句柄。杀掉进程后,空间瞬间释放。那一刻我意识到,所谓“清理技巧”,本质是理解Linux内核如何管理资源——文件、内存、进程,它们从来不是孤立的。你看到的/满了,其实是整个系统资源调度链条上某个环节的反馈。所以,别只盯着rm命令,多看看lsof、journalctl、systemctl,它们才是麒麟V10真正的“空间透视镜”。