欢迎光临枣庄市中国白事服务网
详情描述

du(磁盘使用量)和df(磁盘文件系统)显示不一致是常见问题,主要原因和处理方法如下:

一、常见原因

1. 已删除文件仍被进程占用

# 查看被删除但未释放的文件
lsof | grep deleted
# 或
lsof +L1

# 结果示例:
# process_name 1234 user 5r REG 253,0 100M 12345 /path/to/file (deleted)

处理:重启相关进程或发送信号释放文件句柄。

2. 文件系统预留空间

默认保留5%空间给root用户(ext3/4文件系统)。

# 查看预留比例
tune2fs -l /dev/sda1 | grep "Reserved block count"

# 调整预留比例(如改为1%)
tune2fs -m 1 /dev/sda1

3. 稀疏文件(Sparse Files)

# 创建稀疏文件示例
dd if=/dev/zero of=sparse_file bs=1M seek=1024 count=0

# du显示实际占用,df显示逻辑大小
du -sh sparse_file    # 显示实际大小
ls -lh sparse_file    # 显示逻辑大小

4. 日志文件系统待写入数据

# 强制同步文件系统
sync

5. 容器/虚拟化层占用

# 检查overlay2、docker、lvm等
df -hT
lsblk
docker system df  # Docker专用

二、诊断步骤

1. 对比检查

# 1. 查看df结果
df -h

# 2. 查看根分区实际使用
du -shx /* 2>/dev/null | sort -hr

# 3. 计算差值
df_size=$(df / | awk 'NR==2 {print $3}')
du_size=$(du -sx / 2>/dev/null | cut -f1)
echo "差值: $(( (df_size - du_size) / 1024 )) MB"

2. 查找大文件

# 查找大于100M的文件
find / -type f -size +100M 2>/dev/null | xargs ls -lh

# 使用ncdu交互式查看
ncdu /

3. 检查特殊文件

# 检查隐藏文件(以.开头)
du -sh /.* 2>/dev/null | sort -hr

# 检查/tmp
ls -la /tmp | head -20

三、处理方案

方案1:释放被占用的已删除文件

# 方法A:重启相关进程
# 找到占用进程后
kill -9 PID

# 方法B:清空日志文件(不要直接删除)
truncate -s 0 /var/log/syslog
# 或
cat /dev/null > /var/log/syslog

方案2:清理缓存

# 清理页面缓存
echo 1 > /proc/sys/vm/drop_caches

# 清理目录项和inode缓存
echo 2 > /proc/sys/vm/drop_caches

# 清理页面缓存、目录项和inode缓存
echo 3 > /proc/sys/vm/drop_caches

方案3:检查文件系统错误

# 卸载后检查(谨慎操作)
umount /dev/sda1
fsck -y /dev/sda1
mount /dev/sda1

方案4:容器/Docker清理

# Docker清理
docker system prune -a

# 清理overlay2
systemctl stop docker
rm -rf /var/lib/docker/overlay2/*
systemctl start docker

四、预防措施

定期监控

# 添加到crontab
0 * * * * df -h >> /var/log/disk_usage.log

日志轮转配置

# 检查logrotate配置
cat /etc/logrotate.conf

使用lsof监控

# 监控已删除文件
watch -n 60 'lsof | grep deleted | wc -l'

设置磁盘配额

# 启用配额
quotacheck -cug /home
quotaon /home

五、注意事项

  • 生产环境谨慎操作:清理前先备份重要数据
  • 避免直接删除日志:使用truncate或logrotate
  • 注意容器环境:Docker/容器可能隐藏真实使用量
  • 考虑时间因素:du需要遍历文件,大目录可能需要时间

六、自动化检查脚本

#!/bin/bash
# check_disk_discrepancy.sh

partition="/"
df_used=$(df -k $partition | awk 'NR==2 {print $3}')
du_used=$(du -sxk $partition 2>/dev/null | cut -f1)
diff=$((df_used - du_used))
diff_mb=$((diff / 1024))

if [ $diff_mb -gt 100 ]; then
    echo "警告:$partition 分区 du/df 差值超过100MB"
    echo "df已用: ${df_used}KB"
    echo "du统计: ${du_used}KB"
    echo "差值: ${diff_mb}MB"

    # 查找可能的原因
    echo "检查已删除但未释放的文件:"
    lsof | grep deleted | head -5
fi

通过以上方法,基本可以解决和预防du/df不一致问题。