Linux查看文件大小,du和df命令区别
前言
排查磁盘满时最容易混淆 du 和 df:一个统计文件实际占用,一个统计分区已用空间,二者数字常常对不上。搞清楚各自口径、配合使用,才能准确找到占空间的目录和被已删除但仍被进程占用的空间。本篇讲清两者区别、常用参数和排查组合拳。
一、df:看分区(文件系统)整体用量
df 读取文件系统超级块,统计每个分区总容量、已用、可用、挂载点,回答的是"这块盘还剩多少"。
# 人类可读格式(K/M/G),显示文件系统类型
df -hT
# 只看某个挂载点
df -h /var
# 列出 inode 使用情况(空间没满但报 No space 时排查)
df -i
参数:-h 人类可读,-T 显示类型,-i 查看 inode,-x tmpfs 排除内存临时文件系统。
二、du:统计目录/文件实际占用
du 遍历目录树累加每个文件大小,回答的是"哪个目录最占地方"。
# 查看当前目录大小,人类可读
du -sh .
# 查看 /var 下一级子目录大小并排序(从大到小)
du -h --max-depth=1 /var | sort -rh | head -20
# 查看单个文件大小
du -h /var/log/messages
# 统计当前目录下各子目录,只显示总计
du -sh /var/*
参数:-s 只显示汇总,-h 人类可读,--max-depth=N 限定统计层级,-x 不统计其他挂载点。
三、两者核心区别
| 对比项 | df | du |
|---|---|---|
| 统计对象 | 文件系统分区整体 | 目录/文件实际大小 |
| 数据来源 | 超级块分配/使用记录 | 遍历文件累加 |
| 回答问题 | 盘还剩多少 | 哪个目录占空间 |
| 典型用途 | 判断是否磁盘满、inode 耗尽 | 定位大目录、大文件 |
四、为什么 du 和 df 数字对不上
常见三种原因:
- 已删除文件仍被进程占用:文件删掉了但进程没释放句柄,
du不再统计,df仍计入已用。用lsof | grep deleted找到占用进程,重启或截断对应文件即可释放。 - 硬链接重复统计口径:du 按目录累加,硬链接在不同目录可能被重复计数;df 看块设备分配更准。
- 隐藏在挂载点下的旧文件:目录里先写了数据,后在该路径挂载新盘,旧文件被遮盖,du 看不到,df 上一层分区仍占用。
五、磁盘满排查标准流程
# 1. 先用 df 确认哪个分区满了、inode 是否耗尽
df -h
df -i
# 2. 进入对应分区,逐层 du 找大目录
du -h --max-depth=1 /var | sort -rh | head
# 3. 找大于 500M 的文件
find /var -type f -size +500M -exec ls -lh {} \;
# 4. 检查被删除但仍占用空间的文件
lsof | grep deleted
定位到日志、缓存、旧备份等大文件后,优先归档或压缩,不要直接 rm 正在被写入的日志,应截断:
# 清空正在写入的日志而不释放句柄冲突
> /var/log/nginx/access.log
六、常见坑
- 只 du 不 df:看完目录不大,却忽略分区已 100%;
du -sh /统计到其他挂载点:加-x限定当前文件系统;- 误删正在写入的大日志:空间不释放,应先重启对应服务或用
>截断; - 只看磁盘空间忽略 inode:小文件过多时空间有剩但创建文件失败,用
df -i排查; - 权限不足漏统计:普通用户 du 部分目录读不到,排查时用 root。
总结
df -h 看分区用量和剩余,du -sh --max-depth=1 目录 逐层定位大目录;两者数字不一致时优先怀疑"已删除但被进程占用"的文件,用 lsof | grep deleted 核对。排查顺序:先 df 定位分区,再 du 找目录,最后 find 找具体大文件。
遇到问题加QQ23979811 协助处理
Linux查看目录占用
Linux查看目录占用
引言
磁盘满了先定位是哪个目录吃掉空间,df看整体分区,du逐层下钻找大户。两个命令配合,从分区到目录到文件逐级缩小范围,是磁盘排查的标准路径。
看整体分区:df
df -h
人类可读格式显示各分区总量、已用、可用、使用率,先判断是哪个挂载点满了。
看单个目录总大小
du -sh /var/log
-s汇总,-h人类可读,直接给出这个目录总共占多大。
看一级子目录大小并排序
du -h --max-depth=1 /var | sort -rh | head
只算一层子目录,sort -rh按人类可读大小倒序,head取前几名,快速定位大户。
常用简写
du -sh /var/*
列出/var下每个一级目录大小,逐层进入继续排查。
排除文件系统统计
du -shx /home
-x不跨文件系统,避免把挂载的别的盘也算进来。
看目录下文件数量
ls /var/log | wc -l
有些目录不大但文件海量,inode耗尽也会写不进,配合df -i看inode。
注意事项
- df看分区,du看目录,先df定位再du下钻;
- 大目录du会遍历较慢,加--max-depth限制层数;
- 删除大文件后空间没释放,可能是进程仍持有句柄,需重启进程;
- sort -rh依赖du输出的G/M单位;
- /proc、/sys是虚拟文件系统,du统计无意义;
- 日志目录优先排查,常是增长最快的大户。
总结
df -h看分区整体,du -sh看单目录汇总,--max-depth=1配合sort -rh找一级大户,-x不跨文件系统,ls加wc -l看文件数,df -i查inode。排查路径是先df定位满的分区,再du逐层下钻,删文件后空间不释放要查持有句柄的进程,日志目录优先检查。
MySQL查看数据库大小,表占用空间
前言
磁盘快满了,不知道哪个库哪个表占空间大。本文教你查MySQL数据库和表的大小。
一、查看所有数据库大小
SELECT
table_schema AS '数据库名',
ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS '大小(MB)'
FROM information_schema.tables
GROUP BY table_schema
ORDER BY SUM(data_length + index_length) DESC;
输出:
| 数据库名 | 大小(MB) |
|---|---|
| mydb | 512.34 |
| test | 128.56 |
| mysql | 10.24 |
二、查看某个数据库的所有表大小
SELECT
table_name AS '表名',
ROUND(((data_length + index_length) / 1024 / 1024), 2) AS '大小(MB)',
table_rows AS '行数'
FROM information_schema.tables
WHERE table_schema = 'mydb'
ORDER BY (data_length + index_length) DESC;
把 mydb 换成你的数据库名。
三、查看单个表大小
SELECT
table_name AS '表名',
ROUND((data_length) / 1024 / 1024, 2) AS '数据大小(MB)',
ROUND((index_length) / 1024 / 1024, 2) AS '索引大小(MB)',
table_rows AS '行数'
FROM information_schema.tables
WHERE table_schema = 'mydb' AND table_name = 'users';
四、查看所有表大小(按大小排序)
SELECT
table_schema AS '数据库',
table_name AS '表名',
ROUND(((data_length + index_length) / 1024 / 1024), 2) AS '大小(MB)',
table_rows AS '行数'
FROM information_schema.tables
ORDER BY (data_length + index_length) DESC
LIMIT 20;
只看前20大的表。
五、用命令行查看
查看数据目录
du -sh /var/lib/mysql/
查看某个库的大小
du -sh /var/lib/mysql/mydb/
查看所有库的大小
du -sh /var/lib/mysql/*/
六、常用场景
场景1:磁盘满了,找大表
SELECT
table_schema AS '数据库',
table_name AS '表名',
ROUND(((data_length + index_length) / 1024 / 1024), 2) AS '大小(MB)'
FROM information_schema.tables
ORDER BY (data_length + index_length) DESC
LIMIT 10;
找出最大的10个表。
场景2:表很大,想知道数据和索引各占多少
SELECT
table_name AS '表名',
ROUND(data_length / 1024 / 1024, 2) AS '数据(MB)',
ROUND(index_length / 1024 / 1024, 2) AS '索引(MB)'
FROM information_schema.tables
WHERE table_schema = 'mydb';
场景3:清理无用数据,释放空间
删了很多数据,但磁盘空间没释放。
原因: InnoDB删数据后不会自动释放磁盘空间。
解决: 优化表:
OPTIMIZE TABLE users;
常见坑
坑1:table_rows不准
InnoDB的table_rows是估算值,不是精确值。
原因: InnoDB是多版本的,统计信息不精确。
解决: 要精确行数用 SELECT COUNT(*) FROM 表名;
坑2:删了数据空间没释放
DELETE删了很多行,但文件大小没变。
原因: InnoDB的表空间不会自动收缩。
解决: OPTIMIZE TABLE 表名; 或者重建表。
坑3:临时表占空间
performance_schema等系统库也占空间。
解决: 正常现象,不用管。
坑4:ibdata1文件很大
共享表空间文件很大,但不知道里面是什么。
原因: 所有InnoDB表都存在一个文件里。
解决: 开 innodb_file_per_table,每个表独立文件。
总结
常用查询:
- 查所有库大小:
GROUP BY table_schema - 查某库所有表:
WHERE table_schema='库名' - 查某表大小:
WHERE table_schema='库名' AND table_name='表名'
记住: 磁盘满了先查information_schema.tables找大表。
遇到问题加QQ23979811 协助处理
Linux磁盘占用100%怎么排查,大文件查找清理方法
前言
服务器跑着跑着突然网站打不开了,SSH 也反应变慢,一查磁盘使用率 100%。这是运维中非常常见的问题。磁盘满了不仅影响服务正常运行,还可能导致数据丢失、日志写不进去等严重后果。本文就手把手教你怎么快速定位磁盘占用大的文件,以及怎么安全清理。
第一步:查看整体磁盘使用情况
先用 df 命令看看哪个分区满了:
df -h
参数说明:
-h:以人类可读的方式显示(G、M)
输出示例:
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 40G 38G 2.0G 95% /
devtmpfs 7.8G 0 7.8G 0% /dev
tmpfs 7.8G 0 7.8G 0% /dev/shm
tmpfs 7.8G 480M 7.8G 6% /run
tmpfs 7.8G 0 7.8G 0% /sys/fs/cgroup
看 Use% 那一列,如果哪个分区到了 100% 或者 90% 以上,那就是问题所在。比如上面 /dev/vda1 用了 95%,根分区快满了。
第二步:定位哪个目录占用最大
知道哪个分区满了,接下来找是哪个目录占了最多空间。用 du 命令:
1. 查看根目录下各目录的大小
du -sh /* 2>/dev/null
参数说明:
-s:只显示总计,不显示每个子目录-h:人类可读格式2>/dev/null:忽略权限不足的报错信息
输出示例:
0 /bin
100M /boot
...
15G /home
20G /var
3G /usr
从输出可以看出 /var 目录占了 20G,是大头。
2. 继续往下查 /var 目录
du -sh /var/* 2>/dev/null | sort -rh | head -10
参数说明:
sort -rh:按大小倒序排列head -10:只显示前10个最大的
输出示例:
15G /var/log
3G /var/lib
1G /var/cache
...
继续往下查,直到找到具体是哪个文件最大。
第三步:查找最大的单个文件
如果目录太大不好定位,直接找整个系统里最大的文件:
1. 查找大于100M的文件
find / -type f -size +100M -exec ls -lh {} \; 2>/dev/null | awk '{print $5, $9}'
参数说明:
-type f:只找文件,不找目录-size +100M:找大于100M的文件2>/dev/null:忽略权限报错
2. 按大小排序显示前20个最大文件
find / -type f -size +10M -exec ls -lh {} \; 2>/dev/null | sort -k5 -rh | head -20
这样就能列出系统里最大的20个文件,一目了然。
常见的磁盘占用大户
根据经验,Linux 磁盘占用大通常是这几个地方:
1. 日志文件(/var/log)
这是最常见的。服务跑久了日志文件会越来越大,尤其是:
- Nginx 访问日志、错误日志
- MySQL 慢查询日志、错误日志
- 系统日志 messages、syslog
排查方法:
du -sh /var/log/* | sort -rh | head -10
2. 已删除但仍被进程占用的文件
有时候你删掉了大文件,但磁盘空间没释放,因为还有进程在占用这个文件的句柄。
排查方法:
lsof | grep deleted
如果看到很多 deleted 状态的文件,说明有进程占用着已删除的文件。重启对应的进程就能释放空间。
3. 缓存文件(/var/cache)
yum 下载的缓存包、APT 的缓存都在这里,时间久了会积累很多。
清理方法:
yum clean all
4. Docker 镜像和容器
如果用了 Docker,镜像、容器、日志都会占很多空间。
排查方法:
docker system df
清理方法:
docker system prune -a
安全清理方法
找到大文件后,不要直接 rm -rf 删了就完事,要注意安全:
1. 日志文件:清空而不是删除
如果是日志文件,不要删文件本身,而是清空内容:
> /var/log/nginx/access.log
或者:
echo "" > /var/log/nginx/access.log
这样文件还在,但内容清空了,不会影响正在写入的进程。
2. 大文件:先确认再删除
删之前一定要确认这个文件是不是真的不需要了:
ls -lh /path/to/file
head -20 /path/to/file # 看看内容是什么
确认没问题再删:
rm -f /path/to/file
3. 已删除但被占用的文件
如果删掉文件后空间没释放,找到占用的进程并重启:
lsof | grep deleted
# 找到对应的 PID,重启服务
systemctl restart nginx
常见坑
坑1:用 du 查到的大小和 df 不一致
有时候 df 显示磁盘满了,但 du -sh /* 加起来远没到那个数。这通常是因为:
- 有已删除但仍被进程占用的文件
- 挂载点下还有其他挂载
解决: 用 lsof | grep deleted 找被占用的已删除文件,重启对应进程释放空间。
坑2:删了文件空间没释放
这就是上面说的坑——文件被进程占用着,虽然删了但空间没释放。必须重启进程才能释放。
坑3:直接删日志文件导致服务异常
很多人直接 rm -f /var/log/nginx/access.log,结果 Nginx 还在往这个已经不存在的文件里写,日志就丢了。正确做法是清空内容而不是删除文件:> /var/log/nginx/access.log。
总结
排查磁盘占用的标准流程:
df -h看哪个分区满了du -sh /* | sort -rh找最大的目录find / -type f -size +100M找最大的文件- 确认文件用途后再清理
- 日志文件清空内容,不要直接删文件
日常运维建议配置 logrotate 自动切割日志,避免日志越积越大。
遇到问题加QQ23979811 协助处理