文件系统深入:inode、软硬链接与高效查找

文件系统相关的故障往往最反直觉:df -h 明明有空间却写不进去、删了大文件空间却没变、文件名带特殊字符删不掉。这篇从 inode 机制讲起,把这类问题的原理和解决办法收在一起。

一、inode:文件系统里最被低估的概念

文件在磁盘上分两部分:inode(存放元数据:权限、属主、大小、指向数据块的指针)和数据块(真正的内容)。文件名只是 inode 的一个”门牌”。

1
2
3
ls -i 文件名        # 查看 inode 号
stat 文件名 # inode 的完整元数据
df -i # 看 inode 使用率(IUse% 是否 100%)

经典故障:磁盘有空间但写不进去df -h 还剩 20G,但建文件报 No space left on device——查 df -i,IUse% 100%,全是小文件把 inode 耗尽了。定位小文件最多的目录:

1
find /data -type f | cut -d/ -f3 | sort | uniq -c | sort -nr | head -10

清理或归档这些小文件(通常是日志、缓存、临时文件)即可恢复。inode 或磁盘空间任意一个满,磁盘都无法写入。

二、软链接 vs 硬链接

1
2
ln 源文件 硬链接      # 硬链接:共享同一个 inode
ln -s 源文件 软链接 # 软链接:独立 inode,指向路径
特性 硬链接 软链接
inode 相同 不同
删除源文件 链接依然有效 链接失效(红底白字)
跨文件系统 不可以 可以
目录 不可以 可以

生产中最常用的其实是软链接三件事:

  1. 保持路径不变,解决磁盘不够:数据迁到大盘,软链回原路径,应用无感知;
  2. 代码上线current -> release-20230510,切换即回滚;
  3. 去软件版本号/usr/local/mysql -> mysql-5.7.42

三、find:高段位用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 基本:名称/类型/深度
find ./ -name "*.log" -type f
find ./ -maxdepth 2 -type d

# 按大小:+10M 大于 / -10M 小于 / 组合区间
find ./ -size +10M
find ./ -size +10M -a -size -15M

# 按修改时间:-mtime +7 七天前改过 / -mmin -60 一小时内
find ./ -mtime +7
find ./ -mmin -30 -name "*.txt"

# 按 inode 找(删特殊文件名的文件)
find . -inum 123456 -delete

面试和生产都高频的经典题——删 7 天前的日志:

1
2
3
find /var/log -type f -mtime +7 -exec rm -f {} \;
# 更稳的写法:先 -exec ls -l 复查,确认无误再执行
find /var/log -type f -mtime +7 -exec ls -l {} \;

文件名带空格、特殊字符时用 -print0 + xargs -0 安全处理:

1
find . -name "*.log" -print0 | xargs -0 rm

四、权限规范:三个”绝不做”

  • 绝不做 chmod 777:任何场景都不给全权限,最小权限原则是底线(面试问到”为什么不用 777”就答这条);
  • 绝不拿 -R 递归改系统目录chmod -R / chown -R 只准作用于业务目录,误改 /etc/bin 会直接搞崩系统;
  • 服务文件权限匹配运行用户:nginx 文件归 nginx:nginx、mysql 文件归 mysql:mysql,这是服务能正常读写的前提。

常规权限速查:644 配置文件、755 脚本/目录、600 敏感文件、750 业务私密目录。

1
2
chown -R nginx:nginx /usr/local/nginx/html   # 部署后必做:属主属组对齐
umask # 默认权限由 022 派生:文件 644、目录 755

五、一次”空间不释放”排查实录

现象:删了几个 G 的大日志,df -h 空间一点没变。

排查:

  1. lsof | grep deleted → 找到被删除但仍被进程持有的文件,确认真凶是正在写日志的 java 进程;
  2. 直接重启进程会导致应用短暂中断(不可取)——生产做法:> /proc/<pid>/fd/<句柄号> 清空句柄指向的内容,空间立即释放,应用无感知;
  3. 事后把”日志按天切割 + logrotate 轮转 + 保留 7 天”写进规范,从根上避免大日志长期占用。

文件系统的坑大多是”原理没吃透 + 操作不规范”叠加出来的,把 inode、链接、权限这三块理解透,排障时基本能一眼定位。