mount namespace 中绑定挂载的传播属性
在 Linux 里,mount --bind 只是在另一个路径上建立同一挂载的视图;它不会自动决定后续挂载事件是否同步。真正决定“这个目录里的新挂载要不要出现在另一个位置”的,是挂载传播属性。常用的四种状态是 shared、slave、private 和 unbindable。
官方地址:https://docs.kernel.org/filesystems/sharedsubtree.html
把 bind mount 理解成“复制挂载视图”,把传播属性理解成“挂载事件的边界”:需要双向同步时用 shared,需要只从宿主接收时用 slave,需要隔离时用 private;unbindable 则是在 private 基础上禁止再次绑定。
先分清 bind mount 和传播属性
绑定挂载连接的是一个已有的挂载树和新的挂载点。它可以让两个路径看到相同的文件系统内容,但“看到相同内容”和“收到之后产生的新挂载”不是一回事。比如在源路径下面后来挂载一个临时文件系统,目标路径是否出现对应的子挂载,取决于两边的传播关系。
mount namespace 也不能替代传播属性。创建新的命名空间时,会得到一份挂载视图;如果相关挂载属于 shared peer group,事件仍可能跨命名空间传播。如果需要完全隔离,通常要在子命名空间中把目标树设为 private,再进行后续操作。
本次实验只使用独立的临时目录和 bind mount,不直接修改生产根目录。下面的命令需要 root 权限,适合在一次性虚拟机或专门的 Linux 实验环境中阅读和操作。

四种状态分别意味着什么
可以先用一张速查表建立判断标准:
| 状态 | 接收事件 | 转发事件 | 适合的边界 |
|---|---|---|---|
shared | 是 | 是 | 多个挂载视图需要保持同步 |
slave | 从 master 接收 | 否 | 子环境只跟随宿主,不反向影响宿主 |
private | 否 | 否 | 命名空间或服务需要独立挂载树 |
unbindable | 否 | 否 | 还要禁止该挂载被再次 bind |
shared 的多个挂载属于同一个 peer group,挂载和卸载事件会在组内传播。slave 有一个 master,只接收来自 master 的事件,slave 自己产生的事件不会回传。private 不接收也不转发传播事件。unbindable 的传播语义和 private 类似,但它不能作为 bind mount 的源。
建立一个可回收的绑定挂载实验
先创建实验目录,再绑定一个子目录。这里不挂载真实块设备,而是把另一个普通目录作为后续的“挂载事件”演示对象,避免实验依赖具体磁盘。
# 建立独立实验树;不要直接把生产目录作为实验源路径 LAB=/tmp/mount-propagation-lab mkdir -p "$LAB/source/incoming" "$LAB/bind/incoming" "$LAB/event-source" # 创建 bind mount,让 bind 目录先看到 source 的内容 mount --bind "$LAB/source" "$LAB/bind" # 读取挂载点和传播状态;PROPAGATION 列是判断依据 findmnt -o TARGET,FSTYPE,PROPAGATION "$LAB/source" "$LAB/bind" # 显式设为 private,先得到不会向外传播的基线 mount --make-private "$LAB/source" mount --make-private "$LAB/bind" findmnt -o TARGET,PROPAGATION "$LAB/source" "$LAB/bind"
检查时重点看 PROPAGATION 列,而不是只看两个路径能否列出相同文件。实验树如果原本继承了宿主的 shared 属性,后续命令可能影响其他挂载视图,所以先显式设为 private 更容易解释和回收。
用 shared 观察双向传播
shared 的核心是“挂载事件属于同一个传播组”。先让源挂载成为 shared,再建立一个共享的 bind 视图;随后在其中一个视图下面创建新的挂载,理论上另一个 peer 也会获得对应的挂载点。
# 把源挂载加入 shared peer group;这是传播关系,不是文件复制 mount --make-shared "$LAB/source" # 在源树上建立第二个视图,并把目标也明确设为 shared mount --bind "$LAB/source" "$LAB/bind" mount --make-shared "$LAB/bind" # 用 findmnt 读取传播标记;shared:数字表示 peer group 标识 findmnt -o TARGET,PROPAGATION "$LAB/source" "$LAB/bind" # 在源树中建立一个新的 bind mount,模拟“后来发生的挂载事件” mount --bind "$LAB/event-source" "$LAB/source/incoming" # 检查两个视图是否都出现 incoming;不要只检查目录是否存在 findmnt -R "$LAB/source" findmnt -R "$LAB/bind"
这段实验的结论不是“bind 一定双向同步”,而是“当挂载处在同一个 shared 传播关系中时,新的挂载事件可以同步到 peer”。如果只做了 mount --bind,没有确认传播状态,就不能从 bind 这一动作推断后续事件的方向。
用 slave 把传播方向限制为单向
容器和服务隔离经常需要这样的关系:宿主新增的挂载能被子环境看到,但子环境自己的挂载不能反向出现在宿主。这时可以让子侧成为 master 的 slave。
# 先让源树成为 shared,作为 master 传播端 mount --make-shared "$LAB/source" # 创建 bind 视图,再将目标变成 slave;它接收 master 事件但不反向发送 mount --bind "$LAB/source" "$LAB/bind" mount --make-slave "$LAB/bind" # 读取 master/slave 关系,确认 bind 端不再是普通 private 视图 findmnt -o TARGET,PROPAGATION "$LAB/source" "$LAB/bind" # 生产脚本中应先用 findmnt 找到目标,再决定是否允许该挂载传播 findmnt -R "$LAB"
slave 不是“只读目录”。它仍然可以在自己的视图中进行允许的挂载操作,只是这些新事件不会回传给 master。需要双向协作时不要误用 slave;需要彻底隔离时也不要把 slave 当成 private。
把传播属性放进 mount namespace
进入新的 mount namespace 后,最容易踩的坑是只看到“路径不同”,却没有判断挂载树是否仍处于 shared 传播关系。可以在 namespace 内先把根挂载树设为 private,再对确实需要从宿主接收的子树使用 slave。

# 在一次性实验中创建新的 mount namespace;需要 root 或相应的 namespace 权限 unshare --mount --fork /bin/sh
mount --make-rprivate / 会改变当前命名空间内根挂载树的传播属性,因此应只在隔离的实验进程中使用。若实际目标是让容器接收宿主的设备或卷挂载,通常只把明确的子树设为 slave 或 shared,而不是对整个根树做宽泛修改。
检查与清理时看哪些证据
排查传播问题时,把检查拆成三层:挂载点是否存在、传播类型是什么、后续事件是否出现在预期视图。findmnt 适合看当前挂载树;/proc/self/mountinfo 可以作为更底层的补充,但不要把一串数字直接当成传播方向。
# 只列出实验树,先确认 bind mount 的 TARGET 和 SOURCE findmnt -R "$LAB" # 单独读取传播属性,关注 shared、master、propagate_from 等字段 findmnt -o TARGET,SOURCE,FSTYPE,PROPAGATION "$LAB/source" "$LAB/bind" # 结束实验时先卸载子挂载,再卸载 bind mount,最后删除空目录 umount "$LAB/source/incoming" 2>/dev/null || true umount "$LAB/bind/incoming" 2>/dev/null || true umount "$LAB/bind" 2>/dev/null || true rmdir "$LAB/source/incoming" "$LAB/bind/incoming" 2>/dev/null || true rm -rf "$LAB"
清理命令里的 || true 只是让“已经不存在的实验挂载”不阻塞后续回收;生产脚本不应吞掉所有卸载错误,而应记录仍被进程占用的挂载点。删除目录不会卸载挂载本身,必须先处理挂载关系。
按需求选择传播属性
| 需求 | 优先考虑 | 主要原因 |
|---|---|---|
| 多个视图需要看到同一批新挂载 | shared | 事件在 peer group 内传播 |
| 子环境跟随宿主但不能反向影响宿主 | slave | 只接收 master 事件 |
| 服务或 namespace 完全自主管理挂载 | private | 不接收也不转发事件 |
| 挂载树不能作为 bind 源 | unbindable | 阻止再次绑定 |
最后记住三个判断顺序:先确认自己正在看的挂载点,接着读取它的传播属性,最后用一个受控的子挂载验证事件方向。这样即使 mount namespace、bind mount 和容器运行时叠在一起,也能把“看得到文件”与“传播新挂载”分开定位。
常见问题
为什么做了 bind mount,目标目录却没有同步新挂载?
因为 bind mount 不等于 shared。先用 findmnt -o TARGET,PROPAGATION 读取两边状态;如果是 private,就不会接收或转发新挂载事件。
slave 和 private 有什么区别?
private 完全不参与传播;slave 可以从 master 接收事件,只是不把自己的事件反向转发。容器需要跟随宿主挂载时,slave 通常比 private 更贴合目标。
为什么实验会影响宿主机的挂载树?
常见原因是实验目录继承了 shared 属性,或者在没有隔离的 mount namespace 中直接修改了共享挂载。实验开始时使用独立目录,并在 namespace 内显式执行 mount --make-rprivate /。
unbindable 什么时候有用?
当一棵挂载树不应该被再次 bind,且也不需要接收或转发事件时,可以使用 unbindable。它主要表达“不可复制这个挂载入口”的限制,不是更强的权限控制。
Fetch Streams 分段读取大响应体的背压控制
- 上一篇
- Fetch Streams 分段读取大响应体的背压控制
- 下一篇
- database/sql 查询上下文取消后的 rows 状态
-
- 文章 · linux | 3小时前 |
- ip rule 与多路由表实现策略路由
- 406浏览 收藏
-
- 文章 · linux | 4小时前 |
- nftables 动态集合维护临时封禁地址
- 248浏览 收藏
-
- 文章 · linux | 7小时前 | Linux · journalctl Linux日志 journald systemd-journald Storage=persistent
- journald Storage=persistent 保留重启前日志
- 147浏览 收藏
-
- 文章 · linux | 9小时前 |
- systemd watchdog 监测服务心跳的配置方法
- 482浏览 收藏
-
- 文章 · linux | 21小时前 |
- Linux zram 写回如何在内存与磁盘间平衡
- 373浏览 收藏
-
- 文章 · linux | 23小时前 |
- Linux Landlock 怎样限制普通进程访问文件目录
- 151浏览 收藏
-
- 文章 · linux | 1天前 |
- Linux dm-verity 如何校验只读根文件系统
- 190浏览 收藏
-
- 文章 · linux | 1天前 |
- Linux nftables 集合如何动态维护封禁地址
- 193浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 408次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 484次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 494次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 440次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 268次使用
-
- 详解golang执行Linuxshell命令完整场景下的使用方法
- 2023-01-07 426浏览
-
- go程序部署到linux上运行的实现方法
- 2023-01-02 387浏览
-
- Linux系统下Go语言开发环境搭建
- 2023-01-07 242浏览
-
- Go 容器遍历的实现示例
- 2022-12-23 133浏览
-
- Golang: 内建容器的用法
- 2022-12-30 496浏览

