服务器磁盘满了,SSH 登录都报错 No space left on device。第一反应就是敲 df -h,但有时候明明显示还有空间,却还是报错——这是 inode 耗尽了。深入了解 df 命令后,发现这个看似简单的工具其实藏着不少门道。
df 的底层实现:statvfs 系统调用
df 命令的核心数据来自 statvfs() 系统调用,它返回文件系统的统计信息:
#include<sys/statvfs.h>intstatvfs(constchar *path, struct statvfs *buf);struct statvfs { unsigned long f_bsize; // 文件系统块大小 fsblkcnt_t f_blocks; // 总块数 fsblkcnt_t f_bfree; // 空闲块数 fsblkcnt_t f_bavail; // 普通用户可用块数 fsfilcnt_t f_files; // 总 inode 数 fsfilcnt_t f_ffree; // 空闲 inode 数 // ...};
关键点在于 f_bfree 和 f_bavail 的区别:
- f_bfree
- f_bavail:普通用户可用的块数(预留了 5% 给 root)
这就是为什么 df -h 显示 Use% 会超过 100% —— root 用户可以继续写入,直到用完那 5% 预留空间。
常用参数详解
-h:人类可读格式 (Human-Readable Format)
df -iFilesystem Inodes IUsed IFree IUse% Mounted on/dev/sda1 655360 655350 10 100% /
这就是 inode 耗尽的典型表现:Use% 只有 90%,但 IUse% 是 100%。大量小文件(比如日志切分、缓存文件)会消耗 inode,即使磁盘空间还充足。
-T:显示文件系统类型
df -h --totalFilesystem Size Used Avail Use% Mounted on/dev/sda1 100G 85G 10G 90% //dev/sdb1 200G 50G 150G 20% /datatotal 300G 135G 160G 45% -
适合快速统计总容量。
实战场景
1. 磁盘空间预警脚本
#!/bin/bash# 监控磁盘使用率,超过阈值发邮件告警THRESHOLD=80df -H | grep -vE '^Filesystem|tmpfs|cdrom' | while read line; do usage=line" | awk '{print (echo "NF}') if [ "THRESHOLD" ]; then echo "警告: {usage}%" | mail -s "磁盘空间告警" admin@example.com fidone
2. inode 耗尽排查
# 查找哪个目录 inode 最多for dir in /*; do if [ -d "(find "count df -h | wc -l127
系统运行久了会有很多挂载点,df 会逐个查询,可能变慢。
常见陷阱
1. 删除文件后空间未释放
rm -f /data/large_file lsof +L1COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEnginx 1234 www-data 3w REG 8,17 50G 123 /data/large_file (deleted)# 重启 nginx 释放空间 df -h //dev/sda1 100G 95G 0G 95% /# 普通用户写入失败 df -h /dev/shmtmpfs 7.8G 0 7.8G 0% /dev/shm
tmpfs 占用的是内存,写入大文件会导致内存不足。生产环境建议限制大小:
mount -o remount,size=2G /dev/shm
Web 实现:浏览器端磁盘监控
虽然浏览器无法直接访问本地磁盘,但可以通过 Web API 实现"虚拟磁盘"概念:
// 使用 Storage API 监控 localStorage 配额async function checkStorageQuota() { const estimate = await navigator.storage.estimate() const usedMB = (estimate.usage || 0) / 1024 / 1024 const quotaMB = (estimate.quota || 0) / 1024 / 1024 const percent = ((estimate.usage || 0) / (estimate.quota || 1)) * 100 return { used: usedMB.toFixed(2) + ' MB', quota: quotaMB.toFixed(2) + ' MB', percent: percent.toFixed(1) + '%', warning: percent > 80 }}// 模拟 df -h 输出function formatDiskInfo(info: DiskInfo): string { const pad = (str: string, len: number) => str.padEnd(len) return [ pad('Filesystem', 20), pad('Size', 10), pad('Used', 10), pad('Avail', 10), pad('Use%', 6), 'Mounted on' ].join(' ') + '\n' + [ pad(info.fs, 20), pad(info.total, 10), pad(info.used, 10), pad(info.avail, 10), pad(info.percent, 6), info.mount ].join(' ')}
深入了解 df 命令后,发现它不只是一个简单的磁盘查看工具。从 inode 耗尽到预留空间,从 NFS 超时到文件占用,每个场景都有对应的排查思路。下次遇到磁盘问题,别只看 Use%,记得 -i 也看看。
Linux du 命令参考
相关工具:内存单位转换器 | 端口检测器