你是否曾经遇到过这样的情况:服务器突然报警磁盘空间不足,你急忙登录系统,却不知道该用什么命令快速定位问题?或者执行了某个命令,发现显示的结果与预期不符,却不知道问题出在哪里?
在 Linux 系统管理和故障排查中,磁盘空间问题是最常见也最让人头疼的问题之一。很多工程师都知道 df 和 du 这两个基础命令,但真正能高效使用它们的人并不多。有些人甚至会在生产环境中因为误读命令结果而做出错误的决策。
本文将深入解析 df 和 du 命令的底层原理、使用技巧和实际应用场景。无论你是刚接触 Linux 的新手,还是有一定经验的管理员,都能从中获得实用的知识。我们将从最基本的命令用法开始,逐步深入到高级技巧和实战案例,帮助你彻底掌握这两个看似简单却威力强大的工具。
1. 为什么 df 和 du 的结果经常不一致?
这是很多 Linux 用户都会遇到的困惑:为什么用 df 查看磁盘使用率显示 90%,但用 du 统计文件大小却远远达不到这个数值?
要理解这个问题,我们需要先了解两个命令的工作原理差异:
df (disk free) 的工作原理:
- 直接读取文件系统的超级块信息
- 统计的是磁盘块级别的使用情况
- 包含已删除但仍被进程占用的文件
- 包含文件系统自身的元数据占用
du (disk usage) 的工作原理:
- 遍历目录树统计每个文件的大小
- 只计算当前存在的文件
- 无法统计被删除但未释放的文件
- 不包含文件系统元数据
关键差异点:
- 已删除但被占用的文件:当某个文件被删除但仍有进程在使用时,
df 会统计这部分空间,而 du 不会
- 文件系统开销:不同的文件系统(ext4、xfs、btrfs)有不同比例的元数据开销
- 磁盘配额:如果启用了磁盘配额,两个命令的统计范围可能不同
2. df 命令详解:快速掌握磁盘全局状态
2.1 基础用法与参数解析
df 命令是查看磁盘空间使用情况的首选工具,它能快速显示所有挂载文件系统的空间信息。
2.2 输出字段详解
理解 df 命令的输出字段对于正确解读磁盘状态至关重要:
TEXT
1
Filesystem 1K-blocks Used Available Use% Mounted on
2
/dev/sda1 20511356 18366256 1103300 95% /
3
/dev/sdb1 41151808 1243568 37804032 4% /home
- Filesystem:文件系统设备名或挂载点
- 1K-blocks:总空间(以1KB为单位)
- Used:已使用空间
- Available:可用空间(注意与Free的区别)
- Use%:使用百分比
- Mounted on:挂载点
重要提示:Available字段表示普通用户可用的空间,已考虑了预留空间(通常为5%)。
2.3 实战案例:监控磁盘使用率
在实际生产环境中,我们经常需要监控磁盘使用率,及时发现问题:
BASH
2
df -h / | awk 'NR==2 {if ($5 > 90) print "警告: 根分区使用率超过90%!"}'
7
CURRENT=$(df / | awk 'NR==2 {print $5}' | sed 's/%//')
9
if [ $CURRENT -gt $THRESHOLD ]; then
10
echo "$(date): 磁盘使用率 ${CURRENT}% 超过阈值 ${THRESHOLD}%" >> /var/log/disk_alert.log
3. du 命令详解:精准定位大文件定位
3.1 基础用法与常用参数
du 命令用于统计文件和目录的磁盘使用情况,是查找大文件的利器。
BASH
8
du -h --max-depth=1 /home
11
du -h --max-depth=1 / | sort -hr
14
du -sh --exclude="*.log" /var
3.2 高级技巧:找出占用空间最大的文件
在实际故障排查中,快速找到占用空间最大的文件或目录是关键:
BASH
2
du -ah /var | sort -rh | head -10
5
find /var -type f -exec du -h {} + | sort -rh | head -10
8
watch -n 5 'du -sh /tmp && du -h --max-depth=1 /tmp | sort -hr'
3.3 处理特殊情况的技巧
有些情况下,du 命令需要特殊处理才能得到准确结果:
BASH
8
du -sh --exclude=/proc --exclude=/sys /
4. 环境准备与命令验证
4.1 测试环境搭建
为了更好的理解和实践,建议在安全的环境中测试这些命令:
BASH
2
mkdir -p /tmp/disk_test/{dir1,dir2,dir3}
3
echo "This is a test file" > /tmp/disk_test/file1.txt
4
dd if=/dev/zero of=/tmp/disk_test/largefile bs=1M count=100
4.2 命令兼容性说明
不同Linux发行版的 df 和 du 命令可能有些差异:
- CentOS/RHEL:通常使用GNU coreutils版本
- Ubuntu/Debian:同样基于GNU coreutils,但版本可能较新
- macOS:BSD版本,参数略有不同(如
-h 参数可能不支持)
5. 常见问题排查实战
5.1 问题现象:df显示磁盘满但du找不到大文件
这是最经典的问题,通常由以下原因导致:
BASH
5
dumpe2fs /dev/sda1 | grep -i "block count"
9
for pid in $(lsof | grep deleted | awk '{print $2}' | sort -u); do
10
echo "PID: $pid, Command: $(ps -p $pid -o comm=)"
解决方案:
- 重启占用已删除文件的进程
- 清理文件系统日志(需要卸载文件系统)
- 检查磁盘配额:
quota -u username
5.2 问题现象:du统计结果异常
BASH
2
find /path -type l -exec ls -la {} \;
5.3 问题现象:磁盘空间突然减少
BASH
2
find / -type f -size +100M -mtime -1 2>/dev/null
5
ls -lah /var/log/*.log | sort -k5 -hr | head -10
8
du -sh /tmp/* 2>/dev/null | sort -hr
6. 高级应用场景
6.1 自动化磁盘监控脚本
在生产环境中,我们需要自动化的监控方案:
BASH
5
LOG_FILE="/var/log/disk_monitor.log"
6
ALERT_EMAIL="admin@example.com"
10
local usage=$(df -h "$mount_point" | awk 'NR==2 {print $5}' | sed 's/%//')
11
local available=$(df -h "$mount_point" | awk 'NR==2 {print $4}')
13
if [ "$usage" -gt "$THRESHOLD" ]; then
14
local message="警告: $mount_point 使用率 ${usage}%, 剩余空间 ${available}"
15
echo "$(date): $message" >> "$LOG_FILE"
18
local large_files=$(find "$mount_point" -type f -size +100M -exec ls -lh {} \; 2>/dev/null | head -5)
22
echo "磁盘空间告警: $message"
28
du -h --max-depth=1 "$mount_point" 2>/dev/null | sort -hr | head -10
29
} | mail -s "磁盘空间告警: $mount_point" "$ALERT_EMAIL"
35
check_disk_usage "/home"
36
check_disk_usage "/var"
6.2 结合其他命令的进阶用法
BASH
2
watch -n 1 'df -h; echo "---"; du -sh /var/log/* 2>/dev/null | sort -hr'
5
generate_disk_report() {
6
echo "=== 磁盘空间报告 $(date) ==="
12
du -h --max-depth=1 / 2>/dev/null | sort -hr | head -15
15
find / -type f -size +500M 2>/dev/null | xargs ls -lh
7. 性能优化与最佳实践
7.1 提升命令执行效率
当处理大量文件时,du 命令可能会比较慢,以下是一些优化技巧:
BASH
9
du -h --max-depth=3 /var
12
find /var -type d -print0 | xargs -0 -P4 du -s
7.2 安全注意事项
在使用这些命令时,需要注意一些安全边界:
BASH
4
size=$(du -sh /some/path | cut -f1)
5
echo "确认要删除 ${size} 的数据吗?[y/N]"
7
if [ "$confirmation" = "y" ]; then
12
tar -czf backup_$(date +%Y%m%d).tar.gz /path/to/important/data
8. 不同文件系统的特殊考虑
8.1 ext4 文件系统
BASH
2
tune2fs -l /dev/sda1 | grep -E "(Block count|Free blocks|Reserved blocks)"
8.2 XFS 文件系统
BASH
5
xfs_quota -x -c "report -h" /mountpoint
8.3 Btrfs 文件系统
BASH
2
btrfs filesystem usage /mountpoint
5
btrfs subvolume list /mountpoint
9. 实用脚本合集
9.1 快速磁盘健康检查脚本
BASH
4
echo "=== 磁盘健康检查报告 ==="
17
du -h --max-depth=1 / 2>/dev/null | sort -hr | head -10
21
find / -type f -size +100M -mtime -7 2>/dev/null | xargs ls -lh 2>/dev/null
9.2 自动化清理脚本
BASH
9
find "$LOG_DIR" -name "*.log.*" -mtime +30 -delete
12
find "$TEMP_DIR" -type f -mtime +7 -delete
15
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +90 -delete
17
echo "清理完成: $(date)" >> /var/log/cleanup.log
通过本文的详细讲解,你应该对 df 和 du 命令有了更深入的理解。这两个命令虽然基础,但在实际系统管理和故障排查中发挥着重要作用。记住关键点:df 看文件系统层面,du 看文件层面,当两者结果不一致时,通常意味着有隐藏的问题需要排查。
建议将文中的脚本和技巧保存下来,在实际工作中遇到磁盘空间问题时可以快速参考。熟练掌握这些工具,能够显著提升你的Linux系统管理效率。