d.j*_*.er 3 ubuntu docker resolv
I have a VPN client in my Docker container (ubuntu:18.04).
The client must do the following:
mv /etc/resolv.conf /etc/resolv.conf.orig
Run Code Online (Sandbox Code Playgroud)
Then the client should create new /etc/resolv.conf with their DNS servers. However, the move fails with an error:
mv: cannot move '/etc/resolv.conf' to '/etc/resolv.conf.orig': Device or resource busy
Run Code Online (Sandbox Code Playgroud)
Can this be fixed? Thank you advance.
P.S.: I can 't change the VPN client code.
在 Docker 容器中,该/etc/resolv.conf文件不是普通的常规文件。Docker 以一种特殊的方式管理它:容器引擎将特定于容器的配置写入容器外部的文件中,并将其绑定挂载到/etc/resolv.conf容器内部。
当您的 VPN 客户端运行时mv /etc/resolv.conf /etc/resolv.conf.orig,事情归结为rename(2)系统调用(或来自该系列的类似调用),并且,根据此系统调用的联机帮助页,EBUSY( Device or resource busy) 错误可能由几个原因返回,包括原始文件是挂载点:
EBUSY
重命名失败,因为 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
Run Code Online (Sandbox Code Playgroud)
因此,类似地,您不能/etc/resolv.conf在容器内移动,因为它是一个绑定安装,并且没有直接的解决方案。
鉴于绑定挂载/etc/resolv.conf是读写挂载,而不是只读挂载,仍然可以覆盖此文件:
$ touch sourcefile destfile
$ sudo mount --bind sourcefile destfile
$ mv destfile anotherfile
mv: cannot move 'destfile' to 'anotherfile': Device or resource busy
Run Code Online (Sandbox Code Playgroud)
因此,可能的解决方法是尝试将此文件复制到.orig备份,然后重写原始文件,而不是重命名原始文件,然后重新创建它。
不幸的是,这不符合您的限制 ( I can 't change the VPN client code.),所以我敢打赌您在这里不走运。
任何需要将文件移动到/etc/resolv.conf fails in docker container.
The workaround is to rewrite the original file instead of moving or renaming a modified version onto it.
例如,在bash出现提示时使用以下命令:
(rc=$(sed 's/^\(nameserver 192\.168\.\)/# \1/' /etc/resolv.conf)
echo "$rc" > /etc/resolv.conf)
Run Code Online (Sandbox Code Playgroud)
这可以通过重写来实现/etc/resolv.conf as follows:
/etc/resov.conf through the stream editor, sednameserver 192.168.rc/etc/resolv.conf用更新的内容覆盖原始文件"$rc"命令列表放在括号中是为了在子 shell 中进行操作,以避免变量名污染当前 shell 的命名空间rc, just in case it happens to be in use.
请注意,此命令不需要sudo,因为它利用了容器内默认可用的超级用户权限。否则,使用
sudo sh -c 'rc=$(sed 's/^\(nameserver 192\.168\.\)/# \1/' /etc/resolv.conf); echo "$rc" > /etc/resolv.conf'
Run Code Online (Sandbox Code Playgroud)
作为Michael Johansen clarifies below.
注意sed -i (editing in-place) involves moving the updated file onto the original and will not work.
vi但是,如果容器中存在可视化编辑器,则可以直接编辑和/etc/resolv.conf保存原始文件vi,从而可以进行编辑和保存。vi
| 归档时间: |
|
| 查看次数: |
4056 次 |
| 最近记录: |