1. Linux磁盘空间统计的奥秘:深入理解du命令
作为一名Linux系统管理员,我每天都要和磁盘空间打交道。记得刚入行时,有次服务器报警磁盘空间不足,我急匆匆地用du -sh /var/log/*检查日志目录大小,结果显示只有几十GB,但实际使用却接近90%。这个谜团困扰了我很久,直到后来才发现是隐藏文件在"作怪"。今天,我们就来彻底解析这个看似简单却暗藏玄机的磁盘统计工具。
du(Disk Usage)是Linux系统中最基础也最实用的磁盘空间统计工具。它通过递归遍历目录来计算文件占用空间,但很多人(包括曾经的我)都低估了它的复杂性。特别是在处理隐藏文件、符号链接和不同文件系统时,du的表现往往出人意料。本文将结合我多年运维经验,带你深入理解du的工作原理、常见误区和实用技巧。
2. du命令核心用法解析
2.1 基础语法与常用选项
du的基本语法非常简单:
bash复制du [选项] [文件或目录]
但它的选项组合却能产生丰富的变化。以下是6个最常用的选项:
-
-s/--summarize:只显示总计大小
- 适用场景:快速查看目录整体大小
- 示例:
du -sh /home→ 显示/home目录总大小
-
-h/--human-readable:人性化显示单位
- 自动转换KB/MB/GB
- 示例:
du -h file.txt→ 显示"4.0K"而非"4096"
-
-a/--all:显示所有文件而不仅是目录
- 适用场景:找出大文件
- 示例:
du -ah /var | sort -rh | head -10→ 列出/var下前10大文件
-
--max-depth=N:控制遍历深度
- 示例:
du -h --max-depth=1 /usr→ 只显示/usr下一级子目录大小
- 示例:
-
--exclude=PATTERN:排除特定模式
- 示例:
du -h --exclude='*.log' /var→ 统计时排除.log文件
- 示例:
-
-c/--total:显示总计
- 适用场景:统计多个目录总和
- 示例:
du -sch /home /var /usr→ 分别显示三个目录大小及总和
经验之谈:组合使用-s和-h选项(即
du -sh)是最常用的模式,它能快速给出目录的整洁汇总信息。我在日常巡检中90%的情况都使用这个组合。
2.2 实际应用示例
场景1:快速定位磁盘占用大户
bash复制du -h --max-depth=1 / | sort -h
这个命令组合可以快速找出根目录下哪些子目录占用空间最大。sort -h能正确排序人类可读的大小单位(如1K < 1M < 1G)。
场景2:排除特定目录统计
bash复制du -h --exclude='/proc/*' --exclude='/sys/*' /
在统计根目录大小时,通常需要排除/proc和/sys这些虚拟文件系统,它们会干扰真实数据。
场景3:按修改时间筛选统计
bash复制find /var/log -type f -mtime +30 -exec du -ch {} + | grep total$
这个复杂命令组合可以统计/var/log目录下所有超过30天的日志文件总大小,非常适合日志清理前的评估。
3. 隐藏文件引发的统计差异
3.1 经典问题重现
让我们回到文章开头提到的核心问题:为什么du -sh /root和du -sh /root/*结果不同?
假设/root目录结构如下:
code复制/root
├── file1.txt 10G
├── downloads/ 30G
├── .bashrc 1M
└── .cache/ 20G
执行两个命令的结果差异:
bash复制du -sh /root # 显示约60G (10+30+0.001+20)
du -sh /root/* # 显示约40G (10+30)
3.2 技术原理深度解析
这种差异源于三个关键技术点:
-
Shell通配符扩展机制:
*在shell中默认不匹配以点开头的隐藏文件- 这是POSIX标准定义的行为,所有Unix-like系统一致
-
du命令处理路径的方式:
- 直接给目录路径时,du会递归统计所有内容
- 给文件列表时,du只统计这些具体文件
-
隐藏文件的特殊地位:
- 点文件在Unix传统中表示"不重要"的配置文件
- 但现代系统中,它们往往存储关键数据(如.cache、.config)
3.3 正确统计包含隐藏文件的方法
方法1:直接统计目录
bash复制du -sh /root
这是最简单可靠的方式,适用于大多数情况。
方法2:显式包含隐藏文件
bash复制du -sh .[!.]* * 2>/dev/null | sort -hr
这个复杂命令做了以下工作:
.[!.]*匹配所有非.和..的隐藏文件*匹配所有非隐藏文件2>/dev/null忽略权限错误sort -hr按人类可读格式逆序排序
方法3:使用find命令辅助
bash复制find /root -maxdepth 1 -exec du -sh {} + | sort -h
这种方法更灵活,可以添加各种find条件筛选文件。
踩坑记录:曾经有次清理磁盘时,我只看了
du -sh /var/*的结果,漏掉了.nginx目录下的20GB缓存文件,导致清理后空间仍未释放。从此我养成了直接对目录使用du的习惯。
4. du与df的差异与关联
4.1 根本区别
| 命令 | 统计维度 | 数据来源 | 典型用途 |
|---|---|---|---|
| du | 文件内容大小 | 遍历文件系统 | 查找大文件/目录 |
| df | 磁盘块使用情况 | 文件系统超级块 | 查看磁盘剩余空间 |
4.2 结果不一致的常见原因
-
已删除但未释放的文件:
- 进程仍持有文件描述符时,df统计已用空间包含这些文件
- du无法看到已删除文件,导致统计偏小
- 解决方法:
lsof | grep deleted找到相关进程并重启
-
稀疏文件(Spare File):
- 创建时显示很大但实际占用小的文件
- du按实际块统计,df可能按逻辑大小统计
- 示例:
dd if=/dev/zero of=sparsefile bs=1 count=0 seek=1T
-
不同文件系统挂载点:
- du会跨挂载点统计,df只统计当前文件系统
- 使用
-x选项限制du不跨越挂载点:du -xsh /
-
磁盘配额(Quota):
- df显示的是全局磁盘使用
- 用户视角的du可能受配额限制影响
4.3 实用诊断技巧
当发现磁盘空间异常时,我通常按以下流程排查:
- 先用
df -h确认各分区使用情况 - 找到使用率高的分区,如
/var - 使用
du -xsh /var/* | sort -h定位大目录 - 如果du和df差异大,检查是否有僵尸文件:
bash复制lsof +L1 | grep '/var' - 对于疑似稀疏文件,用
du -h和ls -lh对比查看
5. 高级技巧与性能优化
5.1 加速大目录统计
统计包含数百万文件的大目录时,du可能非常慢。以下技巧可以提升效率:
-
限制遍历深度:
bash复制du -h --max-depth=2 /path/to/large/dir -
跳过特定目录:
bash复制du -h --exclude='*/cache/*' /path -
使用ncdu工具:
bash复制
ncdu /path/to/scan这个交互式工具更快且更直观
-
并行统计:
bash复制find /path -maxdepth 1 -type d | parallel du -sh需要安装GNU parallel
5.2 处理特殊文件类型
-
符号链接:
- 默认情况下du统计链接指向的文件
- 使用
-L选项跟随链接,-P不跟随(默认) - 示例:
du -shL /path统计链接指向内容
-
硬链接:
- du会多次统计同一个inode的空间
- 使用
--count-links避免重复计算
-
压缩文件系统:
- du显示的是逻辑大小,不是磁盘占用
- 对于ZFS/Btrfs等,需用专用工具如
zfs list
5.3 输出格式定制
-
生成CSV报告:
bash复制du -sc --block-size=1M /path/* | awk 'BEGIN{OFS=","} {print $2,$1}' -
可视化展示:
bash复制du -h /path | sort -h | bar需要安装bar工具
-
与find组合生成详细报告:
bash复制find /path -type f -exec du -h {} + | sort -rh > disk_usage_report.txt
6. 常见问题解决方案
6.1 权限不足问题
当对系统目录执行du时,常会遇到:
bash复制du: cannot read directory '/path': Permission denied
解决方案:
- 使用sudo提升权限:
bash复制sudo du -sh /path - 忽略错误信息:
bash复制du -sh /path 2>/dev/null - 仅统计有权限的部分:
bash复制find /path -type d -executable -exec du -sh {} + 2>/dev/null
6.2 磁盘空间统计不准确
可能原因及解决方法:
- 文件系统缓存未同步:
bash复制sync # 强制写入磁盘 - NFS等网络文件系统延迟:
bash复制df -i # 检查inode使用情况 - LVM快照影响:
bash复制lvdisplay # 检查逻辑卷状态
6.3 处理包含特殊字符的文件名
对于包含空格、换行符等特殊字符的文件:
bash复制find /path -type f -print0 | xargs -0 du -h | sort -h
-print0和-0选项正确处理所有特殊字符
7. 生产环境实战案例
7.1 案例一:日志目录突然增长
现象:/var/log目录一夜之间增长50GB
排查步骤:
- 快速定位大文件:
bash复制du -ah /var/log | sort -rh | head -20 - 发现是nginx的access.log异常增长
- 确认是爬虫疯狂扫描导致
- 临时解决方案:
bash复制truncate -s 0 /var/log/nginx/access.log - 长期方案:配置nginx限流和日志轮转
7.2 案例二:磁盘空间"神秘"消失
现象:df显示磁盘已用90%,但du统计只有60%
排查过程:
- 检查已删除未释放文件:
bash复制
lsof +L1 - 发现是已删除的MySQL大表文件
- 解决方案:
bash复制
systemctl restart mysql
7.3 案例三:容器占用的磁盘空间
现象:Docker容器占用空间远超预期
排查方法:
- 查看容器磁盘使用:
bash复制docker system df - 详细分析:
bash复制du -sh /var/lib/docker/{containers,volumes,image} - 清理无用数据:
bash复制
docker system prune -a
掌握du命令的方方面面后,我处理磁盘空间问题的时间从平均2小时缩短到15分钟。特别是在处理那些"消失"的磁盘空间时,理解du和df的差异让我少走了很多弯路。建议每位Linux用户都花时间深入理解这个看似简单却功能强大的工具,它会在你最需要的时候成为得力助手。