ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

操作系统文件管理:inode、挂载与磁盘空间排查

操作系统文件管理:inode、挂载与磁盘空间排查 文件管理这四个字在操作系统课程里常常是最没存在感的一章。前面讲进程调度还能算算周转时间讲内存管理还能画画页表和地址转换一到文件管理很多人的印象就剩下背概念FCB、inode、连续分配、索引分配、位示图。可真到了工作现场你会发现操作系统里跟你打交道最多的恰恰是文件管理——日志写不进去、磁盘莫名其妙满了、删了文件空间不释放、挂载点一重启就失效、同一份代码在同事机器上权限不对全都落在这套机制上。这篇东西我打算按“原理讲透、实操能抄、坑点说尽”的思路把操作系统的文件管理从概念一路捋到命令行。不管你是正在准备期末考试、对着王道那本书啃索引节点的学生还是天天跟 Linux 服务器、NAS、手机存储打交道的从业者都能从这里拿到能直接用的东西。我会尽量把课本上那些抽象的图翻译成你敲一条命令就能看见的现象同时把教材里不会写、只有踩过坑才知道的细节补上。1. 文件管理到底在管什么从“给数据找个家”说起1.1 文件系统的三层抽象文件、目录、超级块很多人学文件管理第一反应是“文件就是磁盘上的一块数据”。这个理解不算错但太浅。操作系统在中间加了三层抽象才把一块块裸的磁盘扇区变成你能用名字访问的东西最上层是文件它是逻辑上有意义的数据集合用户看到的是名字、大小、修改时间中间层是目录它负责把名字映射到文件的物理位置本质上是“名字到编号”的一张表最底层是超级块和索引节点超级块记录这个文件系统有多大、块多大、inode 有多少个、还有多少空闲索引节点则记录单个文件的元数据和数据块地址。为什么要做这三层因为磁盘只认块号和扇区偏移而人只认文件名。操作系统夹在中间就必须把“按名字找文件”翻译成“按块号读数据”。这个翻译过程要做两件事一是把目录项里记录的名字和 inode 号对应起来二是通过 inode 里的块指针找到真正的数据块。你在终端敲cat /etc/hosts的那一瞬间内核其实做了好几次转换只不过太快了你感觉不到。我特别喜欢拿图书馆做类比。超级块是图书馆的总台账告诉你馆里有多少书架、哪些空着目录是检索卡片柜卡片上写着书名和一个编号inode 是那本书自己的借阅档案记录了它占哪几个书架、谁有权限看、什么时候还数据块才是真正的书页。这个类比虽然粗糙但能帮你记住一件事文件名并不存在 inode 里它存在目录项里。这也是后面硬链接能成立的根本原因一个 inode 可以被多个目录项指向名字可以有好几个档案只有一份。1.2 为什么这件事值得单独花一章讲有人会问现在都云存储、对象存储了还学文件管理干什么。我的判断恰恰相反越是往上抽象底下这层越不能糊涂。你写程序要用fsync保证落盘出事故要判断是数据没刷下去还是权限不对容器镜像的分层联合挂载本质就是文件系统叠加数据库的 WAL 日志、消息队列的刷盘策略全都建立在文件系统语义之上。不懂文件管理你排查线上问题时只能靠猜。更现实一点运维日常里三分之一以上的“疑难杂症”都跟文件系统有关。磁盘报警说 95% 满了du算出来只有 40%应用报“设备上没有空间”df看还有一半空改完配置重启服务挂载点不见了。这些问题的答案全在文件管理的知识里而且都不是什么高深理论就是 inode、目录项、挂载表、打开的句柄这几样东西。把这一章啃下来收益比背十个调度算法高得多。1.3 从“文件管理”这个热词看真实需求在搜索热词里能看到很有意思的组合一边是“操作系统期末复习”“王道操作系统笔记”一边是“小米手机文件管理访问 nas”“安装麒麟操作系统”“ubuntu 20.04 下载”。前面是学生党后面是干活的。这两类人的需求其实可以统一学生需要的是从概念到计算题的通路从业者需要的是从现象到命令的通路。而这两条通路在文件管理这里交汇得特别好因为课本上的 inode 位示图、索引结构全都能在真实的命令行输出里看到。举个例子教材里讲索引节点要用多少个直接指针、多少个间接指针你觉得抽象但只要stat一个文件看它占了几个块、inode 号是多少再配合debugfs或者filefrag看一下块分布抽象的图立刻变成具体数字。反过来运维排查 inode 耗尽问题如果你不懂“每个文件至少占一个 inodeinode 数量在格式化时就定死了”这条原理就只会一直删大文件删到怀疑人生。2. 文件的逻辑结构与物理结构从“怎么组织”到“怎么落盘”2.1 逻辑结构顺序、索引、索引顺序的取舍逻辑结构说的是“站在用户角度看文件内部数据是怎么排的”。最常见的三种顺序文件、索引文件、索引顺序文件。顺序文件最简单记录一个接一个想找第 N 条就从头扫或者估算位置。它的优点是读整块快缺点是想随机插一条记录很痛苦得把后面的全挪一遍。索引文件给每条记录建一张索引表表里存位置查找快但索引本身也要占空间而且记录频繁增删时索引维护成本高。索引顺序文件是折中把记录分组组内顺序排再给每组建一个索引项。查的时候先查索引定位到组再组内顺序找。这个思路你在很多地方都能见到比如数据库的 B 树索引、日志的分段存储、哈希表冲突时的桶内链表。教材上经常拿“学生信息表”举例我建议大家拿更熟悉的东西类比你手机里的联系人就是索引顺序结构——按姓的首字母分组组内再排序你翻通讯录时先跳到 M再往下滑。选哪种结构核心看你的访问模式。如果业务基本上是整块顺序读写比如日志、视频、备份文件顺序结构最省事如果需要频繁按某个键随机读取索引几乎是必然选择因为你不想为一条记录扫完几个 G。这里有个常见误区很多人以为“操作系统里的文件都是顺序结构”其实操作系统层面只保证字节流语义文件内部怎么组织完全由应用决定。数据库文件在操作系统看来就是一大堆字节索引是数据库自己建的跟文件系统没关系。2.2 物理结构三兄弟连续、链接、索引物理结构说的是“文件的数据块在磁盘上怎么放”。这是文件管理里最爱考的部分也是真正影响性能的部分。连续分配最简单粗暴给文件分配一段连续的块。好处是顺序读特别快磁头几乎不用来回移动随机访问也方便第 N 块直接算偏移就行。坏处是碎片和扩展困难文件长大了后面那块地方未必空着你得搬家。链接分配把块散落在各处每个块尾部存一个指针指向下一块。这样扩展特别容易有块就用不用连续。代价是只能顺序访问想读最后一块必须从头顺着走而且指针本身占空间。改进版是 FAT文件分配表把指针集中存到一张表里放在内存查找快很多但表的大小跟磁盘容量成正比大磁盘上这张表很占内存。索引分配是现在的主流给每个文件建一个索引块里面存该文件所有数据块的地址。想读第 N 块查索引块的第 N 项即可随机访问没问题也不会外部碎片。缺点是索引块本身占空间大文件需要多级索引。你现在用的 ext4、XFS、NTFS骨子里都是索引思路只不过为了兼顾大文件和小文件做成了多级混合结构。我用一张表把三者的差异摆清楚考试和实操都用得上。分配方式随机访问扩展性外部碎片典型代表连续分配支持O(1)差需预留或搬迁严重早期系统、部分只读镜像链接分配不支持O(n)好随时追加无FAT32、早期文件系统索引分配支持O(1)好多级扩展无ext4、XFS、NTFS注意教材通常把“链接分配”写成隐式链接把 FAT 叫显式链接。区别在于指针是散在数据块里还是集中在内存表里。答题时别混实操时也别以为 FAT 的随机访问和索引一样快它依然要顺着表跳。2.3 混合索引的地址计算一道必须会算的题多级索引的计算是考试高频点也是理解“为什么单个文件能有几个 TB”的关键。我们按经典模型来假设块大小 4KB每个块地址占 4 字节那么一个索引块能存 4096 ÷ 4 1024 个地址。inode 里有 12 个直接指针、1 个一级间接、1 个二级间接、1 个三级间接。12 个直接指针能寻址 12 × 4KB 48KB一级间接指向一个索引块含 1024 个地址能寻址 1024 × 4KB 4MB二级间接的索引块里每个地址再指向一个索引块能寻址 1024 × 1024 × 4KB 4GB三级间接再乘一层能寻址 1024³ × 4KB 4TB。加起来大概是 4TB 4GB 4MB 48KB。也就是说一个 inode 理论上能描述超过 4TB 的文件。这个数字不是我编的你按上面的乘法自己验一遍就能确认。实际文件系统里参数不同比如块大小 1KB 时每个索引块只能放 256 个地址一级间接就只有 256KB总容量会大幅缩水。这里有个容易被忽略的点小文件根本用不到间接索引甚至用不满一个块。你创建一万个 100 字节的文件每个文件也要占一个 4KB 块除非文件系统支持内联小文件空间利用率低到 2.5%。这就是为什么大量小文件会迅速吃满磁盘和 inode而同样大小的一个大文件反而更省。理解了直接指针和间接指针的分工你就明白为什么 inode 要设计成“前几个指针直接后面才是间接”——因为绝大多数文件都很小直接指针能让它们在寻址时少读一次索引块。3. 目录、索引节点与空闲空间管理文件系统的骨架3.1 从 FCB 到 inode元数据都装了什么早期系统用 FCB文件控制块保存文件的所有信息包括名字、大小、权限、数据块地址。问题在于FCB 要放在目录里目录一大光扫描目录就很慢。于是现代文件系统做了拆分目录项只留文件名和 inode 号其余元数据全部搬到 inode 里。这样目录扫描变得很轻文件名查找效率大大提高。inode 里存什么呢大致包括文件类型、权限位、属主和属组 ID、大小、占用块数、三个时间戳访问、修改、状态变更、链接计数、以及那组数据块指针。注意它不存文件名。你可以用stat命令看一下输出里的 Inode、Links、Blocks 就是这些字段的直接体现。$ stat /etc/hosts File: /etc/hosts Size: 221 Blocks: 8 IO Block: 4096 regular file Device: 803h/2051d Inode: 131074 Links: 1 Access: (0644/-rw-r--r--) Uid: (0/root) Gid: (0/root)Links 这一项就是硬链接计数。新建文件时计数为 1每加一个硬链接加 1每删一个名字减 1减到 0 才真正回收数据块。这一条原理能解释后面很多诡异现象先记住。3.2 硬链接和软链接一个 inode两个名字硬链接和软链接是文件管理里最容易被混淆、也最值得动手试的部分。硬链接的本质是“给同一个 inode 再挂一个目录项”。它不复制数据只是多了一个名字链接计数加一。两个名字地位完全平等删掉任意一个文件依然在只有全删完数据才释放。硬链接有几个限制一般不能跨文件系统因为 inode 号只在单个文件系统内有意义一般不能指向目录否则目录树会变成环。软链接符号链接是另一个文件内容是“目标路径字符串”。它是一个独立 inode有自己的大小指向的目标可以不存在也可以跨文件系统。访问软链接时内核会读它的内容然后按路径重新解析所以多一次跳转开销。$ echo hello a.txt $ ln a.txt hard.txt # 硬链接 $ ln -s a.txt soft.txt # 软链接 $ ls -li a.txt hard.txt soft.txt 131075 -rw-r--r-- 2 user user 6 Mar 1 10:00 a.txt 131075 -rw-r--r-- 2 user user 6 Mar 1 10:00 hard.txt 131076 lrwxrwxrwx 1 user user 5 Mar 1 10:00 soft.txt - a.txt看ls -li的输出a.txt和hard.txt的 inode 号相同131075链接计数是 2soft.txt是另一个 inode131076大小只有 5正好是a.txt这串字符的长度。把a.txt删掉硬链接还能正常读软链接就变成断链ls会标红。这个实验花两分钟做一遍比看十页书都管用。3.3 空闲空间管理位示图、空闲链表与成组链接磁盘上哪些块是空的操作系统必须知道。常见三种做法。位示图用一个二进制位表示一个块1 表示占用0 表示空闲。优点是结构紧凑、查找连续空闲块方便缺点是要扫描才能找到空闲位。算一下1TB 磁盘、4KB 块总块数是 1TB ÷ 4KB 2²⁸ 约 2.68 亿块位示图需要 2²⁸ bit也就是 2²⁵ 字节 32MB。32MB 内存换 1TB 磁盘的管理能力这个买卖很划算所以很多文件系统用位示图或其变体。空闲链表把空闲块串成链表分配时取链首。实现简单但要遍历才能找到连续块而且链表指针存在空闲块本身里块越多越冗余。成组链接法是 Unix 系统的经典方案也是教材爱考的点。它把空闲块分组每组第一块记录下一组的信息和本组空闲块数量形成链式结构。这样既不用一张巨大的位示图常驻内存又能快速找到一批空闲块。考试里常让你算“某个块的回收和分配过程”本质就是模拟这个链式结构的变化。实际操作中你感受不到这么细但有个现象跟它直接相关磁盘碎片随时间增长。因为文件频繁创建删除后空闲块变得零散新写的大文件只能被拆到很多不连续的位置。这不会影响正确性但会影响顺序读性能。所以对性能敏感的磁盘定期整理或者预留空间是有意义的。3.4 inode 数量格式化那一刻就定死了这是运维最容易踩的坑之一inode 总数在格式化时就固定了用完之后即使磁盘还有空间也创建不了新文件。ext4 默认按每 16KB 分配一个 inode1TB 盘大概能建 6700 万个 inode每个 inode 占 256 字节左右光 inode 表就要占十几 GB。如果你的业务是大量小文件比如邮件队列、缓存碎片、会话文件默认值可能不够用。可以用mkfs.ext4 -i 8192把每个 inode 对应的空间从 16KB 降到 8KBinode 数量翻倍代价是 inode 表占的空间也翻倍。反过来如果是存大视频、大镜像的盘可以用-i 65536减少 inode 数量把空间省给数据。$ df -i /data Filesystem Inodes IUsed IFree IUse% Mounted on /dev/sdb1 67108864 320181 66788683 1% /data用df -i看 inode 使用率这是排查“磁盘没满但写不进文件”的第一步。我见过太多人对着df -h的 40% 发愁其实df -i已经 100%。4. 磁盘层面的调度与一致性性能的最后一公里4.1 磁盘调度算法从磁头移动到 SSD 时代机械硬盘时代文件系统把请求交给磁盘后内核的 IO 调度器会重排请求顺序减少磁头来回移动。经典算法有四个FCFS 先来先服务公平但慢SSTF 最短寻道优先选离当前磁头最近的请求可能饿死远端请求SCAN 电梯算法磁头单向扫到底再回头兼顾公平和效率C-SCAN 是单向循环扫描回程不服务进一步均匀化等待时间。拿一个经典请求队列来算请求柱面号 98、183、37、122、14、124、65、67当前磁头在 53向磁道号增大方向移动。FCFS 的总移动量是 640 个柱面SSTF 是 236 个SCAN 大概 299 个。数字差距是实打实的这也是为什么教材执着于这些算法。但今天绝大多数生产环境用的是 SSD没有磁头寻道时间几乎为零这些算法的重要性明显下降。内核里的调度器比如 mq-deadline、kyber、none更多在管请求合并和队列深度。所以我的建议是考试老老实实按课本算工作里如果用的是 SSD直接选 none 或 mq-deadline 就行别花时间调参数。这里“不是所有课本知识都等价于生产实践”分清楚对你是好事。4.2 页缓存、回写与 fsync数据到底什么时候落盘你调用write写文件数据并不是立刻写到磁盘上的。内核先把它写进页缓存标记为脏页然后由后台线程按dirty_ratio、dirty_expire_centisecs这些参数定期刷盘。这样做的原因是磁盘 IO 太慢攒一批一起写效率高得多。代价是断电或者内核崩溃时最近几秒的写入可能丢失。要保证落盘你得显式调用fsync或者用O_SYNC打开文件。数据库之所以强调“两阶段提交 刷日志”就是在跟这个缓存机制打交道。很多人写脚本往里写数据跑完就重启机器回来发现数据少了问题就出在这里。$ cat /proc/sys/vm/dirty_background_ratio 10 $ cat /proc/sys/vm/dirty_ratio 20 $ sync echo 3 /proc/sys/vm/drop_caches # 清理缓存测试用生产慎用注意drop_caches会瞬间让系统 IO 压力飙升生产机器上不要随手执行尤其是数据库服务器。真要测落盘用fio配合fsync更靠谱。4.3 日志与一致性断电那一刻发生了什么如果写数据块写到一半断电文件系统可能处于自相矛盾的状态inode 说文件有 10 个块实际只写了 5 个。为了解决这个问题日志式文件系统ext4、XFS 都有在真正改数据之前先把“打算怎么改”写进日志区提交完成后再改真正的位置最后标记日志完成。如果中途断电重启时扫描日志把没完成的改动重放或回滚。ext4 提供三种日志模式journal记录数据和元数据最安全也最慢ordered只记元数据但保证数据先于元数据落盘是默认值writeback只记元数据不保证数据顺序最快但风险最高。怎么选我的经验是跑数据库、跑事务型业务用默认的 ordered纯缓存盘、临时数据盘可以上 writeback 换性能关键账务数据别省那点性能journal 更稳。# 查看当前挂载参数 $ mount | grep / /dev/sda3 on / type ext4 (rw,relatime,dataordered)这里dataordered就是日志模式。改它需要重新挂载或者改/etc/fstab改之前一定确认业务能接受性能变化别在生产高峰动手。5. 上手实操Linux 下文件管理的常用套路5.1 看懂磁盘与 inodedf、du、stat、ls -i先把最常用的四条命令分清楚。df看的是文件系统层面的统计反映超级块里记的数据du看的是目录层面的累加是遍历出来的stat看单个文件的 inode 信息ls -i直接列出 inode 号。这四者的差别是排查磁盘问题的基本功。$ df -h /data Filesystem Size Used Avail Use% Mounted on /dev/sdb1 500G 180G 295G 38% /data $ du -sh /data/* 2/dev/null | sort -rh | head -5 120G /data/videos 30G /data/images 25G /data/logsdf说用了 180Gdu加起来只有 175G差的 5G 去哪了可能是被删除但仍有进程持有句柄的文件也可能是du没权限读的目录还可能是文件系统保留块ext4 默认给 root 保留 5%。这几种情况后面会详细讲先把“两个数字不一致是常态”这条记下来别一看到对不上就慌。5.2 挂载与 fstab把新盘稳稳接进来新盘接进来大致四步分区、格式化、挂载、写 fstab。每一步都有关键点。# 1. 看清设备名别搞错盘 $ lsblk -f # 2. 分区如果整盘用一个分区可以跳过 $ parted /dev/sdb mklabel gpt $ parted /dev/sdb mkpart primary ext4 0% 100% # 3. 格式化指定块大小和 inode 密度 $ mkfs.ext4 -b 4096 -i 16384 -L data /dev/sdb1 # 4. 用 UUID 挂载比设备名稳 $ blkid /dev/sdb1 $ mkdir -p /data $ mount -o defaults,noatime /dev/sdb1 /data关键点有三个。第一fstab 里用 UUID 不用设备名因为设备名会变插拔硬盘、加装设备后/dev/sdb可能变成/dev/sdc一重启就挂不上甚至挂错。第二noatime能减少大量元数据写入读文件时不更新访问时间对高并发读场景很有用。第三写完 fstab 一定用mount -a测一遍别等重启才发现写错了导致进不了系统。提示如果不小心把 fstab 写错导致系统起不来可以进救援模式注释掉那一行。所以改 fstab 之前先备份一份这是个不到十秒的动作能省你半小时。5.3 权限、属主与 umask为什么你的文件别人改不了Linux 权限是“属主、属组、其他”三组每组读写执行三位。目录的权限含义跟文件不同目录的读权限是“能列出里面有什么”写权限是“能在里面创建删除文件”执行权限是“能进入这个目录”。很多人搞不懂为什么给了目录读权限还是进不去就是因为缺执行位。新建文件的默认权限不是 666 或 777而是被umask削过。常见 umask 是 022那么新建文件权限是 666 ~022 644新建目录是 777 ~022 755。这里的 ~是“按位与上掩码取反”意思是 umask 里为 1 的位被强制清零。想改默认权限就调 umaskumask 027会让同组只读、其他完全没权限适合多用户服务器。$ umask 0022 $ touch f mkdir d ls -ld f d -rw-r--r-- 1 user user 0 Mar 1 10:00 f drwxr-xr-x 2 user user 4096 Mar 1 10:00 d特殊权限位也值得记一笔setuid让程序以属主身份运行passwd命令就是靠它setgid在目录上让新建文件继承目录属组sticky位在共享目录上保证只有文件属主能删自己的文件/tmp就是 1777。这几个位在权限字符串里分别显示为属主执行位的小写 s、属组执行位的小写 s、其他执行位的小写 t。5.4 找大文件、批量清理与安全删除磁盘告急时最实用的几条命令# 找大于 1G 的文件跨文件系统不越界 $ find /data -xdev -type f -size 1G -printf %s %p\n | sort -rn | head -20 # 找 30 天没动过的日志 $ find /var/log -type f -name *.log -mtime 30 -print # 确认无误后再删先打印再执行 $ find /var/log -type f -name *.log -mtime 30 -delete我强烈建议养成“先打印、后执行”的习惯。先把-delete换成-print看一遍列表确认没误伤再动手。用-exec rm -f {} \;也行但每个文件起一个进程慢-exec rm -f {} 会批量传参快很多或者用xargs$ find /var/log -type f -name *.log -mtime 30 -print0 | xargs -0 rm -f-print0配合xargs -0是为了处理文件名里有空格、换行的情况。别小看这个细节我见过文件名里带空格的日志用普通xargs直接被拆成好几个参数删错文件。6. 跨平台与真实场景Windows、手机、NAS、服务器6.1 Windows 与 Linux 的文件管理差异对照两个系统的文件管理思路差别不小混用的时候容易翻车。我用一张表对照。维度LinuxWindows路径分隔符/\也接受/大小写严格区分默认不区分文件系统ext4、XFS、BtrfsNTFS、exFAT元数据inode 独立存储MFT 主文件表链接硬链接、软链接快捷方式、硬链接NTFS 支持权限模型属主/属组/其他 ACLACL 为主挂载方式挂到目录树盘符 C: D:最容易出问题的是大小写。你在 Linux 上写Readme.md在 Windows 上写成README.md可能照样能读到因为不区分反过来在 Windows 上传到 Linux 服务器就可能找不到文件。跨平台开发时统一用小写文件名能避开一大半麻烦。另一个坑是换行符Windows 用 CRLFLinux 用 LF脚本从 Windows 拷过去可能报\r: command not found用dos2unix或者sed -i s/\r$//处理一下就好。6.2 手机文件管理访问 NAS协议和权限的坑现在很多人用手机的文件管理去连家里的 NAS图个方便。这类需求背后其实就是 SMB、NFS、WebDAV 这几套协议在跑。真正常见的坑有三个。第一是协议版本不匹配。老 NAS 可能只开 SMB1新手机默认用 SMB2/3连不上或者连上很慢。解决办法是在 NAS 端开启 SMB3或者在手机端选择兼容模式。第二是账号权限。手机端往往用的是匿名访客或者只读账号想上传就被拒绝需要在 NAS 上给对应账号分配写权限。第三是字符编码中文文件名在旧系统上可能显示成乱码一般把服务端编码统一到 UTF-8 就能解决。从文件管理原理角度看这些都不是玄学协议版本决定双方怎么协商读写请求权限决定服务端愿不愿意执行写操作编码决定字节流怎么翻译成字符。理解了这一层排查时你就知道该往哪个方向看而不是反复重启路由器。6.3 容器与云时代的文件管理变化容器把文件管理又往上叠了一层。镜像是一层层的只读文件系统容器启动时在最上面加一个可写层读写通过联合挂载OverlayFS合并呈现。所以在容器里删一个大文件镜像层里的数据其实还在只是被上层标记为“已删除”这就是为什么容器镜像层数越多、体积越膨胀。绑定挂载bind mount也很常见把宿主机的目录直接挂进容器两边看到的是同一份数据。这时候要特别注意权限和 UID 映射宿主机上文件属主是 1000容器里跑的进程如果是 root写出来的文件属主会变来回一折腾权限就乱了。我的经验是容器里尽量用非 root 用户运行并且把 UID 和宿主机对齐能少掉很多麻烦。7. 常见问题与排查实录7.1 空间满了但 du 算不出来最典型的一种删掉了一个正在被进程写入的大日志df显示空间没释放du又找不到这个文件。原因是文件被删后目录项没了但进程还持有文件句柄inode 和数据块都还没回收。$ lsof L1 | head COMMAND PID USER FD TYPE DEVICE SIZE/OFF NLINK NODE NAME nginx 1234 root 2w REG 8,17 2147483648 0 131075 /var/log/nginx/access.log (deleted)看到(deleted)就说明是这个原因。解决办法是重启对应进程或者用 /proc/1234/fd/2清空句柄指向的文件谨慎有些程序会继续写。更根本的解决是给日志加轮转用 logrotate 定期切分避免单个文件无限增长。7.2 inode 耗尽磁盘明明还有空间现象是创建文件报No space left on device但df -h显示空间充足。第一反应应该是df -i。常见于缓存目录、邮件队列、临时会话目录这些小文件每个都要占一个 inode。$ df -i /var/spool Filesystem Inodes IUsed IFree IUse% Mounted on /dev/sda2 1310720 1310720 0 100% /var/spool解决办法是清理小文件找出哪个目录文件最多$ find /var/spool -xdev -type f | sed s#/[^/]*$## | sort | uniq -c | sort -rn | head长期方案是重新格式化加大 inode 密度或者把这类目录单独分一个卷避免拖累整个文件系统。7.3 权限拒绝但权限看着没问题有时候ls -l看着权限正常就是访问不了。几个常见原因父目录缺少执行位导致无法穿越SELinux 或 AppArmor 策略拦了看ls -Z和审计日志挂载参数里有noexec、nosuid导致程序起不来文件系统以只读方式挂载mount输出里有ro。排查顺序建议是先看mount输出确认挂载参数再看namei -l /path/to/file看每一级权限最后看安全模块日志。$ namei -l /data/app/config.ini f: /data/app/config.ini drwxr-xr-x root root / drwxr-xr-x root root data drwx------ app app app -rw-r----- app app config.ini这样一眼就能看出是哪个环节卡住了。namei这个工具很多人不知道但排查路径权限问题特别顺手。7.4 常见问题速查表把上面这些整理成一张表出问题时按图索骥会快很多。现象常见原因关键命令磁盘满但 du 对不上已删除句柄未释放、保留块lsof L1、tune2fs -l写文件报无空间inode 耗尽df -i重启后挂载失效fstab 用设备名或写错blkid、mount -a权限拒绝但权限正常父目录无执行位、安全模块namei -l、ls -Z文件名乱码编码不一致locale、convmv删文件很慢文件多、目录大rsync --delete替代跨平台脚本报错CRLF 换行dos2unix提示rm -rf删除几十万小文件时特别慢因为它要逐个更新目录项。更快的做法是用rsync -a --delete 空目录/ 目标目录/让 rsync 批量处理速度能快好几倍。8. 从课本到实操把文件管理串成一条线8.1 高频考点速记如果你是在备考把下面几条吃透选择题和计算题基本能覆盖大半。文件与文件系统的关系文件系统负责把逻辑文件映射到物理块目录项存名字和 inode 号inode 存元数据和块指针分配方式三选一的优缺点以及多级索引地址容量的计算位示图大小的计算记住公式“块数 ÷ 8 字节”磁盘调度算法的手算重点是移动总量和方向文件共享的两种链接方式及其区别。计算题里最容易错的是单位换算。块大小 4KB 是 4096 字节一个地址 4 字节那么一个索引块放 1024 个地址这个 1024 千万别算成 1000。1TB 等于 2⁴⁰ 字节4KB 等于 2¹² 字节相除得 2²⁸ 块位示图占 2²⁵ 字节即 32MB。把这几组幂次关系记住考场上能省大量时间。8.2 把知识变成手感我更建议的做法是每学一个概念就去机器上找对应现象。学 inode 就stat一个文件学硬链接就ln一个再删原文件试试学挂载就找台虚拟机加块盘挂上去学日志模式就去改fstab里的data参数做对比测试。这些操作加起来不到两小时但形成的记忆比背书牢固得多。尤其是索引结构那块你可以在虚拟机里用dd造一个几百 MB 的文件然后stat看它占了多少块再用filefrag -v看块的分布情况。你会发现大文件的块号分布并不连续这正好印证了索引分配和空闲空间管理的实际效果。这种“课本上的图在屏幕上活过来”的体验是单纯刷题给不了的。最后分享一个我自己用了很多年的小习惯每台新配的机器格式化完盘之后我会立刻记三件事——文件系统类型、块大小、inode 总数和使用率。写在一个简单的文本里放在/root下。等到半年后磁盘报警翻出来一看就知道当初是怎么规划的不用靠猜。文件管理这东西原理不难难的是把原理和现场对上号而这本小账本就是我对号入座的起点。
返回列表