1. 为什么需要统计文件大小?
在Linux系统管理中,了解文件和目录的实际磁盘占用情况是一项基础但至关重要的任务。想象一下这样的场景:你的服务器突然报警磁盘空间不足,但通过df -h查看发现根目录使用率已达95%。此时你需要快速定位是哪些文件占用了大量空间,是日志文件膨胀了?还是某个应用程序产生了异常大的临时文件?这时du命令就是你的第一响应工具。
与ls -l显示的文件"逻辑大小"不同,du(disk usage)命令统计的是文件在磁盘上实际占用的"物理空间"。这两个数值的差异主要来自两个方面:首先,文件系统通常按块分配空间(默认4KB),一个1字节的文件也会占用整个块;其次,稀疏文件、硬链接等特殊文件类型也会影响实际空间占用。例如:
$ ls -l bigfile.txt -rw-r--r-- 1 user group 1073741824 Jun 10 10:00 bigfile.txt # 显示1GB $ du -h bigfile.txt 0 bigfile.txt # 实际可能是稀疏文件2. du命令核心用法解析
2.1 基础统计模式
最基础的用法是直接针对文件或目录执行du,不带任何参数时默认以KB为单位显示:
$ du /var/log 132 /var/log/apt 48 /var/log/lighttpd 1024 /var/log/syslog.1 ...常用参数说明:
-h:人性化显示(自动转换KB/MB/GB)-s:只显示总计(summary)-c:最后显示总计(可与-s配合)--apparent-size:显示逻辑大小而非物理占用
实际案例:快速找出/home下占用最大的用户目录
$ du -sh /home/* | sort -rh 4.8G /home/user1 2.1G /home/user2 ...2.2 深度控制与过滤技巧
当处理深层目录结构时,--max-depth参数非常实用。比如只查看当前目录下一级子目录的大小:
$ du -h --max-depth=1 /usr 144M /usr/lib 56K /usr/include 2.1G /usr/share ...结合find命令可以实现更灵活的过滤。例如找出所有大于100MB的日志文件:
$ find /var/log -type f -name "*.log" -exec du -h {} + | awk '$1 ~ /G/ || $1 ~ /[0-9]{3}M/' 1.2G /var/log/syslog.1 450M /var/log/kern.log3. 高级应用场景与性能优化
3.1 排除特定目录的统计
在分析整个文件系统时,可能需要排除某些挂载点。例如统计根目录但不包含/data挂载点:
$ du -h --exclude=/data --max-depth=1 /对于NAS等网络存储,使用--exclude-from参数可以批量排除:
$ cat exclude_list /mnt/backup /mnt/nas $ du -h --exclude-from=exclude_list /3.2 处理特殊文件类型
对于包含大量硬链接的目录(如Time Machine备份),需添加-l参数统计重复空间:
$ du -lh /backups统计docker容器占用空间时,要注意--size-only避免重复计算共享层:
$ du -sh /var/lib/docker/overlay2 --size-only3.3 性能调优技巧
当处理百万级文件时,du可能运行缓慢。此时可以:
- 使用
-x限定在同一文件系统 - 通过
timeout限制运行时间 - 采用增量统计策略
实测案例:对一个含300万文件的目录
$ time du -sh /data # 原始方式 real 4m12s $ time find /data -type f -printf "%s\n" | awk '{sum+=$1} END{print sum}' real 1m45s # 更高效的替代方案4. 常见问题排查与误区
4.1 du与df显示不一致的7种原因
这是运维中最常见的问题之一,主要可能原因包括:
- 已删除文件仍被进程占用(lsof检查)
- 文件系统预留空间(tune2fs查看)
- 稀疏文件特殊处理
- 容器/虚拟机的存储驱动差异
- 磁盘配额限制
- 文件系统错误(需fsck)
- LVM快照未释放空间
诊断脚本示例:
#!/bin/bash diff=$(( $(df -P / | awk 'NR==2{print $3}') - $(du -sx / | awk '{print $1}') )) echo "Difference: $(( diff / 1024 )) MB"4.2 权限问题处理方案
当遇到"Permission denied"错误时,可以:
- 使用sudo提升权限(注意安全风险)
- 通过
--no-dereference跳过符号链接 - 使用
2>/dev/null过滤错误输出 - 改用
ncdu等交互式工具
安全扫描场景下的推荐用法:
$ sudo du -ah --exclude=/proc --exclude=/sys / | grep -E '[0-9]G\s'4.3 输出格式的陷阱
不同Linux发行版的du输出可能有差异:
- GNU coreutils版本支持
--block-size自定义单位 - BSD版本默认512字节块大小
- BusyBox版本功能受限
跨平台脚本应显式指定单位:
$ du -k /path # 强制KB单位 $ du -m /path # 强制MB单位5. 替代工具与可视化方案
5.1 ncdu交互式分析
ncdu(NCurses Disk Usage)提供了更友好的TUI界面:
$ sudo apt install ncdu $ ncdu /var其优势在于:
- 实时排序功能
- 快捷键导航
- 批量删除操作
- 导出扫描结果
5.2 图形化工具对比
| 工具名称 | 安装方式 | 特点 |
|---|---|---|
| Baobab | apt install baobab | GNOME集成,环形图展示 |
| QDirStat | apt install qdirstat | Qt界面,支持文件类型过滤 |
| Filelight | apt install filelight | KDE组件,饼图可视化 |
5.3 自制监控脚本示例
定期扫描关键目录的shell脚本:
#!/bin/bash LOG_FILE="/var/log/disk_usage_$(date +%Y%m%d).log" THRESHOLD="1G" echo "===== $(date) =====" >> $LOG_FILE du -h --threshold=$THRESHOLD --max-depth=3 / 2>/dev/null >> $LOG_FILE配合crontab实现每日扫描:
0 3 * * * /usr/local/bin/disk_monitor.sh6. 内核机制与底层原理
6.1 文件系统如何记录大小
在ext4文件系统中,每个inode包含两个大小字段:
i_size:文件逻辑大小(通过stat显示)i_blocks:实际分配的512字节块数
查看inode详细信息:
$ stat testfile Size: 1024 Blocks: 8 IO Block: 4096 regular file6.2 块分配策略影响
现代文件系统的特性会影响du统计:
- 写时复制(COW)文件系统如btrfs
- 透明压缩(如ZFS的lz4)
- 去重技术
检查文件系统特性:
$ df -T / # 查看文件系统类型 $ tune2fs -l /dev/sda1 | grep "Features" # ext4特性6.3 容器环境特殊考量
在Docker/Kubernetes环境中,存储统计更复杂:
# 查看容器层大小 $ docker ps -s CONTAINER ID SIZE abc123 +2MB (virtual 1.2GB) # 详细存储分析 $ docker system df -v7. 性能基准测试数据
通过不同方法统计同一目录的耗时对比(测试环境:ext4, 1.2M files):
| 命令 | 耗时(秒) | 内存占用(MB) |
|---|---|---|
| du -sh | 12.3 | 15 |
| find -type f -printf "%s\n" | 8.7 | 8 |
| ls -lR | awk | 22.1 |
| ncdu -x | 14.5 | 32 |
优化建议:
- 对于SSD存储,增加
-P参数并行处理 - 使用
ionice -c 3降低IO优先级 - 避免在业务高峰执行扫描