接手一台运行了两年多的Ubuntu服务器,最让人头疼的场景莫过于收到磁盘空间告警。df -h 一看,根分区使用率已经飙到92%,但问题是,你根本不知道这几十G的空间到底被什么文件吃掉了。du -sh * 一层层翻找太慢,而且面对密密麻麻的目录结构,很容易遗漏那些藏在深处的“空间杀手”。这时候,ncdu 就是那个能让你在三十秒内锁定问题目录的工具。

什么是ncdu以及它为什么比du更好用

ncdu 的全称是 NCurses Disk Usage,本质上是一个基于文本用户界面的磁盘使用分析器。它底层调用的是系统调用级别的文件统计,但和传统的 du 命令相比,它提供了一个可交互的浏览界面。你不需要记住复杂的命令行参数,不需要反复执行 du 来深入子目录,所有操作都通过方向键和几个快捷键完成。更重要的是,ncdu 在扫描完成后会把整个目录树的大小关系缓存在内存里,你在不同目录之间跳转、排序时,响应速度极快,完全不需要重新扫描磁盘。对于动辄上百万个文件的服务器文件系统,这种体验优势是 du 无法比拟的。

安装ncdu:一行命令搞定

在Ubuntu上安装ncdu非常简单,官方软件源里就有。

sudo apt update
sudo apt install ncdu -y

安装完成后,直接输入 ncdu 就能启动。如果你想分析当前目录,直接运行即可;如果想分析根目录,使用 ncdu / ;如果只想分析某个特定挂载点,比如 /var,就运行 ncdu /var。需要注意的是,扫描根目录或系统关键目录时,建议使用 sudo 权限,否则很多没有读权限的目录会被跳过,导致统计结果不准确。实际运维中,最常见的用法就是 sudo ncdu / ,然后耐心等待扫描完成。根据磁盘性能和文件数量,扫描时间从几秒到几分钟不等。

扫描过程的实时反馈

启动扫描后,ncdu 会在屏幕底部显示一个进度条,包含当前正在扫描的目录路径、已扫描的文件数量和总大小。这个设计非常贴心,因为当你在排查磁盘问题时,往往希望尽快看到结果。如果某个目录卡住很久,比如 /proc 或某些挂载的远程文件系统,你可以按 q 键提前结束扫描,已经扫描完成的部分仍然可以交互浏览。对于生产环境,建议先用 --exclude 参数排除掉不需要分析的目录,比如 /proc、/sys、/dev 这些虚拟文件系统,以及你可能挂载的NFS或外部存储路径。

sudo ncdu / --exclude /proc --exclude /sys --exclude /dev --exclude /mnt/nfs

这样可以显著缩短扫描时间,避免对网络文件系统的不必要遍历。

交互界面:快速定位空间占用大户

扫描完成后,ncdu 会展示一个排序好的目录列表,默认按大小降序排列。最占空间的目录会排在最上面,旁边显示绝对大小和一个直观的百分比条形图。你只需要用上下方向键移动光标,按回车键进入子目录,按左方向键返回上级目录。这个操作逻辑和文件管理器完全一致,几乎没有学习成本。在界面中,你可以看到每个目录和文件的大小,单位会自动在K、M、G、T之间切换。如果你看到一个特别大的文件,比如几十G的日志文件,可以直接按 d 键触发删除操作,ncdu 会弹出确认提示,确认后文件就会被删除。这个功能在紧急清理空间时非常高效,但操作前务必确认文件确实可以删除。

常用快捷键:让分析效率翻倍

除了基本的浏览操作,ncdu 还提供了一系列快捷键,掌握它们能让你在分析磁盘空间时事半功倍。按 n 键可以按文件名排序,这在你想查找特定名称的大文件时很有用。按 s 键按文件大小排序,这是默认排序方式。按 C 键按项目数量排序,能帮你发现那些包含海量小文件的目录。按 M 键按最后修改时间排序,适合排查最近写入的大量数据。按 g 键可以在显示百分比、图形、百分比加图形之间切换。最实用的快捷键之一是 b 键,它会在当前目录启动一个子shell,你可以在这个shell里执行任何命令,比如 ls -lh 查看详细文件信息,或者用 rm 精确删除某些文件。退出子shell后,ncdu 会自动刷新目录信息。另一个值得记住的是 e 键,它会在当前选中的项目上打开一个shell,方便你对单个文件或目录进行操作。

导出和比较扫描结果

在实际运维中,你经常需要对比不同时间点的磁盘使用情况,或者将扫描结果保存下来供后续分析。ncdu 支持将扫描结果导出为JSON格式的文件,使用 -o 参数即可。

sudo ncdu -o /tmp/disk-scan-2025-01-15.json /

这个JSON文件包含了完整的目录结构和大小信息,可以下载到本地分析,也可以用 ncdu -f 重新加载查看。

ncdu -f /tmp/disk-scan-2025-01-15.json

这个功能在远程服务器上特别有用。你可以在服务器上执行扫描导出,然后把JSON文件复制到本地机器上,用本地的ncdu慢慢分析,完全不占用服务器的交互时间。如果你需要定期监控磁盘使用趋势,可以写一个简单的cron任务,每周执行一次扫描并保存带日期的JSON文件,当出现磁盘告警时,就能对比历史数据,快速定位是哪个目录在近期增长异常。

处理海量小文件的特殊技巧

有些场景下,磁盘空间被海量小文件占满,比如邮件服务器的邮件队列、容器镜像的层文件、或者某个应用的缓存目录。这类目录的特点是单个文件很小,但文件数量可能达到百万级别。ncdu 在处理这类目录时,扫描速度会明显下降,因为需要对每个文件执行stat调用。如果你发现扫描某个目录特别慢,可以先用 ls 或 find 命令确认一下文件数量。对于这种情况,一个有效的策略是先用 ncdu 的 --exclude 参数跳过已知的正常大目录,集中精力扫描可疑区域。另外,ncdu 在扫描时会显示当前目录的路径,如果你发现它卡在某个路径很久,可以记下这个路径,然后终止扫描,单独对这个路径运行 ncdu。这样既能节省时间,又能精准定位问题。

结合其他命令进行深度清理

ncdu 帮你找到了空间占用的罪魁祸首,但后续的清理工作往往需要结合其他命令。比如,你发现 /var/log 目录下有几个巨大的日志文件,在确认它们可以删除后,除了用 ncdu 自带的 d 键删除,更安全的做法是用 truncate 命令清空文件内容但保留文件结构,这样依赖这些日志文件的进程不会因为文件被删除而出现写入错误。

sudo truncate -s 0 /var/log/syslog.1
sudo truncate -s 0 /var/log/kern.log.1

如果你发现是某个用户的 home 目录占用了大量空间,可以用 ncdu 深入分析后,与该用户沟通清理。对于APT缓存这类系统级空间占用,ncdu 能帮你确认 /var/cache/apt/archives 的大小,然后你可以用 apt clean 命令安全清理。Docker 相关目录也是空间占用的重灾区,ncdu 可以直观展示 /var/lib/docker/overlay2 的大小,然后你可以用 docker system prune 命令清理无用的镜像和容器。

在自动化脚本中使用ncdu

虽然 ncdu 主要是一个交互式工具,但它也可以用在自动化脚本中。通过 -0 参数,ncdu 可以输出一个以null字符分隔的文件列表,适合用 xargs 处理。不过更实用的做法是利用导出功能。你可以编写一个脚本,定期扫描关键目录并导出JSON,然后写一个简单的分析程序来检查是否有目录大小超过阈值。例如,用 jq 命令解析JSON,提取出大小超过1G的目录路径。

ncdu -o - /var 2>/dev/null | jq '.[3][] | select(.asize > 1073741824) | .name'

这条命令会列出 /var 下实际占用空间超过1G的目录名称。你可以把这个逻辑集成到监控系统中,实现磁盘空间异常的自动预警。

ncdu的局限性和替代方案

ncdu 虽然强大,但也有一些局限性。它的扫描速度受限于磁盘IO性能,在机械硬盘上扫描大目录会比较慢。另外,ncdu 统计的是文件的实际占用大小,而不是磁盘分配大小,对于稀疏文件,两者可能存在较大差异。如果你的文件系统使用了硬链接,ncdu 会重复计算每个链接的大小,导致统计结果偏大。在这些特殊场景下,你可能需要结合 du 的 --apparent-size 参数或使用其他工具。另一个值得提及的替代方案是 gdu,它是用Go语言实现的类似工具,性能更高,特别适合SSD和NVMe磁盘,扫描速度通常比 ncdu 快好几倍。如果你的服务器磁盘性能很好但文件数量巨大,可以考虑安装 gdu 作为补充。

sudo apt install gdu
sudo gdu /

gdu 的使用方式和 ncdu 几乎一样,同样支持交互式浏览和快捷键操作,而且原生支持多线程扫描,能充分利用现代多核CPU的性能优势。

实战案例:一次典型的磁盘空间排查

假设你收到监控告警,根分区使用率超过90%。登录服务器后,直接执行 sudo ncdu / --exclude /proc --exclude /sys --exclude /dev,等待扫描完成。扫描结果显示 /var 目录占了总空间的45%,进入 /var 后,发现 /var/log 占了30%,其中 nginx 的 access.log 居然有12G。再进入 /var/lib,发现 /var/lib/mysql 占了10%,这是数据库的数据目录。同时 /var/lib/docker 占了5%,里面有几个旧的容器镜像。定位清楚后,你决定先处理日志文件,用 truncate 清空 access.log,然后配置 logrotate 防止再次积累。对于MySQL数据目录,这属于正常业务数据,不能随意删除,需要和开发团队确认是否有可以清理的历史数据。Docker目录则可以用 docker system prune 清理。整个排查和决策过程不超过五分钟,这就是 ncdu 带来的效率提升。

养成定期分析磁盘的习惯

磁盘空间问题往往不是突然发生的,而是日积月累的结果。将 ncdu 纳入日常运维巡检流程,每个月对服务器执行一次全盘扫描并导出结果,对比历史数据观察增长趋势,可以在问题变得严重之前就发现异常。比如某个应用开始产生大量调试日志,某个目录的缓存策略失效导致文件堆积,这些都能在定期扫描中暴露出来。运维工作的核心不是救火,而是防火,ncdu 就是你预防磁盘空间火灾的一个得力工具。