3

我的 Docker 容器 ( ubuntu:18.04) 中有一个 VPN 客户端。

客户必须执行以下操作:

mv /etc/resolv.conf /etc/resolv.conf.orig

然后客户端应该/etc/resolv.conf使用他们的 DNS 服务器创建新的。但是,移动失败并出现错误:

mv: cannot move '/etc/resolv.conf' to '/etc/resolv.conf.orig': Device or resource busy

这可以解决吗?谢谢你提前。

PS:我无法更改 VPN 客户端代码。

4

1 回答 1

7

在 Docker 容器中,该/etc/resolv.conf文件不是普通的常规文件。Docker 以一种特殊的方式对其进行管理:容器引擎将容器特定的配置写入容器外部的文件中,并将其绑定挂载/etc/resolv.conf容器内部。

当您的 VPN 客户端运行mv /etc/resolv.conf /etc/resolv.conf.orig时,事情归结为rename(2)系统调用(或来自该系列的类似调用),并且根据此系统调用的手册页,EBUSY( Device or resource busy) 错误可能由几个原因返回,包括原始文件是挂载点:

重命名失败,因为 oldpath 或 newpath 是某个进程正在使用的目录(可能作为当前工作目录,或者作为根目录,或者因为它已打开以供读取)或正在被系统使用(例如作为挂载点),而系统认为这是一个错误。(请注意,在这种情况下不需要返回 EBUSY ——无论如何进行重命名并没有错——但如果系统无法以其他方式处理这种情况,则允许返回 EBUSY。)

虽然有人说在这种情况下不能保证会产生错误,但它似乎总是针对绑定安装目标触发(我猜这可能发生在这里):

$ touch sourcefile destfile
$ sudo mount --bind sourcefile destfile
$ mv destfile anotherfile
mv: cannot move 'destfile' to 'anotherfile': Device or resource busy

因此,同样地,您不能/etc/resolv.conf在容器内移动,因为它是绑定安装,并且没有直接的解决方案。

鉴于绑定挂载/etc/resolv.conf是读写挂载,而不是只读挂载,仍然可以覆盖此文件:

$ mount | grep resolv.conf
/dev/sda1 on /etc/resolv.conf type ext4 (rw,relatime)

因此,可能的解决方法是尝试将此文件复制.orig到备份中,然后重写原始文件,而不是重命名原始文件然后重新创建它。

不幸的是,这不符合您的限制 ( I can 't change the VPN client code.),所以我敢打赌,您在这里不走运。

于 2020-03-07T09:39:20.980 回答