这段时间好几个同事来问我,说背了一堆 Linux 命令,什么 ls、cd、grep、awk 都滚瓜烂熟,可真遇到"磁盘满了但找不到大文件""删除文件后空间没释放""开发板挂不上根文件系统"这种实操问题,还是两眼一抹黑:该敲哪条命令、输出怎么看、下一步查什么,完全没有头绪。我跟他们说,别急着记命令,先把 Linux 文件系统这根主线理顺。命令只是文件系统之上的操作接口,你理解了文件、目录、inode、挂载这几层关系,大部分命令根本不用背,遇到问题自然能顺藤摸瓜。
这篇内容就当作一本"按场景组织的速查手册"来写:以 Linux 文件系统为核心骨架,把常用命令按实际用途重新梳理一遍,包括 VFS 与 inode 原理、挂载链路、权限与属性、空间排查、嵌入式根文件系统这几个高频场景。适合刚入门 Linux 的开发者、需要频繁处理文件的运维人员,以及准备 Linux 面试、想建立系统化知识体系的朋友。
1. 先建立一个直觉:把文件系统想象成一棵倒挂的树
1.1 为什么很多人背了命令却不会解决问题
我观察到的通病是:大家学命令的时候是按"命令字母表"背的,ls 完了背 cd,cd 完了背 cp,cp 完了背 mv。这种学习方式最大的问题是命令之间是孤立的,你记住了每个命令的语法,却没搞清它们操作的对象——文件、目录、块设备这些东西之间是什么关系。一旦问题稍微绕个弯,比如"为什么 df 显示满了但 du 加起来没多少",孤立的知识点就拼不出完整的排查链路。
正确的方式是先建立文件系统的整体模型。Linux 下一切目录都从根目录 / 开始,向下长成一棵倒挂的树:/bin、/etc、/home、/var、/mnt 各自承担不同的职责。普通用户接触到的所有文件、目录、设备节点、进程信息、内核参数,都被抽象成了这棵树上的一批"文件"。命令做的事,无非是对这棵树进行增删改查、移动、复制、权限调整、空间管理。
1.2 文件系统的类型决定了你该怎么挂载和使用
同样是"文件系统"四个字,底层却有很多完全不同的实现。搞清楚它们各自适合什么场景,很多选型问题就不会纠结了(比如 U 盘分区格式选什么、嵌入式设备为什么用 littlefs)。
| 文件系统类型 | 典型用途 | 关键特点 | 使用注意 |
|---|---|---|---|
| ext4 | Linux 常规磁盘分区 | 稳定成熟,支持日志,默认多数发行版主文件系统 | 不跨系统,Windows 原生读不了 |
| XFS | 大规模数据存储、高并发写入 | 单文件 8EiB 上限,在线扩容强,RHEL 系列默认 | 不能直接缩容,删除大量小文件性能略弱 |
| Btrfs | 快照、压缩、子卷管理 | 支持写时复制,功能多 | 复杂度高,对小白不友好 |
| vfat/exFAT | U 盘、SD 卡、跨平台移动盘 | Windows/Linux/macOS 通用 | exFAT 无日志,异常断电容易丢数据 |
| tmpfs | 内存盘,跑临时文件、编译缓存 | 数据在内存,读写极快,重启消失 | 占内存,要控制 size 上限 |
| proc/sysfs/devtmpfs | 内核暴露信息给用户态 | 不在磁盘上,是内核的视图 | 千万不要直接写 proc,除非你在调内核参数 |
| littlefs | 嵌入式 NOR/NAND Flash | 掉电安全、磨损均衡、写放大小 | 容量小,不适合当作常规磁盘文件系统 |
这里特别提示一点:proc、sysfs 这套特殊文件系统并不存在于物理磁盘上,你 ls /proc 看到的一大堆数字目录其实是内核运行时动态生成的。理解这一点,后面看系统状态命令(比如 free、ps)解析 /proc 下的文件时就不会困惑它们的数据从哪来。
2. VFS与inode:为什么说"一切皆文件"不是一句口号
2.1 VFS:让不同文件系统共用一套操作接口
Linux 之所以能用同一套 ls、cat、cp 命令操作 ext4、XFS、NFS、littlefs,靠的是内核里的 VFS(Virtual File System,虚拟文件系统)这一抽象层。你可以把它理解成一个翻译官:用户态进程调用 open()、read()、write() 时,VFS 负责把这些通用请求转译成具体文件系统(比如 ext4 或 littlefs)的实现函数。
这个设计的好处体现得很直接:你在 NFS 网络盘上操作和本地磁盘操作,命令没有任何区别;换个文件系统格式,也不需要改应用代码。正因为有 VFS,前面说的"一切皆文件"的哲学才真正落地——普通文件是文件,目录是文件,块设备节点是文件,socket 也是文件。你甚至可以 cat /proc/cpuinfo 直接看到 CPU 信息,因为在 VFS 眼里那也是一个"文件"。
2.2 inode:文件清单里最重要的隐藏字段
用 ls -l 看文件,你只能看到大小、权限、时间这类信息,但文件真正放在磁盘上的索引信息藏在 inode(索引节点)里。每创建一个文件,文件系统就分配一个 inode,里面记录:文件类型、权限、属主、大小、时间戳、数据块的位置。文件名只是目录项(dentry)里的一个字符串,它和 inode 通过一个数字编号关联。用 ls -i 就能看到每个文件的 inode 编号。
这个设计直接解释了三个操作系统和面试里反复出现的经典问题:
- 为什么硬链接能共享同一份内容?因为两个不同的文件名指向同一个 inode,你可以用 ln 创建硬链接。文件内容的引用计数(链接数)大于 1 时,删除任何一个名字都不会真正释放数据块,只有链接数归零文件才被删除。
- 为什么软链接(符号链接)会失效?因为软链接是自己独立的 inode,它的"内容"是目标路径字符串。目标文件被删,软链接就指向一个不存在的路径,表现为红底白字的链接断裂。
- 为什么 df 和 du 显示的空间不一致?df 统计的是文件系统层面块设备的使用量,包括被删但依然被进程占用的空间;du 统计的是目录树里实际可见的文件大小总和。大文件被删但进程还持有句柄时,df 不减,du 当然也统计不到。
验证硬链接共享 inode 的实操非常简单:
echo "hello linux" > /tmp/a.txt ln /tmp/a.txt /tmp/b.txt ls -li /tmp/a.txt /tmp/b.txt你会看到两条记录的 inode 编号完全相同,而且链接数变成 2。删除 /tmp/a.txt 后 /tmp/b.txt 内容依然完整,因为数据块始终被那个 inode 引用着。
2.3 stat:一条命令看透文件全部状态
快速了解一个文件的完整元信息,用 stat 比 ls 可靠得多:
stat /etc/hosts输出里会显示文件名、大小、块数、inode 编号、硬链接数、访问权限、UID/GID,以及三个时间戳:Access(最后访问时间)、Modify(内容最后修改时间)、Change(元数据最后变更时间)。三个时间戳很容易搞混,我一般这样记:Modify 是文件内容变了,Change 是文件的"身份证信息"变了,比如改了权限、改了属主、硬链接数变化,Change 就会更新。面试官如果问"ctime 是什么",你答"元数据变更时间"比"创建时间"专业得多——因为大多数文件系统并不记录真正的创建时间。
3. 挂载不只是mount命令:从fstab到根文件系统
3.1 挂载的本质:把一块存储"接"到目录树上
很多人以为 mount 就是把分区"打开",其实挂载的本质是建立一个映射关系:把一个文件系统(在某个块设备或网络路径上)关联到当前目录树的一个空目录上。关联之后,你 cd 进这个目录,看到的就是那个文件系统里的内容。卸载(umount)就是把映射关系切断,目录恢复成普通空目录。
这个机制适用于本地磁盘分区,也适用于 NFS 网络目录、USB 设备、ISO 镜像文件。很多时候排错,你要先明白"这块设备挂在了哪个目录",才能判断数据写在哪儿、空间算在谁头上。查看当前所有挂载点:
mount df -hT lsblk -f三条命令各有侧重:mount 列出挂载项和挂载参数,df 显示各挂载点的空间和文件系统类型,lsblk 显示块设备的分区关系和文件系统格式。排查"某目录空间不够"时,先用 df 看它落在哪个挂载点,再用 lsblk 确认底层设备是谁,思路一下就清晰了。
3.2 /etc/fstab 逐字段拆解:为什么开机挂载失败
开机自动挂载不是 mount 命令完成的,而是系统读取 /etc/fstab 一条条执行。每一行由六个字段组成,我按顺序解释一下:
# <device> <dir> <type> <options> <dump> <pass> UUID=8f23-9a2c /data ext4 defaults,noatime 0 2 192.168.1.10:/srv /mnt/nfs nfs defaults,_netdev 0 0前两个字段是"要挂载什么"和"挂到哪里"。第三个字段是文件系统类型。第四个字段是挂载选项,defaults 表示读写、自动挂载、允许设备等常用选项的组合;noatime 可以避免每次读取文件都更新访问时间,对 SSD 和嵌入式 Flash 能明显减少写入磨损;_netdev 表示网络设备,等网络就绪后再挂载,避免开机时网络没起来导致挂载失败卡住启动流程。
第五、六字段平时很少动:dump 是备份标记,0 表示不备份;pass 是 fsck 检查顺序,根分区设 1,其他本地分区设 2,网络文件系统设 0。一个非常常见的坑是:fstab 里写了错误的 UUID 或文件系统类型,开机就会进入 emergency mode。解决办法是用 live 环境或单用户模式登录,把那一行注释掉再重启。
强烈建议 fstab 里写 UUID 而不是 /dev/sda1 这种设备名。设备名会随内核识别顺序变化,UUID 是文件系统创建时生成的全局唯一标识,写入 fstab 后设备名怎么换都不会挂错。可以用 blkid 查询 UUID:
blkid3.3 NFS 和 NAS 挂载:不同协议的命令差异
嵌入式开发和服务器环境里,远程文件系统几乎是日常。NFS 挂载常规写法:
mount -t nfs -o vers=3,nolock,timeo=600 192.168.1.10:/srv/nfs /mnt/nfs这个命令里值得记的是:vers=3 指定 NFS 协议版本。为什么嵌入式调试时经常强制用 v3?一方面很多精简内核或老掉的内核默认只支持 v3,另一方面 v3 不需要额外的 rpcbind/lockd 服务,协议逻辑简单,开发板上更容易调通。timeo=600 是超时时间,网络不稳定的嵌入式环境设短一点可以加快失败重试,不至于让进程长时间卡死。
连接 NAS 或 Windows 共享则要用 CIFS:
mount -t cifs -o username=user,password=pass,uid=1000,gid=1000 //192.168.1.20/share /mnt/nas用 NAS 时踩得最多的坑是权限错乱:Windows 共享服务端解析的用户和 uid 跟本机对不上,挂载后文件属主显示成 nobody 或数字。通过 uid/gid 参数强制映射成你本机的用户 ID,能省掉很多 chown 的麻烦。
关于 Ventoy 做启动盘时分区文件系统类型选哪个的问题,我的建议是:用 exFAT。它的兼容性最好,Windows、Linux、macOS 都能直接读写,也不像 NTFS 那样在 Linux 下需要依赖 ntfs-3g 才能写。ext4 虽然对 Linux 最友好,但拿到 Windows 上完全读不了。当启动盘兼顾 PE、Linux 镜像和日常拷贝文件时,exFAT 是少数不用折腾的选择。
4. 权限与属性:普通权限、特殊权限、属性三层分开记
4.1 普通权限:目录的执行权限到底在管什么
ls -l 第一列的 rwxrwxrwx 大多数人都认识,但目录的 x 权限经常被误解。文件上的 x 表示可执行;目录上的 x 表示"能穿过这道门",也就是说你必须拥有目录的 x 权限,才能 cd 进去、才能访问其中的任何文件。只有 r 权限只能列出文件名,但没有 x 就没法 stat 文件,也打不开文件内容。只有 w 权限不能新建文件,因为创建文件需要在目录里同时有 w 和 x。
遇到"我能 ls 目录但 cat 文件提示无权限"这种问题,基本就是目录缺 x 权限。排查时别只盯着文件本身,沿路径把每一级目录的权限过一遍,很多时候问题出在中间层。
4.2 SUID、SGID、Sticky:三个特殊权限的作用机制
普通权限之外,还有三个特殊权限位,它们是 Linux 安全模型里绕不开的部分,也是面试题常客。
| 特殊权限 | 表示位 | 作用 | 典型示例 |
|---|---|---|---|
| SUID | s 出现在 owner 的 x 位 | 程序运行时临时获得文件属主的身份 | /usr/bin/passwd |
| SGID | s 出现在 group 的 x 位 | 程序运行时临时获得属组身份;目录设置后,新建文件自动继承目录属组 | 团队共享目录 |
| Sticky | t 出现在 other 的 x 位 | 目录里每个人只能删自己的文件 | /tmp |
为什么 /usr/bin/passwd 需要 SUID?普通用户要改密码,必须写 /etc/shadow,但 /etc/shadow 只有 root 能读写。没有 SUID,普通用户根本无法完成这个操作。有了 SUID,用户执行 passwd 时进程的 uid 临时变成 root,于是它可以以 root 身份修改 shadow 文件。这就是为什么 ls -l /usr/bin/passwd 里能看到 rwsr-xr-x。数字表示法里 SUID=4、SGID=2、Sticky=1,所以 chmod 4755 表示添加 SUID,chmod 1777 表示给 /tmp 这类目录加粘滞位。
这里要给一个很实在的安全建议:特意找一下系统里异常带 SUID/SGID 位的文件。恶意提权工具最常见的做法就是把一个程序设置 SUID 后丢到某个目录,你再以 root/普通用户身份运行它,就可能获得超出预期的权限。定期执行下面这条命令检查全盘 SUID 文件是个好习惯:
find / -type f -perm -4000 -ls 2>/dev/null把输出和系统原始情况对比,多出来的文件就要警惕。这个动作放到理解 SUID 机制的语境里,既是排查手段,也是安全的加固手段。
4.3 chattr/lsattr:属性层是最后一道防线
很多人以为 chmod 就管完权限了,其实 chmod 管的是权限位,而 chattr/lsattr 管理文件系统属性(attribute),是更底层的一层防线。最常用的两个属性是 i(immutable,不可变)和 a(append,只可追加):
chattr +i /etc/ssh/sshd_config # 锁住配置文件,root也不能改 lsattr /etc/ssh/sshd_config # 查看属性 chattr -i /etc/ssh/sshd_config # 解除锁定再改配置chattr +i 的效果是:任何人(包括 root)都不能修改、删除、重命名该文件。对重要配置文件如 sshd_config、fstab,加上 i 属性能有效防止误操作和恶意篡改。chattr +a 则只允许追加,不能截断或覆盖已有内容,非常适合挂接日志文件,保证日志只增不减,避免被清空。注意,chattr 只在使用 ext4、XFS 这类 Linux 原生文件系统时有效,在 vfat、NFS 上通常不支持。
5. 磁盘空间与inode:两条"满了"排查的完整链路
5.1 磁盘满但找不到大文件的定位顺序
谈磁盘满之前先记住一个反直觉的事实:df 和 du 统计口径完全不同。df 看的是文件系统块的占用,du 是遍历目录树计算每个文件实际大小。真正排查的顺序应该这样走:
- 用 df -h 确认是哪个挂载点满了;
- 用 du -sh /* 从根目录扫起,一级一级缩小范围;
- 定位到大目录后 du -sh * 排序找出最大文件或目录;
- 如果 du 统计出来明明很小但 df 显示满了,那几乎可以断定有已删除但仍被进程占用的文件。
第 4 步是运维排障里最常见的隐藏坑。程序打开一个日志文件后,运维用 rm 把日志文件删了,但程序还持有文件描述符,空间一直没释放。df 还满着,du 却找不到这个文件。处理方法是找出哪个进程占用:
lsof | grep deleted看到被删除但仍打开的进程后,要么重启进程,要么杀掉进程,空间才会归还。如果暂时不能重启进程,可以用清空代替删除:
: > /var/log/xxx.log # 或者 truncate -s 0 /var/log/xxx.log这样文件描述符还指向同一个文件,但文件内容清空了,空间立即释放。这是处理"不能停服务但必须释放空间"最实用的办法。
为了避免走到删除那一步,也可以提前给日志做轮转。logrotate 配置好按天/按大小切割日志,保留期内的日志压缩存放,比等磁盘告警再手动清要省心得多。
5.2 inode 耗尽:df -h 没满但创建不了文件
系统还有另一种"满":inode 耗尽。df -i 查看 inode 使用率:
df -i如果 inode 使用率显示 100%,哪怕 df -h 还剩十几个 G,你依然无法创建任何新文件。原因很简单,每个文件都要占用一个 inode,inode 用完了,文件系统就无法再记录新文件的信息。这种情况通常是小文件太多造成的:大量几 KB 的缓存文件、临时文件、邮件队列堆在一起,几百万个 inode 很快就没了。
定位办法是先确认哪个挂载点 inode 满,再到对应目录下统计文件数:
find /var -xdev -type f | wc -lxdev 参数限制不跨文件系统,避免扫到其他挂载点导致统计膨胀。找到数量异常庞大的目录后,清理旧文件或合并小文件即可。如果业务场景本身就需要海量小文件,在格式化分区时可以用 mkfs.ext4 -i 调整 inode 密度,但这是规划层面的动作,改起来得重新格式化,生产环境慎用。
5.3 sync:写缓存、脏页和掉电风险
文件系统为了性能,写入操作大量使用 page cache:write() 调用把数据写进内存缓存就返回了,内核后台再异步把脏页(dirty page)刷到磁盘。这个设计极大提升了写性能,但也带来了掉电丢数据的风险。sync 命令的作用就是强制把所有脏页刷回磁盘:
sync拔 U 盘、移动硬盘之前必须 sync,这是我从第一次格式化 U 盘起就记住的硬规矩。虽然现代桌面环境在弹出设备时已经自动执行了同步,但在服务器命令行环境、嵌入式开发板、或手动卸载设备前,先 sync 再 umount 是最稳妥的顺序。顺带一提,umount 卸载本身就会同步数据,所以很多老手就说"卸载就是最好的 sync"。
涉及"哪些脏页、多久刷一次"的参数在 /proc/sys/vm/ 下可调,dirty_ratio、dirty_background_ratio、dirty_writeback_centisecs 等等。服务器重要数据盘可以调低 dirty_ratio,让内核更积极地把数据落盘;代价是写入性能下降,但对数据安全敏感的场景完全值得。
6. 特殊文件系统与嵌入式场景:tmpfs、proc、littlefs和NFS根文件系统
6.1 proc、sysfs、devtmpfs、tmpfs 各自管什么
/ 目录树里有一批不落盘的"特殊文件系统",理解它们对读懂系统状态异常关键:
- /proc 是 procfs 的挂载点,存放进程信息和内核运行时参数。ps、top、free 这些命令的数据源就是 /proc 下的文件。
- /sys 是 sysfs 的挂载点,提供设备、驱动、内核对象的层级视图。ls /sys/class 能看到系统里的设备类别。
- /dev 是 devtmpfs,由内核动态创建和管理设备节点。所以你在 /dev 下看到的 sda、ttyS0 都是内核自动创建的。
- /tmp 在某些发行版上使用 tmpfs,数据放在内存里,速度快,重启就清空。如果业务把重要数据放在 /tmp 下而系统重启了,数据就没了,这个坑要提前知道。
如果想手动做一个内存盘,可以用:
mount -t tmpfs -o size=2G tmpfs /mnt/ramdisk现在很多现代机器的 /run、/dev/shm 都是 tmpfs,好处是对 SSD 零磨损、读写速度极快,代价是占内存和重启失数据。编译软件时把临时构建目录放到 tmpfs 能显著提速,我之前用这种方法把大型 C++ 项目的编译耗时缩短了不少。
6.2 根文件系统是什么,嵌入式环境怎么用 NFS 挂载
传统 Linux 启动时,内核先加载 initramfs(一个内存里的临时根文件系统),再挂载真正的根文件系统,也就是 / 所在的分区或网络路径。根文件系统里要包含内核启动用户态进程所需的最小集合:init 程序、shell、动态库、必要的配置文件。嵌入式开发里,根文件系统通常先做成一个目录,再打包成 rootfs.ext4 或其他镜像格式烧写到 Flash。
但开发调试阶段,反复烧写 Flash 非常浪费时间,所以更高效的做法是通过 NFS 挂载根文件系统,把开发主机上的目录直接给开发板使用。启动参数这样写(内核 cmdline):
root=/dev/nfs nfsroot=192.168.1.5:/opt/rootfs,v3 rw ip=dhcp主机侧需要先配置 NFS 服务,导出 /opt/rootfs 目录(编辑 /etc/exports),然后开发板启动时内核会通过 NFS 挂载 rootfs 作为根文件系统。这样改代码、改库、加配置,直接在开发机上操作,开发板重启就能生效,省掉整个烧写环节。手动调试时也可以先启动到一个最小系统,再手动挂载 NFS rootfs:
mount -t nfs -o nolock,vers=3 192.168.1.5:/opt/rootfs /mnt/target6.3 闪存文件系统 littlefs 与 PlatformIO 场景
嵌入式设备上,Flash 存储和普通机械盘/SSD 差别很大:Flash 有擦写寿命限制,写入前必须先擦除,意外断电时如果文件系统没有掉电保护,很容易损坏整块分区。littlefs 就是专门为这类场景设计的文件系统,两个核心特性值得记住:
- 掉电安全:任何时刻断电,都不会导致已有文件损坏或元数据崩溃;
- 动态磨损均衡:自动把写入分散到不同块,避免某几个块频繁擦写提前报废;
- 写放大小:相比 FAT 类文件系统,写放大更小,能在小容量 Flash 上更耐用。
在 PlatformIO 中使用 ESP32 这类 MCU 时,可以在 board_build 配置里指定文件系统:
board_build.filesystem = littlefs然后在代码里通过 LittleFS 库挂载和读写文件。同样是在 Flash 分区上做文件存储,选 littlefs 比 SPIFFS 更稳:littlefs 面对掉电更可靠,目录支持也更完整,文件大小限制更友好。如果你曾经遇到 MCU 设备断电后配置数据丢失,换成 littlefs 后大概率能解决。
7. 把命令学活的思路:按问题反查而不是按字母背
7.1 高频命令按场景归纳
速查手册的价值在于"需要时能快速找到",所以我按真实问题场景重新归纳一批高频命令,而不是按字母排序:
| 场景 | 要解决的问题 | 该敲的命令 |
|---|---|---|
| 文件管理 | 复制、移动、删除、链接 | cp、mv、rm、ln |
| 文件查看 | 快速看内容、实时跟踪日志 | cat、less、head、tail -f |
| 内容处理 | 搜关键词、按列处理输出的文本 | grep、awk、sed、cut、sort |
| 磁盘与挂载 | 看空间、看块设备、挂载/卸载 | df、du、lsblk、blkid、mount、umount |
| 权限处理 | 改权限、改属主、查属性、查 ACL | chmod、chown、chattr、lsattr、getfacl |
| 进程管理 | 看进程、杀进程、查占用句柄 | ps、top、kill、lsof |
| 网络排查 | 看端口、测连通、查连接 | ss、ping、telnet、curl |
| 系统日志 | 看内核和系统日志 | dmesg、journalctl |
grep 是文本处理里最值得花时间学的命令。它的 -E 支持扩展正则、-r 递归目录、-l 只显示文件名、-v 反向过滤。命令行处理日志时,"grep 过滤 + awk 取列 + sort/uniq 统计"这一组合基本能解决 80% 的现场需求。反而是那些花哨的管道组合,平时用不到也记不住,用到时再翻 man 就行。
7.2 面试里占大头的问题其实都集中在几个模块
结合我参与面试和被面试的经验,Linux 相关的题如果涉及文件系统,高频考点非常集中:
- 硬链接和软链接的区别:硬链接共享 inode、不能跨文件系统、不能链目录;软链接是独立文件、可以跨文件系统、可以链目录但会失效。
- inode 是什么,inode 耗尽会怎样:文件元信息存储区,inode 满时磁盘有空间也无法创建文件。
- df 和 du 的区别与联系:df 看文件系统块占用、du 遍历目录统计文件大小,已删除文件场景两者不一致。
- 为什么 rm 文件后磁盘空间没释放:文件仍被进程占用句柄,lsof 查看 deleted 文件。
- SUID 的用途和风险:临时获得属主身份,异常 SUID 文件是提权排查的重点对象。
- 目录的 r/w/x 分别代表什么:r 列出文件名、w 增删改文件名、x 进入目录和访问文件。
这个清单不复杂,但它恰恰说明一个问题:面试官不是要考你背诵能力,而是考你能否把现象和知识串起来。你把文件系统模型理解透了,这些问题都只是模型的具体展开而已。
7.3 两条值得养成的习惯
第一,遇到奇怪的文件系统行为,先跑 stat 再看 dmesg。stat 能快速确认文件的真实元信息,dmesg 能告诉你内核层面的错误(比如 I/O 错误、文件系统只读切换)。很多时候顺序反了会绕远路:你以为是权限问题,结果 stat 一看 is 普通目录、ctime 异常,再查 dmesg 才发现磁盘有坏块,系统把挂载点切换成了只读。
第二,改配置文件之前先备份或者用 diff 对比。加注释掉一行 fstab 导致开不了机,绝大多数情况下是因为没有备份也没有核对字段含义。先 cp 一份 .bak,再动手改,最后 mount -a 验证,这个流程能避免 90% 的误操作。专业运维和混日子的差别,往往就在这些操作习惯上。
我最早也是从背命令开始的,那会儿记了厚厚一本笔记,见了新命令就抄,结果一到现场还是抓瞎。后来想明白了,命令只是文件系统这个骨架上的操作接口,先把文件、目录、inode、挂载这几层关系弄通,命令自然就串起来了。这篇速查手册我没有把所有命令都列出来,如果列全了,它反而没法用了。遇到问题先想"这个问题在文件系统里对应哪一层",再想该查哪条命令,这个顺序比背一百个命令都管用。最后送一个自己常用的经验:任何奇怪的文件系统现象,先 stat 再 dmesg,通常答案就在这两条命令的输出里。