前几天我清理服务器磁盘,df -h 一看,根目录用了 89%。我习惯性地 cd / 然后 du -sh * 一个个排查。

扫到 /lost+found,占用 0 字节。

用了这么多年 Linux ,每次 ls / 都会看到这个文件夹。但我从来没有打开过它,甚至从来没有想过它到底是干嘛的。

但我也从来没有动过删它的念头,因为不敢,怕删了会出问题。我猜你也是。

这很奇怪。一个我从来没用过的文件夹,一个占 0 字节的文件夹,一个我甚至不知道里面装过什么的文件夹,到底是什么东西?它的存在意义是什么?

这事要从 1970 年代的 Unix 讲起。

那时候的磁盘不像现在这么靠谱。硬盘是会坏的,磁道是会花的,文件系统是会莫名其妙崩掉的。你正在写论文,啪一下断电了,重启之后发现昨天写的第三章变成了乱码。甚至整个文件都没了。

Unix 的开发者们面临一个很具体的问题,磁盘坏了以后,文件怎么办?

不是「怎么修好磁盘」这种大问题。它更小、更尴尬,有些文件,数据还在磁盘上,inode 也还在,但它没有名字了。

一个文件在 Unix 文件系统里,由两部分组成,inode 和数据块。inode 存的是文件的元信息,权限、大小、指向数据块的指针。文件名不在 inode 里。文件名存在目录项里,目录项指向 inode。

正常情况下,文件名 → 目录项 → inode → 数据块,这条链路是完整的。

但磁盘出问题的时候,可能会出现一种情况,inode 和数据块都完好无损,但目录项丢了。也就是说,文件的数据还在磁盘上结结实实写着,只是文件系统「忘了」它叫什么、放在哪个目录里了。

它变成了一个孤儿。

打开网易新闻 查看精彩图片

有数据、有 inode、但没有名字。就像一个小孩站在商场里,他知道自己是谁,但找不到爸妈,也说不出家在哪。

这时候你就需要一个失物招领处。

这个失物招领处,就是 lost+found。

Unix 里有个命令叫 fsck(file system check),专门用来检查和修复文件系统。当你非正常关机、或者磁盘出了问题,系统启动时会自动跑 fsck。

fsck 会扫描整个文件系统,找出那些「有 inode 但没名字」的孤儿文件。找到了以后,它把这些孤儿文件放进一个专门的目录里,重新给它们一个名字,通常是那个 inode 的编号,比如 #123456。

这样你至少能找回数据了。虽然你不知道这个文件原来叫什么,但你可以 cat #123456 看看里面是什么。

这个「专门的目录」,就是 lost+found。

好,到这里一切都很合理。文件系统坏了,有个工具帮你把孤儿文件收容到一个目录里,你回头自己去认领。

但有一个问题。

这个 lost+found 目录,是什么时候创建的?

你的第一反应可能是,fsck 运行的时候,发现需要用到这个目录,顺手建一个不就行了?

不行。

原因很残酷,当文件系统真的坏到需要用 lost+found 的时候,它很可能已经连创建新目录的能力都没有了

你想想,文件系统损坏是个什么状态?inode 表可能乱了,空闲空间位图可能坏了,目录结构可能裂了。在这种状态下,你让 fsck 去「顺手建个目录」。它可能根本找不到空闲的 inode,或者写目录项的时候发现那块磁盘已经读不出来了。

这就像你让一个正在心梗发作的人自己走到急诊室。他不是不想走,他是走不动。

所以 Unix 的设计者做了一个非常反直觉的决定,在一切都还正常的时候,提前把急救室建好。

怎么建?在创建文件系统的时候,mkfs(make file system)会在根目录下预留一个 lost+found 目录,提前分配好 inode 和足够的目录项空间。这个目录是空的,但它占着位置。

fsck 出问题的时候不需要「创建」lost+found。它只需要「往里放东西」。这就像医院在没有病人的时候就把急诊室建好、把设备摆好、把氧气接好。不是浪费,是等不起。

这就是为什么你不能删 lost+found。

不是因为它里面有什么重要的东西。大多数时候它里面什么都没有。是因为万一真出了事,文件系统需要这个「预留的急救位」。你删了它,下次磁盘出问题的时候 fsck 可能会告诉你,我找到了 47 个孤儿文件,但我没地方放它们。

那就真的 lost 了,没有 found。

还有一个更反直觉的事儿。

你现在的电脑上很可能没有 lost+found。

如果你用的是 macOS 的 APFS 文件系统,没有。如果你用的是 Windows 的 NTFS,没有。如果你用的是 ZFS 或 Btrfs,也没有。

lost+found 是 ext 系列文件系统的专属设计。ext2、ext3、ext4,这些世界上使用最广泛的文件系统(因为 Linux 服务器绝大多数用的是 ext4),至今保留着这个从 1970 年代传下来的机制。

而新一代的文件系统,比如 ZFS 和 Btrfs,用了一种完全不同的思路。它们不靠事后修复,而是靠「写时复制」(Copy-on-Write)和校验和来防止文件系统损坏。数据永远不会被原地覆盖,每一次写入都是写到新位置。如果写入过程中断电了,旧数据还在原地完好无损。不存在「孤儿文件」这个概念。

所以在 ZFS 和 Btrfs 的世界里,lost+found 是不需要的。它们的「急救」机制是预防性的,不是修复性的。

但 ext4 不行。ext4 是传统的日志文件系统,它还是会原地写数据。日志只能保证文件系统元数据的一致性,不能保证数据块本身不出事。所以 lost+found 这个急救箱,对 ext4 来说至今仍然有意义。

你看,同一个问题,「磁盘坏了怎么办」,两代文件系统给出了两种答案。

打开网易新闻 查看精彩图片

老式修复和新式写时复制的对比

老一代的答案是「坏了再修,提前准备好修的工具」。新一代的答案是「不给你坏的机会」。

不能说哪个更好。ext4 简单、稳定、性能好,全球无数服务器在跑。ZFS 和 Btrfs 更强壮,但复杂度和资源消耗也更高。选哪个,取决于你更怕修不好,还是更怕跑不动。

说回 lost+found。

我后来去翻了一下我服务器上那个 0 字节的 lost+found。用 ls -la /lost+found,确实是空的。但它的存在本身,就是一句话,

「我知道你可能永远不会用到我。但如果有一天你需要我,我希望我已经在这里了。」