Linux 入门指南 · 第九章:理解数据存在哪里,以及怎样可靠地恢复。
第一章介绍了统一的目录树。本章进一步解释:磁盘上的文件系统怎样进入这棵树,备份怎样保存数据,以及恢复时要检查什么。
以下挂载示例针对已经包含文件系统、且已确认用途的数据设备。分区和格式化会改变磁盘结构,不是挂载已有数据的必要步骤;接入一块磁盘后,应先识别,再决定如何使用。
一、设备、分区、文件系统与挂载点
磁盘设备
└── 分区或其他逻辑设备
└── 文件系统
└── 挂载到某个目录
└── 通过目录路径访问文件
这是常见结构,不是唯一结构。文件系统也可以直接建立在整个设备、逻辑卷、加密映射设备或其他存储层之上。
| 概念 | 回答的问题 | 示例 |
|---|---|---|
| 磁盘设备 | 系统识别到了哪个块设备? | /dev/sdb、/dev/nvme1n1 |
| 分区 | 设备中划分了哪些区域? | /dev/sdb1、/dev/nvme1n1p1 |
| 文件系统 | 文件和目录按什么结构保存? | ext4、XFS、Btrfs |
| UUID | 如何标识某个文件系统? | 由查询工具读取的标识值 |
| 挂载点 | 通过哪个目录访问它? | /mnt/data、/srv/data |
设备名可能随硬件识别顺序变化,不能仅凭 /dev/sdb 这个名字判断它始终是同一块盘。持久配置常使用文件系统 UUID,但克隆磁盘等操作也可能产生重复标识,需要结合实际设备确认。
二、先查看现有存储结构
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINTS
lsblk -f
findmnt
lsblk 查看块设备层次与属性,findmnt 查看挂载关系。部分旧版本的 lsblk 不支持 MOUNTPOINTS,可以改用 MOUNTPOINT 或查看其帮助。
进一步查询文件系统标识:
sudo blkid
按路径判断文件实际落在哪个挂载上:
findmnt -T /var/log
findmnt -T "$HOME"
df -h "$HOME"
目录看起来位于 /home/aron,不代表它一定与根目录处在同一文件系统。挂载关系才决定数据实际进入哪个文件系统。
三类常见存储疑问
| 疑问 | 优先查看 |
|---|---|
| 磁盘已接入但找不到文件 | lsblk -f 与挂载情况 |
| 某目录写满了,另一块盘仍有空间 | 该目录实际所在的文件系统 |
| 目录为空,服务却持续写入 | 预期的数据盘是否真正挂载,服务是否写到了挂载点下方的根盘目录 |
最后一种情况常出现在数据盘未成功挂载时:挂载点仍然是一个普通目录,程序可能继续向根文件系统写数据。
三、挂载已有文件系统
先创建一个用于挂载的空目录:
sudo mkdir -p /mnt/data
下面的 REPLACE_WITH_UUID 必须替换成已核对的实际文件系统 UUID:
sudo mount -o ro /dev/disk/by-uuid/REPLACE_WITH_UUID /mnt/data
findmnt /mnt/data
ls -la /mnt/data
-o ro 表示请求只读挂载,适合先确认内容。但某些文件系统仍可能在挂载时回放日志,不能把只读挂载当作严格的取证级防写保护。
普通使用是否需要读写挂载,应在确认文件系统状态和数据用途后决定。挂载选项还可能包含 noexec、nodev、nosuid 等限制,具体效果与文件系统及挂载上下文有关。
挂载会暂时遮住目录原有内容
如果 /mnt/data 原来已有文件,挂载后会显示新文件系统的内容,原目录中的文件并没有因此删除,而是暂时不可见。卸载后才能重新通过这个路径看到它们。
因此,不要把已有业务目录随意用作挂载点。先确认目录为空、未被服务使用,再建立挂载关系。
卸载与占用问题
cd "$HOME"
sudo umount /mnt/data
命令是 umount。离开挂载目录再卸载,可以避免当前终端的工作目录本身占用它。
遇到 target is busy 时,先检查是否有终端、程序或服务正在访问该文件系统。安装了相应工具时,可以用:
sudo fuser -vm /mnt/data
先协调停止相关任务,再正常卸载。强制或延迟卸载有特定适用条件,不应当作普通占用问题的默认处理方式。
四、持久挂载与 /etc/fstab
手动执行 mount 通常只影响当前运行状态。需要在启动时建立挂载关系时,常见配置入口是 /etc/fstab。
一条记录通常由六个字段组成:
设备标识 挂载点 文件系统类型 挂载选项 dump字段 fsck顺序
下面仅展示一个可选数据盘的格式,UUID、类型和选项必须按实际情况确定:
UUID=REPLACE_WITH_UUID /mnt/data ext4 defaults,nofail 0 2
| 字段 | 示例含义 |
|---|---|
UUID=... |
选择已经确认的文件系统 |
/mnt/data |
已准备好的挂载点 |
ext4 |
文件系统类型,需要与设备一致 |
defaults,nofail |
使用默认选项,并按管理器规则允许该挂载失败时继续启动 |
0 |
不通过这一字段安排 dump 备份 |
2 |
对适用的文件系统安排非根文件系统检查顺序 |
nofail 适合某些可选设备,不能解决业务对磁盘的依赖。如果服务必须使用这块盘,需要同时配置服务的挂载依赖,避免磁盘缺失时写到错误位置。
编辑前备份配置,编辑后可以先检查条目:
findmnt --verify --verbose
它不能代替实际挂载验证,也不能证明重启后所有硬件和服务条件都正常。对 systemd 管理的系统,修改 fstab 后通常还需要 sudo systemctl daemon-reload,再按当前环境验证目标挂载。
入门阶段先理解格式和检查方式,不需要为了学习而修改根文件系统等关键挂载。
五、文件名、inode 与链接
文件名属于目录项,inode 保存文件的元数据,并关联文件数据。两个路径是否指向同一个对象,不能只看名称或内容是否相同。
ls -li notes.txt
stat notes.txt
硬链接与软链接的区别:
| 特性 | 硬链接 | 软链接 |
|---|---|---|
| 关联对象 | 同一文件系统内的同一个 inode | 保存目标路径的独立对象 |
| 能否跨文件系统 | 通常不能 | 可以 |
| 目标路径删除后 | 其他硬链接仍可访问该对象 | 可能成为悬空链接 |
| 是否适合任意目录 | 普通用户通常不能对目录创建硬链接 | 可以指向目录 |
示例针对已有普通文件 notes.txt:
ln notes.txt notes-hardlink.txt
ln -s notes.txt notes-link.txt
ls -li notes.txt notes-hardlink.txt notes-link.txt
硬链接不是独立备份。通过任一硬链接修改文件内容,其他硬链接看到的内容也会改变。
文件占用的空间通常要等链接数降到零,并且不再被进程打开等条件满足后才能释放。这也解释了某些“删除日志后 df 空间没有立刻下降”的现象,相关排查见第五章。
六、备份之前先定义恢复需求
备份的目的,是在原数据不可用或不正确时,得到一个可用的恢复版本。只有一个与原数据同步变化的副本,通常不足以覆盖误删、错误覆盖和勒索等情形。
| 方式 | 主要能力 | 常见边界 |
|---|---|---|
| 普通复制 | 保存当时的一份内容 | 是否独立取决于位置,可能被后续覆盖 |
| 目录同步 | 减少重复传输,保持副本接近源 | 错误修改可能同步到副本 |
| 快照 | 快速保留某时刻的存储状态 | 可能依赖原设备,也可能不具备应用一致性 |
| 有版本的备份 | 保留可选择的历史恢复点 | 需要管理容量、保留期限与恢复方法 |
确定备份方案时,先说明以下几件事:
- 哪些目录与配置必须恢复,哪些缓存可以重新生成。
- 最多能接受丢失多久的数据,以及恢复需要多快。
- 副本保存在哪里,是否与原数据共享相同的故障点。
- 谁能读取或删除备份,历史版本保留多久。
常见的 3-2-1 思路是保留三份数据、分布在两种介质上,并有一份异地副本。具体实现要服务于恢复需求,还可结合离线或不可变副本应对误删和恶意修改。
七、使用 tar 保存一个版本
假设已有项目目录 $HOME/projects/demo。下面使用一个独立的新目录保存本次归档,备份位置位于项目目录之外:
backup_root="$HOME/backups"
mkdir -p -- "$backup_root"
snapshot_dir=$(mktemp -d "$backup_root/demo-XXXXXXXX")
tar -czf "$snapshot_dir/demo.tar.gz" -C "$HOME/projects" demo
这是逐行展示的命令示例。用于脚本时,需要按第八章检查目录创建、mktemp 和 tar 的退出状态,失败时停止后续步骤。
-C "$HOME/projects" demo 让归档中的路径从 demo/ 开始,避免把整个家目录的绝对路径结构带进恢复目录。
备份保存了什么
归档通常包含文件内容、路径和一部分元数据。需要完整保留 ACL、扩展属性或其他文件系统特性时,必须确认工具选项与恢复端支持,不能默认普通 tar 或 rsync -a 已经覆盖全部信息。
软链接通常按链接对象保存,目标在目录外时,不代表目标数据也一并备份。外部挂载、密钥、环境文件和软件配置也要按恢复需求单独确认。
正在变化的数据需要一致性策略
归档过程中源目录如果持续变化,得到的文件可能不是同一时刻的业务状态。对于数据库和其他状态服务,应使用应用支持的备份工具、协调停写,或结合具备一致性保证的快照流程。
直接打包正在运行的数据库数据目录,不能自动保证恢复后可用。
本地归档之后还需要独立副本
$HOME/backups 与项目在同一磁盘上时,它主要覆盖部分误操作场景,不能应对整盘损坏。还需要按需求把版本传到独立设备或远端,并管理访问与保留策略。
第七章中的 rsync 可以用于传输归档。不要让同步过程把仍在写入、尚未完成的归档当作最终版本。
八、恢复:先到独立目录,再决定替换
先确认归档能够读取,并查看内容:
gzip -t "$snapshot_dir/demo.tar.gz"
tar -tzf "$snapshot_dir/demo.tar.gz"
gzip -t 检查压缩流完整性,tar -t 检查归档条目是否能读取。两者都不能证明业务数据完整或应用可以启动。
在一个新目录中恢复:
restore_dir=$(mktemp -d "$HOME/demo-restore-XXXXXXXX")
tar -xzf "$snapshot_dir/demo.tar.gz" -C "$restore_dir"
ls -la "$restore_dir/demo"
这些命令承接上一节的变量。新开终端时,需要重新设置 snapshot_dir 为实际备份目录,不能假定旧变量仍然存在。
恢复后检查什么
| 检查对象 | 要确认的结果 |
|---|---|
| 目录结构 | 归档中的相对路径与预期一致 |
| 关键文件 | 内容、大小及必要的校验符合预期 |
| 权限与所有权 | 恢复后的用户、组和访问规则适合目标环境 |
| 软链接与依赖 | 链接目标、配置引用、外部数据仍可用 |
| 应用状态 | 使用应用自己的检查或恢复流程确认可用 |
| 恢复时长 | 能否满足实际恢复时间要求 |
不同机器可能使用不同 UID、GID。归档中的所有者名称与数字身份不一定能直接迁移,恢复时应明确映射关系,而不是对整个目录直接开放权限。
确认恢复内容之后,再安排停止相关服务、替换目标数据并进行功能检查。直接解压到正在使用的项目目录,可能混入旧文件或覆盖仍被使用的配置。
九、容量、保留与恢复记录
备份本身也会占满磁盘。定时备份需要同时考虑版本保留、容量预警和失败日志,保留规则必须对应明确的备份目录与文件范围。
不要只凭“创建时间较早”就对整个家目录批量删除。清理前先列出候选条目,保留仍可能需要的恢复点,并确认至少存在可用的独立副本。
恢复记录可以简洁地保留:备份对象、生成时间、工具选项、保存位置、校验结果、恢复步骤和验证结果。这样才能在更换机器或长时间之后仍然知道如何使用归档。
十、命令速查
| 命令 | 用途 |
|---|---|
lsblk -f |
查看块设备与文件系统信息 |
sudo blkid |
查询文件系统标识 |
findmnt -T 路径 |
查看某路径所在的挂载 |
df -h 路径 |
查看对应文件系统空间 |
sudo mount -o ro 设备 挂载点 |
请求只读挂载已有文件系统 |
sudo umount 挂载点 |
卸载文件系统 |
findmnt --verify --verbose |
检查 fstab 的可解析性与相关条件 |
ls -li 文件 |
查看 inode 与链接信息 |
tar -czf 备份.tar.gz -C 父目录 子目录 |
用相对路径创建归档 |
gzip -t 备份.tar.gz |
检查 gzip 压缩流 |
tar -tzf 备份.tar.gz |
查看归档条目 |
tar -xzf 备份.tar.gz -C 恢复目录 |
恢复到已有目录 |
上一篇:Shell 脚本与定时任务 · 返回指南目录。

