在Ubuntu服务器运维中,磁盘空间突然告警是最常见的故障之一。当你收到"No space left on device"的报错时,最快的排查方式就是用du命令逐层扫描目录占用,再配合ncdu这个交互式工具直观定位到底是哪个目录或文件吃掉了你的磁盘。简单来说:du是命令行里的瑞士军刀,适合写脚本批量排查;ncdu是带TUI界面的磁盘分析器,适合人肉交互式排查。两者搭配使用,基本能在5分钟内锁定磁盘占用大户。
为什么磁盘会被快速占满?常见原因有哪些
Ubuntu服务器磁盘爆满通常不是突然发生的,而是日积月累的结果。最常见的几个"元凶"包括:日志文件无限增长(比如/var/log下的syslog、kern.log)、Docker容器的overlay层数据堆积、APT缓存未清理、数据库binlog未设置过期策略、用户上传的临时文件忘记删除。还有一种容易被忽略的情况——某个进程在疯狂写入,比如一个失控的cron任务每分钟写一次日志,一天就能产生几个G的数据。所以排查的第一步不是盲目删文件,而是先搞清楚"谁在写、写在哪"。
du命令基础用法:从根目录开始扫描
du(disk usage)是Linux系统自带的工具,不需要额外安装。最基础的用法是指定目录路径,它会递归计算该目录下每个子目录和文件的磁盘占用。比如你想看根目录下各个一级目录占了多少空间:
sudo du -h --max-depth=1 /
这里-h表示以人类可读的格式输出(KB、MB、GB),--max-depth=1表示只显示一层深度。输出结果会按目录大小排序,你一眼就能看到/var、/home、/usr谁最大。如果你想看某个可疑目录的下一级,就把--max-depth改成2,比如:
sudo du -h --max-depth=2 /var
如果你只想看最大的前10个目录或文件,可以配合sort和head:
sudo du -h --max-depth=1 / | sort -rh | head -10
sort -rh中的-r是倒序,-h是按人类可读的数字大小排序(能正确处理1G和500M的比较)。这个组合在实际运维中非常实用,能快速给你一个"Top 10占用清单"。
du的进阶技巧:精确到文件级别和排除特定目录
有时候你知道是某个大目录的问题,但需要进一步精确到具体文件。这时候可以用du的-a参数显示所有文件:
sudo du -ah --max-depth=2 /var/log | sort -rh | head -20
但要注意,显示所有文件会非常慢,尤其是目录里文件数量多的时候。另一个实用技巧是排除某些目录,比如你知道/proc和/sys是虚拟文件系统不需要统计,可以用--exclude:
sudo du -h --max-depth=1 --exclude=/proc --exclude=/sys --exclude=/dev /
还有一个容易被忽略的参数-s(summarize),它只显示目录的总计大小而不展开子目录,适合快速确认某个路径的总占用:
sudo du -sh /var/log/*
ncdu:交互式磁盘分析神器
如果说du是手动挡,那ncdu(NCurses Disk Usage)就是自动挡。它提供了一个基于终端的图形化界面,你可以用方向键上下浏览目录,按Enter进入子目录,按d删除选中文件,按q退出。整个过程非常直观,不需要记复杂的命令参数。
安装方式很简单:
sudo apt update sudo apt install ncdu
安装完成后,直接扫描根目录:
sudo ncdu /
它会花一些时间扫描(取决于磁盘大小和文件数量),扫描完成后你会看到一个按占用大小排序的目录列表,最大的在最上面。你可以用方向键选择,按回车钻进去看细节。界面右侧会显示每个条目的大小和占比百分比,非常清晰。如果你想扫描某个特定目录而不是整个系统:
sudo ncdu /var
ncdu的高级用法:导出结果和远程分析
ncdu有一个很实用的功能是导出扫描结果,方便后续分析或发给同事。使用-o参数指定输出文件:
sudo ncdu -o /tmp/ncdu-export.json /
导出的JSON文件可以在另一台机器上用ncdu -f重新加载查看,不需要重新扫描。这在你无法直接操作生产服务器、只能拿到扫描结果文件的场景下非常有用。
另外,如果你的服务器没有图形界面,但你想在本地电脑上查看分析结果,可以把导出文件下载到本地,然后在本地终端运行ncdu -f ncdu-export.json来浏览。这种方式在远程运维中非常高效。
实战排查流程:从告警到定位的完整步骤
下面给出一个完整的实战排查流程,当你收到磁盘空间不足告警时可以按这个步骤操作:
第一步,确认磁盘整体使用情况:
df -h
这会显示每个挂载点的总空间、已用、可用和使用率。先确认是哪个分区满了,通常是/根分区或者/var单独分区。
第二步,用du快速定位大目录:
sudo du -h --max-depth=1 / | sort -rh | head -10
假设输出显示/var占了80G,那就继续深入:
sudo du -h --max-depth=2 /var | sort -rh | head -10
第三步,如果du的输出还不够直观,启动ncdu交互式分析:
sudo ncdu /var
在ncdu界面里你可以快速浏览、进入、退出,几分钟内就能锁定具体是哪个子目录或文件占用最大。常见的发现包括:/var/log下某个日志文件几十G、/var/lib/docker下容器数据膨胀、/var/cache/apt下APT缓存堆积等。
第四步,确认文件后再决定是否删除。删除前一定要确认文件是否还在被使用,比如正在写入的日志文件直接删除可能导致进程报错,正确做法是先清空内容:
sudo truncate -s 0 /var/log/syslog
或者用echo重定向清空:
sudo echo "" > /var/log/syslog
预防措施:如何避免磁盘再次被占满
定位到问题后,更重要的是建立预防机制。以下几个措施建议落实:
第一,配置日志轮转。Ubuntu默认使用logrotate,但默认配置可能不够激进。编辑/etc/logrotate.conf或/etc/logrotate.d/下的具体配置,设置合理的轮转周期和保留数量。比如:
# /etc/logrotate.d/custom
/var/log/syslog {
daily
rotate 7
compress
delaycompress
missingok
notifempty
}
第二,定期清理APT缓存:
sudo apt clean sudo apt autoremove
第三,设置Docker容器的日志驱动和大小限制。在/etc/docker/daemon.json中配置:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
第四,设置磁盘监控告警。可以用cron写一个简单的检查脚本,当使用率超过85%时发送通知:
#!/bin/bash
THRESHOLD=85
USAGE=$(df / | tail -1 | awk '{print $5}' | sed 's/%//')
if [ "$USAGE" -gt "$THRESHOLD" ]; then
echo "Disk usage is ${USAGE}%" | mail -s "Disk Alert" admin@example.com
fi
第五,考虑使用LVM或定期扩容。如果业务增长导致磁盘需求持续增加,提前规划存储扩容比临时救火要好得多。
du与ncdu的对比总结:什么场景用哪个
总结一下两者的适用场景:du适合自动化脚本、远程SSH批量检查、需要精确控制输出格式的场景;ncdu适合人工交互式排查、需要快速浏览目录结构、不想记参数的场景。在实际运维中,我个人的习惯是先用du的一行命令快速拿到Top 10,然后用ncdu钻进去看细节。两者不是替代关系,而是互补关系。掌握这两个工具,Ubuntu服务器的磁盘问题基本不会让你手忙脚乱。
最后提醒一点,无论用什么工具排查,删除文件之前一定要三思。生产环境中误删关键文件的代价远比磁盘满了更严重。养成"先确认、再操作、后验证"的习惯,才是一个成熟运维工程师的基本功。
