在我的一些构建脚本中,我一直使用挂载命名空间作为安全挂载的机制,而不会在脚本终止时留下这些挂载。 当该命名空间中的最后一个进程退出时,未共享的挂载点将被隐式卸载。
我的脚本通常包括这样的 stansa:
#!/bin/bash
self_ns=$(ls -lh /proc/self/ns/mnt)
init_ns=$(ls -lh /proc/$PPID/ns/mnt)
if [ "${self_ns#*mnt:}" = "${init_ns#*mnt:}" ] ; then
unshare --mount $0 "$@"
exit $?
fi
虽然这对我来说已经有一段时间了,但我最近在 jenkins 构建服务器上遇到了问题。
我认为问题在于构建脚本本身正在jenkins chroot 环境中执行。因此,当脚本执行时unshare --mount ...
,它会失败并出现错误:
unshare: cannot change root filesystem propagation: Invalid argument
不幸的是,我真的不明白这个限制或如何绕过它。当我在命令行上尝试 chroot 时,我无法复制此错误。我不知道詹金斯插件做了什么导致这种情况。
最重要的是,这些挂载点在每次退出时都会被删除,不会失败。
根据 AB 的评论,我找到了一种解决方法:
AB 写道:
基于此,我发现这不起作用:
但这有效:
问题的原因是
unshare
试图设置根目录的挂载传播标志,这只能对挂载点进行。Jenkins chroot 环境的根目录不是挂载点。例如:
完整再现:
一个简单的解决方法,它不会在挂载命名空间之外进行挂载。它转义 chroot 以设置挂载传播,并假设 mount 命令在 chroot 之外可用:
或者将 chroot 转换为
pivot_root
环境: