磁盘与 inode 诊断
目标
从数据块和 inode 两个维度分析磁盘容量问题,亲手制造并诊断‘明明删除了,容量却没有减少’的情况,然后完成恢复。
为什么重要
No space left on device 并不只表示‘没有数据块’,而是表示‘内核缺少接受这次写入所需的资源’。这种资源可能是数据块、inode,也可能是扣除 root 预留部分后的可用空间。因此必须同时查看 df -h 与 df -i;如果 df 与 du 的结果不一致,则应怀疑存在已删除但仍被打开的文件。第 5~6 步制造的情况尤其常见于实际工作——**而且在这种情况下,一旦重启进程,恢复机会也会随之消失。**操作顺序本身就是能力。
步骤
在 /root/disk 目录中工作。
- 把
/root所在文件系统的 inode 使用率(%)以纯数字形式写入/root/disk/inode_pct.txt。 - 把
/etc目录的实际使用量以纯 KB 数字写入/root/disk/etc_kb.txt。 - 在
/usr/bin直属的普通文件中,找出最大的一个,把它的文件名写入/root/disk/biggest.txt。 - 创建
/root/disk/many目录,并放入正好 500 个大小为 0 的文件。再将该目录的du -sk值写入/root/disk/many_kb.txt。 - 创建至少 10MB 的
/root/disk/ghost.log,让某个进程持续打开该文件,然后只删除文件名。把该进程的 PID 写入/root/disk/ghost_pid.txt。评分时该进程必须仍然存活。 - 将第 5 步进程仍持有的文件内容恢复到
/root/disk/recovered.log。大小必须与原文件相同。 - 创建
/root/disk/findghosts.sh <최소바이트>。在整个系统中查找已删除但仍处于打开状态、且大小不低于该值的文件,按pid=<PID> bytes=<크기>格式逐行输出。 - 创建
/root/disk/diskreport.sh <디렉터리>。用以下两行输出该目录整个子树中普通文件的数量和总字节数。目录不存在时必须以非 0 退出码结束。files=<개수>bytes=<합계>
提示
- 使用
readlink /proc/<PID>/fd/<N>可以查看 fd 指向什么。已删除文件的末尾会带有(deleted)。 stat -L -c %s /proc/<PID>/fd/<N>会跟随符号链接并报告实际大小。- 使用
find "$d" -type f -printf '%s\n'可以获取大小列表并求和。 - 常见错误 1:第 5 步中打开文件的进程一旦结束,幽灵文件就会消失,导致第 6~7 步全部失败。
- 常见错误 2:第 7 步要注意不要统计
/proc/self或评分器自身的 fd。
读取 inode 使用率
把 /root 所在文件系统的 inode 使用率(%)以纯数字形式写入 /root/disk/inode_pct.txt。
df 有一个专门显示 inode 而不是数据块的选项。去掉 % 符号,只写数字。
测量目录实际使用量
把 /etc 目录的实际使用量以纯 KB 数字写入 /root/disk/etc_kb.txt。
du 会遍历路径并统计实际占用的数据块。有一组选项可以用 KB 为单位汇总。
查找最大的文件
在 /usr/bin 直属的普通文件中,找出最大的一个,把它的文件名写入 /root/disk/biggest.txt。
使用 find 的 -printf 同时输出大小和名称,再进行排序。这里只需要文件名,而不是路径。
创建 500 个空文件
创建 /root/disk/many 目录,并放入正好 500 个大小为 0 的文件。再将该目录的 du -sk 值写入 /root/disk/many_kb.txt。
可以用花括号展开或 seq 一次创建。请确认虽然内容为 0 字节,du 的结果却不是 0。
创建已删除但仍打开的文件
创建至少 10MB 的 /root/disk/ghost.log,让某个进程持续打开该文件,然后只删除文件名。把该进程的 PID 写入 /root/disk/ghost_pid.txt。评分时该进程必须仍然存活。
先创建文件,让某个进程持续打开它,再只删除名称。tail -f 很合适。
恢复幽灵文件
将第 5 步进程仍持有的文件内容恢复到 /root/disk/recovered.log。大小必须与原文件相同。
/proc//fd/<编号> 是指向该文件的符号链接。直接复制这个路径即可。
幽灵文件检测脚本
创建 /root/disk/findghosts.sh <최소바이트>。在整个系统中查找已删除但仍处于打开状态、且大小不低于该值的文件,按 pid=<PID> bytes=<크기> 格式逐行输出。
对 /proc//fd/ 执行 readlink,只选择以 (deleted) 结尾的项。使用 stat -L 测量大小。
递归容量汇总脚本
创建 /root/disk/diskreport.sh <디렉터리>。用以下两行输出该目录整个子树中普通文件的数量和总字节数。目录不存在时必须以非 0 退出码结束。
files=<개수>bytes=<합계>
使用 find 查找普通文件,并计算数量与大小总和。不存在的目录应按错误处理。