Linux 文件系统基本管理深度剖析:设备识别、挂载排障与空间利用

引言

在 Linux 操作系统中,“一切皆文件”的理念不仅体现在常规数据上,更延伸到了硬件设备与存储介质。文件系统是操作系统管理存储设备上数据的“图书馆管理员”,它决定了数据如何被组织、存放和检索。对于运维人员而言,掌握文件系统的底层工作原理与核心管理工具,是日常排查磁盘空间爆满、文件丢失及挂载失败等生产故障的必备能力。

本文将基于课堂实战,深入讲解文件系统层面的设备识别、容量监控、挂载卸载原理、持久化配置,以及针对不同空间瓶颈的综合排障策略。


一、 识别文件系统与设备

1. 深入理解块设备与命名规则

在 Linux 中,所有硬件存储设备均以块设备文件的形式存在于 /dev 目录下。这里的“块”意味着数据以固定大小的块为单位进行读写。不同的硬件接口(SCSI/SATA、NVMe、虚拟化 VirtIO)对应着不同的设备命名前缀:

  • SATA/SAS/USB(SCSI 子系统)/dev/sda/dev/sdb
  • NVMe 固态硬盘/dev/nvme0n1/dev/nvme1n1
  • 虚拟机 VirtIO 磁盘/dev/vda/dev/vdb
  • SD/MMC 存储卡/dev/mmcblk0

这些设备文件并不是真实的文件,而是设备节点。分区后,设备名会增加数字后缀:/dev/sda1(第一块硬盘的第一个分区),/dev/nvme0n1p1(NVMe 磁盘的第一个分区)。

2. lsblk 命令:获取块设备拓扑结构

lsblk 以树状结构清晰展示磁盘、分区、逻辑卷之间的层级关系,是查看设备架构的首选。

[root@server-xianyu ~ 18:47:26]# lsblk
NAME            MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda               8:0    0   200G  0 disk 
├─sda1            8:1    0     1G  0 part /boot
└─sda2            8:2    0   199G  0 part 
  ├─centos-root 253:0    0    50G  0 lvm  /
  ├─centos-swap 253:1    0   3.9G  0 lvm  [SWAP]
  └─centos-home 253:2    0 145.1G  0 lvm  /home
sr0              11:0    1   4.4G  0 rom  

字段深度解读

  • NAME:设备名称。
  • MAJ:MIN:主设备号和次设备号。主设备号 8 代表 SCSI 磁盘驱动,253 代表 Device Mapper(LVM)。内核通过这些数字精确识别驱动程序。
  • RM:可移除标记(1 代表可移动设备,如 U 盘或光驱,0 为固定硬盘)。
  • RO:只读标记。若为 1,则该设备只能读取(如光驱)。
  • SIZE:容量大小。
  • TYPE:类型(disk 磁盘、part 分区、lvm 逻辑卷、rom 只读存储)。
  • MOUNTPOINT:当前挂载的目录,空表示未挂载。

3. df 命令:监控文件系统空间使用率

df 是排查磁盘空间是否“爆满”的第一道防线。推荐配合 -h(易读单位)和 -T(显示文件系统类型)使用。

# 结合使用 -h(1024进制)和 -T
[root@server-xianyu ~ 18:47:30]# df -hT
文件系统                类型      容量  已用  可用 已用% 挂载点
devtmpfs                devtmpfs  2.0G     0  2.0G    0% /dev
tmpfs                   tmpfs     2.0G     0  2.0G    0% /dev/shm
tmpfs                   tmpfs     2.0G   13M  2.0G    1% /run
tmpfs                   tmpfs     2.0G     0  2.0G    0% /sys/fs/cgroup
/dev/mapper/centos-root xfs        50G  4.9G   46G   10% /
/dev/mapper/centos-home xfs       146G  465M  145G    1% /home
/dev/sda1               xfs      1014M  174M  841M   18% /boot
tmpfs                   tmpfs     394M  8.0K  394M    1% /run/user/42
tmpfs                   tmpfs     394M     0  394M    0% /run/user/1000
  • -h vs -H-h 采用 1024 进制(1G=1024M),-H 采用 1000 进制(1G=1000M),硬盘厂商常用 1000 进制,所以 df -H 显示的容量数字会比 -h 略大。
  • 如何确定某个目录落在哪个分区?:直接执行 df /tmp,系统会输出 /tmp 所在挂载点的对应信息。

4. du 命令:精准定位

如果发现根分区已使用 90%,需要立刻查出是哪个目录占用了空间,此时 du 登场。

# 查看 /boot 目录总占用
[root@server-xianyu ~ 18:52:09]# du -sh /boot
141M	/boot

实战排查技巧(层层递进法)
在笔记案例中,为了找到消耗 4GB 空间的“罪魁祸首”,使用了组合拳:

# 1. 看根目录下谁最大
[root@server-xianyu ~ 18:55:50]# du -sk /* 2>/dev/null | sort -rn | head -n 5
8031628	/usr
1084276	/var
442608	/home
144312	/boot
43224	/etc
# 输出发现 /usr 最大(8031628 KB)

# 2. 深入 /usr
[root@server-xianyu ~ 18:55:55]# du -sk /usr/* 2>/dev/null | sort -rn | head -n 5
5638052	/usr/share
1214028	/usr/lib64
877648	/usr/lib
147552	/usr/bin
73856	/usr/libexec
# 输出发现 /usr/share 最大(5638052 KB)

# 3. 深入 /usr/share
[root@server-xianyu ~ 18:56:50]# du -sk /usr/share/* 2>/dev/null | sort -rn | head -n 5
4284696	/usr/share/doc
451260	/usr/share/locale
213252	/usr/share/help
122840	/usr/share/fonts
83908	/usr/share/icons
# 输出发现 /usr/share/doc 最大(4284696 KB)

# 4. 深入 /usr/share/doc
[root@server-xianyu ~ 18:57:21]# du -sk /usr/share/doc/* 2>/dev/null | sort -rn | head -n 5
4194316	/usr/share/doc/dhclient-4.2.5
4376	/usr/share/doc/gcc-4.8.5
1216	/usr/share/doc/postfix-2.10.1
1192	/usr/share/doc/python-kitchen-1.1.1
1060	/usr/share/doc/pam-1.1.8

# 最终定位到大文件:/usr/share/doc/dhclient-4.2.5/bigfile-4G(4194304 KB)
[root@server-xianyu ~ 18:57:51]# du -sk /usr/share/doc/dhclient-4.2.5/* 2>/dev/null | sort -rn | head -n 5
4194304	/usr/share/doc/dhclient-4.2.5/bigfile-4G
4	/usr/share/doc/dhclient-4.2.5/README.dhclient.d
4	/usr/share/doc/dhclient-4.2.5/dhclient.conf.example
4	/usr/share/doc/dhclient-4.2.5/dhclient6.conf.example

这种**“逐层剥离”**的策略,完美诠释了 Linux 的 KISS 原则(Keep It Simple, Stupid):把大任务拆解成小工具的组合,能极其高效地完成复杂排障。


二、 文件系统的挂载与卸载机制

要让文件系统的数据在 Linux 目录树中可见,必须先执行挂载(Mount)操作,即将其附加到一个称之为挂载点的空目录上。

1. 标准挂载 (mount 命令)

# 虚拟机添加一块硬盘sdb
[root@server-xianyu ~ 19:04:07]# lsblk
NAME            MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda               8:0    0   200G  0 disk 
├─sda1            8:1    0     1G  0 part /boot
└─sda2            8:2    0   199G  0 part 
  ├─centos-root 253:0    0    50G  0 lvm  /
  ├─centos-swap 253:1    0   3.9G  0 lvm  [SWAP]
  └─centos-home 253:2    0 145.1G  0 lvm  /home
sdb               8:16   0   100G  0 disk 
sr0              11:0    1   4.4G  0 rom  

# 格式化文件系统
[root@server-xianyu ~ 19:04:14]# mkfs.xfs /dev/sdb
meta-data=/dev/sdb               isize=512    agcount=4, agsize=6553600 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=0, sparse=0
data     =                       bsize=4096   blocks=26214400, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal log           bsize=4096   blocks=12800, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

# 创建挂载点(必须是空目录)
[root@server-xianyu ~ 19:06:17]# mkdir /date

# 获取设备唯一标识(推荐使用 UUID 挂载,避免设备名变动)
[root@server-xianyu ~ 19:09:01]# blkid /dev/sdb
/dev/sdb: UUID="46526d63-5c6c-4e34-b33c-35cccbdee0fd" TYPE="xfs" 

# 挂载
[root@server-xianyu ~ 19:12:01]# mount /dev/sdb /data
# 或者用 UUID:
[root@server-xianyu ~ 19:12:32]# mount UUID='46526d63-5c6c-4e34-b33c-35cccbdee0fd' /data

[root@server-xianyu ~ 19:13:02]# lsblk
NAME            MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda               8:0    0   200G  0 disk 
├─sda1            8:1    0     1G  0 part /boot
└─sda2            8:2    0   199G  0 part 
  ├─centos-root 253:0    0    50G  0 lvm  /
  ├─centos-swap 253:1    0   3.9G  0 lvm  [SWAP]
  └─centos-home 253:2    0 145.1G  0 lvm  /home
sdb               8:16   0   100G  0 disk /data
sr0              11:0    1   4.4G  0 rom  

底层补充mount 命令实质是调用系统调用 mount(),将设备文件(/dev/sdb)与特定节点(/data)进行绑定。挂载后,mount 命令不加任何参数可以查看当前所有挂载点的详细状态,括号里会显示挂载选项(如 rw 可读写、relatime 相对更新时间、seclabel SELinux 安全标签等)。

2. 文件系统卸载 (umount 命令)

[root@server-xianyu ~ 19:15:21]# umount /data
# 或者 umount /dev/sdb

[root@server-xianyu ~ 19:16:39]# lsblk
NAME            MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda               8:0    0   200G  0 disk 
├─sda1            8:1    0     1G  0 part /boot
└─sda2            8:2    0   199G  0 part 
  ├─centos-root 253:0    0    50G  0 lvm  /
  ├─centos-swap 253:1    0   3.9G  0 lvm  [SWAP]
  └─centos-home 253:2    0 145.1G  0 lvm  /home
sdb               8:16   0   100G  0 disk 
sr0              11:0    1   4.4G  0 rom  

注意:umount 后面必须跟挂载点或设备名其中之一,且必须保证当前工作目录不在挂载点内部

3. 经典高频故障:“target is busy” 的排障方法

如果当前终端目录停留在 /data 目录下,卸载时会提示 target is busy。这是运维中极其高频的错误。

故障原因:有进程正在访问该目录内的文件(比如你正在 /data 里执行 ls 或者 tail -f)。此时需要定位进程并将其“赶走”。

  • 方法一:使用 lsof(List Open Files)
    lsof /data 会列出当前所有正在访问该目录或文件的进程。

    [root@server-xianyu ~ 19:17:45]# cd /data
    [root@server-xianyu data 19:17:48]# touch file-{1..3}
    [root@server-xianyu data 19:18:14]# ls
    file-1  file-2  file-3
    [root@server-xianyu data 19:18:16]# umount /dev/sdb
    umount: /data:目标忙。
            (有些情况下通过 lsof(8) 或 fuser(1) 可以
             找到有关使用该设备的进程的有用信息)
    
    [root@server-xianyu data 19:18:33]# lsof /data
    COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
    bash    1872 root  cwd    DIR   8,16       48   64 /data
    lsof    2147 root  cwd    DIR   8,16       48   64 /data
    lsof    2148 root  cwd    DIR   8,16       48   64 /data
    

    输出解析:COMMANDbashPID 是 1508,FD=cwd 表示当前工作目录就在 /data。关闭该 bash窗口或执行 cd / 离开该目录即可解决。

  • 方法二:使用 fuser(识别并杀死进程)
    fuser -m /data 不仅能识别,还支持快速清理。

    # 查看占用进程
    [root@server-xianyu data 19:19:27]# fuser -m /data
    /data:                1872c
    # 末尾的 'c' 表示当前目录。
    

    如果确认该进程可以安全终止,可以执行 fuser -km /data 发送 SIGKILL 信号直接杀掉占用进程,然后再执行 umount /data


三、 文件系统的持久化挂载(/etc/fstab

手动挂载的分区在服务器重启后会失效,因此我们需要将其写入系统挂载配置文件 /etc/fstab,确保开机自动挂载。

/etc/fstab 六字段深度解析

该文件每一行代表一个挂载项,使用空格或制表符分隔成 6 个字段:

  1. 设备文件(Device):推荐使用 UUIDblkid 可查),因为设备名 /dev/sdb1 可能会因为插拔或重启顺序改变而导致挂载失败。
  2. 挂载点(Mount point):须为系统上真实存在的空目录(如 /data01)。
  3. 文件系统类型(File system type):如 xfsext4iso9660 等。
  4. 挂载选项(Mount options):常用 defaults 套件(包含 rwsuiddevexecautonouserasync)。
  5. Dump 备份标记:通常设为 0。若设为 1,则 dump 命令会备份该文件系统。
  6. Fsck 检查顺序
    • 0:表示不检查。XFS 文件系统必须设为 0,因为 XFS 有自己的日志机制,不支持传统的 fsck
    • 1:表示优先检查(通常仅根分区 / 设置 1)。
    • 2:表示按顺序检查(用于其他 ext4 文件系统)。

配置实例与测试:

[root@centos7 ~]# blkid /dev/sdb1
/dev/sdb1: UUID="f5c35f10-0274-45af-b044-73694989fe01" TYPE="xfs"

# 向 /etc/fstab 追加条目(注意不要写错符号,必须空格分隔)
UUID="f5c35f10-0274-45af-b044-73694989fe01" /data01 xfs defaults 0 0

# 执行挂载测试(重要!):不重启,直接尝试挂载 fstab 中的所有条目
[root@centos7 ~]# mount -a

# 验证
[root@centos7 ~]# df -h /data01

四、 查找系统中的文件

1. locate:基于数据库的极速查找

locate 依托于系统定期维护的 mlocate 数据库(系统默认每天更新一次)。它的特点是查找速度极快,甚至可以做到毫秒级返回。但刚安装的软件包,如果不先手动执行 updatedb 刷新数据库,会查找不到。

  • -i:忽略大小写。
  • -c:仅统计匹配数量。
  • -r:使用正则表达式查找。

2. find:实时遍历的全能搜索

find 直接在文件系统目录树中实时遍历,虽然速度比 locate 慢,但能力最强,支持极其复杂的条件组合。

(1)按文件名(-name)与忽略大小写(-iname

find /etc/ -name '*passwd*'

(2)按文件类型(-type
-type d 目录,-type f 普通文件,-type l 软链接。

(3)按文件所有者(-user / -uid)与属组(-group / -gid

find / -user laoma
# 找无主文件(系统垃圾)
find / -nouser

(4)按文件权限(-perm)—— 三种模式解析(极易混淆)

  • 精确匹配-perm 764,查找权限完全等于 rwxrw-r-- 的文件。
  • 最小匹配-perm -764,查找权限至少包含 ugo 对应位(u至少为7,g至少为6,o至少为4)的文件(比如 777 也能被匹配)。
  • 任意匹配-perm /764,查找 ugo 其中任意一个满足对应最小位(u至少7,或g至少6,或o至少4)的文件。
  • 实战巧用find / -perm -4000 可快速找出所有带 SUID 权限(可能提权的程序)的文件,是安全排查常用手段。

(5)按文件大小(-size)与修改时间(-mmin / -mtime

find -size +10M   # 大于 10M
find -size -10k   # 小于 10k
find -mmin -10    # 10分钟内修改过的
find -mtime +30   # 30天前修改过的

(6)逻辑关系与动作(-a、-o、!、-exec)

# 查找无主 或 无组的文件
find / -nouser -o -nogroup

# 找到文件后直接删除
find / -name "PASSWD" -delete

# 找到文件并复制到指定目录({} 代表找到的文件路径)
mkdir findfiles
find / -inum 67160130 -exec cp -a {} ./findfiles \;

(注:-exec 后的 \; 表示每条匹配执行一次命令,效率较低;但如果用 + 代替 \;,则将结果打包一次执行,效率大幅提升。)


五、 文件系统空间不足综合排障案例

在实际生产环境中,空间不足并不是单纯的“删个文件就行”,下面三种情况极其容易让人踩坑。

情况1:大量的大文件占据空间

现象df -h 显示分区已 100%。
排查:使用 find /myapp-1/ -size +100M 快速定位超 100M 的文件。
处理:确认非业务文件后,直接 rm -f 删除。

情况2(经典陷阱):删除文件后,空间并没有释放

现象:明明执行 rm -f 删除了 2GB 的日志文件,但 df -h 显示磁盘依然是 100% 占用。
根因该文件被某个进程(如 tail -f)一直打开着。在 Linux 内核中,删除目录项(硬链接)并不代表释放磁盘空间,只有 “文件的打开句柄(File Handle)被关闭”(即持有该文件的进程彻底退出),文件占用的磁盘块才会被系统真正回收。
排查与解决

# 找出所有已删除但仍被打开的文件(标记为 (deleted))
[root@centos7 ~]# lsof | grep delete | grep /myapp-1
tail      1654 root    3r   REG  8,17 2061565952 444 /myapp-1/etc/bigfile (deleted)
# 定位到进程 PID 为 1654,杀掉它
[root@centos7 ~]# kill 1654
# 再次查看 df,空间立即释放!

防范建议:运维清大文件前,习惯先执行 > /path/to/bigfile 清空文件内容,再 rm 删除,则可避免占用风险。

情况3(易被忽视的瓶颈):大量小文件耗尽 inode

现象df -h 显示磁盘还有 900M 剩余空间,但 touch 创建新文件时报错 设备上没有空间
原因:文件系统占满的不是数据块,而是索引节点(inode)。每个文件(无论大小 1KB 还是 1GB)都需要占用一个 inode 来记录文件的元数据(权限、位置、时间等)。当创建了海量小文件(比如 65,000 个空文件),inode 表会被彻底撑爆。
排查与解决

# -i 参数查看 inode 使用情况
[root@centos7 ~]# df -hi /myapp-2
文件系统     Inodes IUsed IFree IUse% Mounted on
/dev/sdb2         64K   64K     0  100% /myapp-2

此时空间虽多,但无法继续创建文件。需将小文件合并(如 tar 打包、cat 拼接),或备份后删除这些小文件,释放 inode。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐