登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  linux

tar --one-file-system 怎样排除挂载点

来源:17golang原创

时间:2026-11-06 23:44:52 406浏览 收藏

我在整理服务器目录备份时,最容易忽略的不是压缩参数,而是目录里面藏着另一个文件系统:例如日志目录、容器数据目录或临时盘被挂载到目标目录下。tar 默认会继续递归进去,结果就是一份看似“目录备份”的归档把挂载盘内容也带走了。

GNU tar 的处理方式很直接:创建归档时加上 --one-file-system,目录递归遇到不同文件系统的挂载点就不再向下展开。它不是任意路径黑名单,显式写在命令行或 --files-from 中的路径仍然会被处理。

官方地址:https://www.gnu.org/software/tar/manual/

如果你的目标是“归档某个文件系统,但不顺带进入下面挂载的其它文件系统”,把 --one-file-system 放进创建归档的命令即可;如果还显式指定了挂载目录,就要按显式输入规则重新判断。

先看 tar 默认为什么会跨挂载点

tar 接收一个目录参数时,会把它当作目录树递归扫描。目录树中的某个子目录如果是挂载点,路径看起来仍然连续,但它背后已经属于另一个文件系统。默认行为并不会因为这个目录名字发生变化就自动停下。

这也是备份时容易出现容量突然变大的原因:目标目录本身可能只有几百 MB,挂载进去的数据库盘、对象缓存盘却有几十 GB。对目录做归档与对文件系统做归档是两个不同层次的问题,先把这个边界分清,后面的命令才不会靠猜。

tar 目录递归与挂载点文件系统边界关系说明图
图1:目标目录、挂载文件系统和 tar 递归边界的静态关系;这是说明图,不是运行截图。

图中可以把 --one-file-system 理解为“限制目录递归跨越文件系统边界”的开关。它关心的是目录递归所遇到的文件系统归属,不是根据目录名做字符串排除。

用 --one-file-system 限制目录递归

假设需要归档 /srv/data,归档文件写到同一台机器的独立备份目录,可以这样写:

# 只递归 /srv/data 所在文件系统,不进入下面的其它挂载点
tar --create --gzip --file=/backup/data-$(date +%F).tar.gz \
  --one-file-system \
  --directory=/srv/data .

--directory=/srv/data . 让归档中的路径从相对根开始,避免把本机绝对路径直接当作归档层级;--one-file-system 则决定递归遇到其它文件系统时不再继续向下。输出归档最好放在目标目录之外,避免把正在生成的归档再次读进自己。

如果习惯短选项,也可以保留压缩和文件参数的短写法:

# -c 创建、-z gzip、-f 指定归档文件;长选项负责表达边界
tar -czf /backup/data.tar.gz --one-file-system -C /srv/data .

这个选项用于创建归档,适合全量或增量备份一整个文件系统的场景。它不是解压时的过滤器,也不能替代权限、敏感目录和备份保留策略。

用 -v 观察哪些挂载点被跳过

刚开始改备份脚本时,我通常会先加上 --verbose,因为“没有进入挂载点”最好能在输出里留下线索。GNU tar 文档说明,--one-file-system 与 --verbose 一起使用时,被排除的文件会在标准错误中按名称提示。

# -v 让 tar 把归档项和被排除的跨文件系统目录写入可观察输出
tar -czvf /backup/data.tar.gz \
  --one-file-system \
  -C /srv/data . 2> /backup/data-tar.stderr

这里的重点不是把输出保存下来就算完成,而是观察它是否符合预期:目标文件系统中的目录继续递归,挂载点不会再展开。第一次接入新机器时,可以把这份标准错误记录作为备份脚本的人工检查材料;长期运行时则不必强行把每个文件都打印出来。

区分目录递归与显式路径

这是 --one-file-system 最容易被误解的地方。它只改变“因为正在递归某个目录而遇到不同文件系统”的行为。GNU tar 手册明确区分了两类输入:目录递归遇到的跨文件系统内容会被限制,但命令行明确写出的路径,或者通过 --files-from 提供的路径,不会因为它们位于其它文件系统就被这个选项删除。

# /srv/data 下的挂载点受边界限制;显式写出的 /mnt/archive 仍是归档输入
tar -czf /backup/mixed.tar.gz \
  --one-file-system \
  /srv/data /mnt/archive

同样的规则也适用于文件列表:

# 文件列表中的路径是明确输入;先确认列表内容再交给 tar
tar -czf /backup/from-list.tar.gz \
  --one-file-system \
  --files-from=/etc/backup-paths.txt
tar 目录递归路径与显式挂载路径处理边界关系图
图2:目录递归受文件系统边界限制,而显式路径仍进入归档输入集合;这是静态结构示意图。

因此,脚本里不能只看到 --one-file-system 就宣布“所有挂载点都排除了”。如果需求是“无论如何都不能归档某个路径”,还需要在输入集合层面移除它,例如重新组织根目录、使用专门的排除规则,或不要把该路径写进显式文件列表。

把边界放进一次可复用的备份工作流

我更倾向于把这件事拆成四个检查点,而不是把一条很长的 tar 命令直接塞进定时任务。

  1. 确认目标:明确要备份的是某个目录,还是目录所在的单一文件系统。
  2. 查看挂载关系:先列出目标目录下的挂载点,确认哪些数据盘不应随目录递归进入。
  3. 固定归档命令:使用 --one-file-system,输出文件放在目标目录之外,并在首次部署时保留一次 -v 的标准错误记录。
  4. 审查显式输入:检查命令行参数和 --files-from 文件,确认没有把被排除的挂载路径再次主动加入。

这个工作流的价值在于,它把“tar 没有递归进去”和“备份脚本根本没有把该路径作为显式输入”分开了。前者由文件系统边界控制,后者由输入清单控制,恢复时也更容易解释归档为什么不包含某个挂载盘。

几个容易踩到的边界

场景实际含义处理建议
目录递归遇到挂载点不同文件系统的目录内容不再向下归档创建归档时使用 --one-file-system
显式写出挂载路径它属于明确的归档输入,不会被该选项自动移除从参数或文件列表中删除它
只加了排除选项但不看输入可能仍把显式路径加入归档审查命令行与 --files-from
把它当成权限控制它只改变 tar 的递归边界,不是访问控制策略权限、密钥和备份保留另行治理

还要注意,挂载点是否存在是运行环境事实;同一条脚本在开发机、容器和生产机上看到的文件系统布局可能不同。备份说明里最好记录目标根目录、挂载关系和显式输入清单,而不是只记录 tar 参数。

总结:什么时候该用这个选项

当任务是“归档一个目录所在的文件系统,同时不跨入它下面挂载的其它文件系统”时,tar --one-file-system 是清晰而直接的选择。先用 -v 观察一次边界,再把命令固定到备份脚本里;如果命令或文件列表显式写了挂载路径,就必须把它当作独立输入审查。

真正需要记住的只有一句:它限制的是目录递归,不是所有路径输入。把文件系统边界和归档输入边界分别管理,备份结果才容易预测。

相关问题

--one-file-system 会删除挂载点目录本身吗?

它的作用重点是阻止继续递归到不同文件系统的内容,不应把它理解为按目录名做删除。需要精确控制归档清单时,应结合输入结构和排除规则判断。

为什么加了 --one-file-system 仍然出现挂载盘内容?

优先检查是否把挂载路径直接写在命令行,或通过 --files-from 明确提供了它。显式输入不属于“递归时偶然遇到”的路径。

是否应该永远加 -v?

首次部署、调整挂载关系或排查备份体积时值得使用;稳定的定时任务可以减少逐文件输出,只保留必要的错误和摘要日志。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>