type: learning-note
title: Linux:块 2 产出日------六天内容整块复现
date: 2026-09-30
description: FHS/inode/链接/挂载/df-du/apt 六天整块复现;含今天纠正的点(/var 与 /usr、inode 六类、文件名存目录、mount 四段、du 总计行、apt 预览三样)、旧知识回收与产出验收
2026-09-30 学习笔记
> 📌 GitHub:https://github.com/AR-firefly
笔记区
核心观点
**`/var` = variable(会变的),不只是日志**
`man hier` 第 340 行原文:This directory contains files which **may change in size**, such as spool and log files.(放**大小会变**的文件,比如排队任务和日志)。
`ls /var` 那 13 个条目------`cache` `log` `spool` `lock` `mail` `crash`------**全是会变的**,日志只是最常打交道的那个。`man hier` 里 `/var` 那些子项,描述清一色以 "**Variable** data" / "**Variable** state" 开头。
**`/usr` 的词源有两种说法**
**原始来源 = user**------Unix 早期命名爱省元音(`ls`、`cmp`、`mv`),`user` 缩成 `usr`。Kernighan & Pike《The Unix Programming Environment》(1984) 里称它 "user filesystem"
**FHS 为什么这么分**
**FHS = Filesystem Hierarchy Standard**(文件系统层次标准),`man hier` 末尾 STANDARDS 节写着 "Version 3.0, published March 19, 2015"。
**为什么要它**:一个软件(比如 nginx)写出来得能装到**所有** Linux 上,它必须知道"配置写哪、日志写哪、程序放哪"。**有统一标准,软件写一次到处能装。**
**inode 里存哪六类 + 文件名存哪**
| inode 里存 | `stat` 输出里对应的行 |
| -------------------------- | ------------------------------ |
| 对象类型 + 权限模式 | `regular file` + `-rw-r--r--` |
| 用户和组所有权 | `Uid:` `Gid:` |
| 逻辑大小与已分配数据块统计 | `size:` / `Blocks:` |
| 硬链接数 | `Links:` |
| 访问、修改、状态变更时间戳 | `Access` / `Modify` / `Change` |
| 指向文件数据的引用 | 内容在磁盘的哪一块 |
**它不存什么**:**文件名**。文件名存在**目录**里------目录的"内容"就是一张「**名字 → inode 号**」的对照表。鸟哥 7.1.4 原文:「inode 本身并不记录文件名,文件名的记录是在目录的 block 当中。」
**一个文件的东西分三处放**:内容 → **数据块**;档案信息 → **inode**;名字 → **目录**。
**`stat` 里的 `File:` 那行不是 inode 里的**------它是从**敲进去的参数**来的。实测 `cd /etc && stat passwd | head -1` 打 `File: passwd`,`stat /etc/passwd | head -1` 打 `File: /etc/passwd`,而 `stat -c "%i"` 两个都是 **15300**。
→ **名字只是外面套的一层标签,inode 号才是身份。**
**硬链接 vs 软链接,一眼判据**
```
327 -rw-r--r-- 2 ... hard.txt
327 -rw-r--r-- 2 ... orig.txt
328 lrwxrwxrwx 1 ... soft.txt -> orig.txt
```
| 看哪里 | 硬链接 | 软链接 |
| ---------------- | ------------------------- | -------------------------- |
| 第 1 列 inode 号 | **和目标的号相同**(327) | **自己独立的号**(328) |
| 第 2 列链接数 | **+1**(2) | **不变**(1) |
| 第 1 列首字符 | `-` | **`l`**,末尾还有 **`->`** |
**数据什么时候真被回收**:链接数 `2` → 两个名字都在;`1` → 还剩一个名字揪着它,**数据还在**;**`0`(一个名字都不剩)** → 系统才把那些字节还给磁盘。**看链接数,不看名字在不在。**
**悬空链接能救回来**:把目标名字重新建出来(`printf '...' > /tmp/lab/orig.txt`),`soft.txt` **立刻复活**------它是"一张写着名字的纸条",名字又有人应了。
**挂载点是什么、为什么被挡住**
`man 8 mount` 原文:The previous contents (if any) and **owner and mode** of dir become **invisible**, and **as long as this filesystem remains mounted, the pathname dir refers to the root of the filesystem on device**.
-
**挂载点** = 你想让这块存储**在哪用**的那个目录(`mount` 不替你创建,**必须先用 `mkdir` 建出来**)
-
**挡住** = 挂上之后,这个路径指的就是**接上来那块文件系统的根**------所以看到的是新文件系统的属主和权限,不是原来那个目录
-
**是 `invisible`(看不见),不是 `deleted`(删掉)**
**实测三现象**:往 `/tmp/mntlab`(里面有 `original.txt`)挂 tmpfs → 目录**变空**、**属主从 `ar-26710` 变 `root`**、权限变 `drwxrwxrwt`;`sudo ls /root` **空**、全盘搜(`find / -xdev -name`)**0 个**;卸下后 `original.txt` **原样回来**(15 字节、内容没变)。
**挂载要 root,但只是为了"建立连接"那一刻**
`man 8 mount`:The root permissions are necessary to **mount** a filesystem by default. 建完之后**访问不需要 root**------实测普通用户 `ls /mnt/c` 照样能读。
**`mount` 四段格式**
```
/dev/sdd on / type ext4 (rw,relatime,discard,...)
└───┬──┘ └┬┘ └─┬─┘ └──┬──┘ └───────┬───────┘
来源 on 挂载点 type 类型 选项
(路标) (路标)
```
-
**`on` 和 `type` 是"路标"**------固定出现、位置固定,**本身不是数据**;`type` 后面那个词才是类型名
-
**第 1 段来源写 `none`** = 没有实体设备(tmpfs、overlay)
-
**第 4 段是"选项"不是"权限"**------`rw`/`ro` 说的是**能不能写**,跟 `rwx` 那套权限是两码事
**`findmnt` 为什么比 `mount` 好**
`man 8 mount`:The listing mode is maintained for **backward compatibility only**. For more robust and customizable output use **findmnt(8)**, especially in your scripts.
`mount` 的输出是**一段文本**------脚本要抠"挂载点"只能**按空格切**。挂载点名字带空格时实测切出 **7 段**(正常 6 段),按位置取就错位;`man` 里还写着控制字符会被替换成 `?`。`findmnt` 输出**表格**(第一行表头、列能挑能换序 `-o`),**不怕空格**。
**`/etc/fstab` 是什么**
**f**ile**s**ystem **tab**le,**开机自动挂载的清单**,**一行一条**。开机时系统读一遍照着挂;`mount -a` 干同一件事(按**行序**挂)。
**六字段**:
| # | 字段 | 写什么 |
| --- | ------ | ------------------------------------------------------- |
| ① | 来源 | 推荐 `UUID=...`;也可 `/dev/sdX` |
| ② | 挂载点 | 挂到哪个目录 |
| ③ | 类型 | `ext4` / `tmpfs` / `9p` ... |
| ④ | 选项 | `defaults` / `ro` / **`noauto`**(`mount -a` 会跳过它) |
| ⑤ | dump | 给老备份工具用,**一律写 `0`** |
| ⑥ | pass | `fsck` 顺序:根 `1`、其他本地盘 `2`、不查 `0` |
**本机 fstab 是空的**(只有一行 `# UNCONFIGURED FSTAB FOR BASE SYSTEM`)------**WSL 不靠它挂东西**,`/mnt/c`、`/mnt/d`、`/usr/lib/wsl/*` 那 40 行挂载全是 WSL 自己在启动时做的,fstab 里**真条目 0 条**。
**"只给一个名字"时 `mount` 会去翻 fstab**------
`man 8 mount`:If only the directory or the device is given ... then mount **looks for a mountpoint** ... **in the /etc/fstab file**.
-
**两个都给**(设备 + 挂载点)→ 直接挂,不看 fstab
-
**只给一个** → 去 fstab 翻
-
只给一个而 fstab 是空的 → **`mount: /tmp: can't find in /etc/fstab.`**(退出码 1)
**磁盘满有两本账**
| | `df -hT` | `df -i` |
| ------------------ | ------------- | ------------ |
| 算哪本 | **数据块** | **inode** |
| 撑爆 100M tmpfs 后 | `Use% = 100%` | `IUse% = 1%` |
**两种满报的是同一句话**(`No space left on device`)------要区分得自己跑 `df` 和 `df -i`。
**为什么一个 100% 一个 1%**:那块盘上**只建了 1 个文件**------块被内容塞满,inode 只用了 2 个(根目录 1 + 文件 1),总数 97 万。**内容多 ≠ 文件多。**
**`du` 逐层定位 + 总计行**
```
$ du -xhd1 ~ | sort -h
52K /home/ar-26710/.cache
100K /home/ar-26710/s1-practice
288K /home/ar-26710 ← 最后一行是【总计】,不是子目录
```
-
**判据**:`du -sh ~` 只打一行 `288K`,跟上面那条的**最后一行一模一样**(`-s` = 只出总计)
-
**父目录的数字包含子目录**,**不能逐行相加**
-
**`du -d1` 只列目录、不列文件**------文件大小算进它所在的目录;要看文件加 `-a`
-
**`| sort -h`**:不带 `-h` 是按**字符**排(实测 `8.0K` 被排到 `52K` 后面)
**定位动作**:从 `~` 看最大的是 `s1-practice` → 进那一层再跑同一命令 → 一层一层往下钻。
**`df` 和 `du` 为什么对不上(五条)**
`df` **读文件系统自己记的账**;`du` **自己走一遍目录树数**。
| # | 原因 | 本机在哪见过 |
| --- | ---------------------------- | --------------------------------------------------------------------------------------- |
| 1 | 进程**开着已删的文件** | 09-24:`df` 70M / `du` 30M,`lsof +L1` 抓到 `(deleted)` |
| 2 | **保留空间 / 元数据 / 日志** | `Avail` 比 `Size − Used` 少 **51G**;`Reserved block count ÷ Block count` = **正好 5%** |
| 3 | 树里**挂着别的文件系统** | `du -hd1 /tmp` vs `du -xhd1 /tmp`;条件不满足时两条一样 |
| 4 | **权限读不进去** | `perm-test` 报 `Permission denied` → `du` 总数**偏小** |
| 5 | **稀疏文件** | 表观 100M、实占 0 |
**apt:装包前那张纸该读的三样**
```
Installing: ← ① 要装哪些(清单)
figlet
...
Summary:
Upgrading: 0 ← 别的包的状态,不是重点
Installing: 1
Removing: 0
Not Upgrading: 51
Download size: 138 kB ← ② 下多少
Space needed: 752 kB ← ③ 占多少
```
**这张纸是 apt 在问"我准备这么干,行不行"**------你敲回车它才动手。要盯的是"**它准备对你机器做什么**":**装什么、下多少、占多少**。
**`dpkg -l` 的状态位**:每行开头两位,表头三行是"指针"------第 1 位 `Desired`(你希望它怎样)、第 2 位 `Status`(实际怎样)、第 3 位 `Err`(坏没坏,**大写 = 坏**)。
**`remove` vs `purge`**
| | 程序文件 | 配置文件 | `dpkg -l` 那行 |
| -------- | -------- | -------- | -------------- |
| `remove` | 删 | **留** | 变 **`rc`** |
| `purge` | 删 | **删** | **整个消失** |
`rc` = **r**emoved + **c**onffiles remain。`man dpkg`:This removes everything **except conffiles** ... which may **avoid having to reconfigure the package if it is reinstalled later**.
**什么时候用哪个**:**以后还想装回来** → `remove`;**彻底不要了** → `purge`。同段还有一句:包**压根不带配置文件**时,`remove` 和 `purge` **同效**。
**孤儿包 & `autoremove`**
**孤儿包** = 当初作为依赖**自动装上**、现在**没有任何包再用它**。`remove toilet` 时 apt 会自己说 `The following packages were automatically installed and are no longer required: libcaca0 toilet-fonts`------**但它不动手**,把决定权留给人。
`man apt-get`(`autoremove` 条):remove packages that were **automatically installed to satisfy dependencies** for other packages and are **now no longer required**.
**先 `--dry-run` 看,再真跑**(`-s` / `--simulate` / `--just-print` / `--dry-run` / `--no-act` 是**同一串别名**)。
关键方法/流程
-
**看挂载**:`mount`(四段文本)/ `findmnt`(表格,可 `-o` 挑列)
-
**挂载**:`sudo mount -t 类型 -o 选项 来源 挂载点`(挂载点要先建)
-
**卸载**:`sudo umount 挂载点`(**少一个 n**)
-
**看某块盘用量**:`df -hT 路径`(块)/ `df -i 路径`(inode)
-
**定位谁占地方**:`du -xhd1 目录 | sort -h` → 进最大的那个 → 再跑一遍
-
**看文件身份**:`stat 文件`(inode 号、链接数、权限、三个时间)/ `stat -c "%i %n" 文件...`
-
**看链接**:`ls -li`(号同不同 / 链接数 / 首字符 / `->`)
-
**查已装包状态**:`dpkg -l | grep 名字`(看状态位 `ii` / `rc`)
-
**装**:`sudo apt install 包名`(**先看那张纸的三样**)
-
**卸**:`sudo apt remove 包名`(留配置)/ `sudo apt purge 包名`(连配置删)
-
**清孤儿**:`apt autoremove --dry-run`(先看)→ `sudo apt autoremove`
实战记录
**① 磁盘满排查:块满 vs inode 满**
```
$ dd if=/dev/zero of=/tmp/fulllab/big.bin bs=1M count=200
dd: IO error: No space left on device
$ df -hT /tmp/fulllab → 100M 100M 0 100%
$ df -i /tmp/fulllab → 974932 2 974930 1%
```
**② 挂载点被遮挡**
```
挂载前: original.txt 在,目录 60 字节、属主 ar-26710
挂上后: 目录空、属主变 root、权限 drwxrwxrwt
卸下后: original.txt 原样回来,cat → hello original
```
**③ `remove` → `purge` 四个证据**
```
装完 ii figlet ... /etc/emacs/site-start.d/50figlet.el 在(290 字节)
remove 之后 rc figlet ... 文件还在
purge 之后 那一行整个消失 ls: No such file or directory
```
线索区(学完后合上材料,自问自答)
**Q: `/var` 放什么?`/usr` 呢?两个词各是什么缩写?**
A: `/var` = **variable**,放**会变的**(日志、缓存、spool、锁);`/usr` 装**软件**。`usr` 原始是 **user** 的省略,现代被重新解释成 Unix System Resources。
**Q: FHS 是什么、为什么需要它?**
A: **文件系统层次标准**。一个软件要能装到所有 Linux 上,必须知道"配置/日志/程序各写哪"------**有统一标准,软件写一次到处能装。**
**Q: inode 里存哪几类?不存什么?**
A: 存**类型+权限 / 属主属组 / 大小与块 / 链接数 / 三个时间 / 内容在哪**;**不存文件名**。
**Q: 文件名存在哪?**
A: **目录里**------目录的内容就是一张「**名字 → inode 号**」的对照表。
**Q: `stat` 输出的 `File:` 那行是从哪来的?**
A: **从敲进去的参数**,不是从 inode 读的。同一个文件用不同路径写,它就显示不同的名字,但 inode 号不变。
**Q: 硬链接和软链接,一眼怎么分?**
A: 看 `ls -li`:**号相同 + 链接数 +1** = 硬;**独立号 + `l` 开头 + `->`** = 软。
**Q: 数据什么时候真被回收?**
A: **链接数归零**(一个名字都不剩)。`1` 的时候数据还在。
**Q: 悬空链接怎么救?**
A: 把**目标名字**重新建出来,链接**立刻复活**(它只是"一张写着名字的纸条")。
**Q: 挂载点是什么?往非空目录上挂,原来的东西去哪了?**
A: 挂载点 = **你想让它在哪用**的那个目录。原来那些东西**哪也没去**------`invisible`(看不见),不是 `deleted`(删掉);卸掉就回来。
**Q: 挂上之后为什么属主变成 root 了?**
A: 因为**你看到的已经不是原来那个目录**,是**接上来那个文件系统的根**------属主和权限是挂载时给这个根设的。
**Q: `mount` 一行的四段是什么?**
A: `来源 on 挂载点 type 类型 (选项)`。`on` 和 `type` 是**路标**,不是数据。
**Q: 脚本里为什么用 `findmnt` 不用 `mount`?**
A: `mount` 输出是**一段文本**,挂载点带空格就切错位(实测 7 段 vs 6 段);`findmnt` 是**表格**,按列取值,不怕空格。
**Q: fstab 是什么?本机为什么是空的?**
A: **开机自动挂载清单**,一行一条。本机是 **WSL**,挂载由 WSL 自己启动时做掉,**不靠 fstab**。
**Q: 只给 `mount` 一个名字会发生什么?**
A: 去 **fstab** 里翻条目;本机翻不到 → `can't find in /etc/fstab.`(退出码 1)。
**Q: 磁盘"满"有哪两种?报的错一样吗?**
A: **块满**和 **inode 满**,报的是**同一句** `No space left on device`;要区分自己跑 `df` 和 `df -i`。
**Q: `du` 输出的最后一行是什么?**
A: **总计**(把上面全加起来的汇总),不是子目录。判据:`du -sh` 那一行跟它**一模一样**。
**Q: `df` 和 `du` 为什么对不上?举三条。**
A: ① 进程开着已删的文件 ② 保留块/元数据 ③ 树里挂着别的文件系统 ④ 权限读不进去 ⑤ 稀疏文件。
**Q: 装包那张纸,该读的三样?**
A: **装哪些(`Installing:` 清单)** / **`Download size`** / **`Space needed`**。`Upgrading` 说的是别的包,不是重点。
**Q: `remove` 和 `purge` 差在哪?怎么看出来?**
A: `remove` 留配置、`purge` 连配置删。看 `dpkg -l` 状态位:`rc` = 包没了配置还在;`purge` 后那行**整个消失**。
**Q: 什么包会被 `autoremove` 盯上?apt 为什么不自己删?**
A: **当初作为依赖自动装上、现在没人依赖**的包。删不可逆,"没人依赖"≠"用不着",**得人点头**。
总结(50字以内,用自己的话概括今天学到了什么)
`/var` 是会变的、inode 不存名字(名字在目录)、挂载点是接上来的那个目录、块满和 inode 满是两本账、`du` 最后一行是总计、apt 先读那份清单。
复习卡片
| 概念 | 必学/了解 | 一句话 | 场景 |
| -------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------- | ------------------ |
| `/var` | 必学 | **variable**,放会变的东西(日志/缓存) | 认目录 |
| `/usr` | 必学 | 装**软件**;`usr` 原始=user,现代解作 Unix System Resources | 认目录 |
| FHS | 必学 | **文件系统层次标准**,软件写一次到处能装 | 理解"为什么这么分" |
| inode 六类 | 必学 | 类型权限/属主属组/大小块/链接数/三时间/内容在哪 | `stat` 读数 |
| inode 不存名字 | 必学 | 文件名在**目录**里(「名字 → 号」对照表) | 理解改名不变号 |
| `stat` 的 `File:` | 必学 | 来自**敲进去的参数**,不是 inode | 看输出别被骗 |
| 硬链接判据 | 必学 | 号相同 + 链接数 +1 | `ls -li` |
| 软链接判据 | 必学 | 独立号 + `l` + `->` | `ls -li` |
| 链接数归零才回收 | 必学 | `1` 时数据还在,`0` 才还给磁盘 | 删文件 |
| 悬空链接可救 | 必学 | 把目标名字建回来,立刻复活 | 断链 |
| 挂载点 | 必学 | 你想让它在**哪用**的那个目录,**必须先存在** | `mount` |
| `invisible` 不是 `deleted` | 必学 | 原内容被**挡住**、不是删掉;卸掉就回来 | 非空目录挂载 |
| 挂载只要建那刻的 root | 必学 | 建完之后访问不需要 root | 权限判断 |
| `mount` 四段 | 必学 | `来源 on 挂载点 type 类型 (选项)`;`on`/`type` 是路标 | 读输出 |
| `none` 来源 | 必学 | 没有实体设备(tmpfs/overlay) | 认输出 |
| `findmnt` | 必学 | 表格输出,不怕空格,脚本里用它 | 排障/写脚本 |
| `umount` | 必学 | **少一个 n**,按挂载点卸 | 卸载 |
| `/etc/fstab` | 必学 | **开机自动挂载清单**,一行一条 | 开机挂载 |
| fstab 六字段 | 必学 | 来源/挂载点/类型/选项/dump(0)/pass(1,2,0) | 读 fstab |
| 本机 fstab 空 | 必学 | WSL 自己挂,不靠 fstab | 理解报错 |
| 磁盘满两种 | 必学 | 块满 / inode 满,**报同一句** | 排查 |
| `df -hT` / `df -i` | 必学 | 看块 / 看 inode | 排查第一步 |
| `du -xhd1 \| sort -h` | 必学 | 逐层定位标准动作 | 找谁占地方 |
| `du` 最后一行是总计 | 必学 | 判据:`du -sh` 跟它一样 | 别答错 |
| `df`/`du` 对不上 | 必学 | 五条:删了没关/保留块/子挂载/权限/稀疏 | 对不上时 |
| 装包预览三样 | 必学 | 装哪些/下多少/占多少 | 按 Y 之前 |
| `dpkg -l` 状态位 | 必学 | 第 1 位期望、第 2 位实际、第 3 位坏没坏 | 查状态 |
| `rc` | 必学 | **r**emoved + **c**onffiles remain | 卸包后 |
| `remove` vs `purge` | 必学 | 留配置 / 连配置删;不带配置的包两者同效 | 卸包选哪个 |
| 孤儿包 | 必学 | 当初自动装上、现在没人依赖 | 清理 |
| `autoremove` | 必学 | 清孤儿;**先 `--dry-run`** | 清理 |
| **了解层(合并一行)** | 了解 | 本轮只带出、没深挖没考:`/proc` 下的内核参数、`mount` 的 `--target`/`--source`、`autopurge`、9p 协议细节、UUID 重格式化会变 | 见到再查 |
旧知识回收(今天暴露出来的)
| 概念 | 一句话 | 出处 |
| ----------------------- | -------------------------------------------------------------------------------- | --------------------------------------------------------- |
| **主组/附加组记在哪** | 主组记 `/etc/passwd` **第 4 段**;附加组记 `/etc/group` **第 4 段** | 09-16 抽考:数量答对,**位置答"不知道"** |
| **`ls -r` 是反向排序** | `ls -r` = reverse **反向排序**(不是"去掉读权限");**敲错不报错**,静静地倒着排 | 09-16 抽考答成"减掉 r 权限";09-22 混过一次、方向正好相反 |
| **`-r` 跨命令三义** | `chmod -r` 去掉读权限 / `ls -r` 反向排序 / `ln -r` 建相对链接 | 同上 |
| **`du` 最后一行是总计** | 判据:`du -sh` 那一行跟它一模一样 | 今天答了总计行当"最大的是谁" |
| **装包预览三样** | 装哪些+`Download size`+`Space needed` | 今天答成"Upgrading + 两样" |
| **`mount` 四段** | 来源 / 挂载点 / 类型 / 选项 | 今天答成"位置/挂没挂上/路径/权限" |
今日产出验收
| 条 | 标准 | 结果 |
| --- | ------------------------------------ | ------------------------------------------------------------------------------------------------------- |
| ① | 讲清 FHS:各目录放什么、为什么这么分 | ⚠️ `/var`/`/usr` 说错、为什么没答 → **已讲已重讲**;符号链接指认全对 |
| ② | 讲清 inode:存什么、和文件名什么关系 | ⚠️ 记得"不含名字",六类说不全、文件名存哪不知道 → **已补全**;名字 vs 身份用反例拧正 |
| ③ | 讲清挂载:挂载点是什么、fstab 管什么 | ✅ 用自己话总结对了("让它在特定的地方也能用");`mount` 四段第一次答错,**重考通过** |
| ④ | 独立用 `df` + `du` 定位一次磁盘满 | ✅ 亲手撑爆、`df -hT` 100% / `df -i` 1%;`du` 逐层 narrowing,第一次被总计行带偏、**换真目录后答对** |
| ⑤ | 会用 apt 装/卸/查一个包 | ✅ 全程亲手;交易预览三样第一次答错,**重考通过**;`remove`→`rc`、`purge`→消失、`autoremove` 清孤儿全对 |
| ⑥ | 交「磁盘与文件系统排查记录」 | ✅ `kb/产出/块2-磁盘与文件系统排查记录.md` 落盘 |