共计 3282 个字符,预计需要花费 9 分钟才能阅读完成。
Docker 中执行 sed: can’t move ‘/etc/resolv.conf73UqmG’ to ‘/etc/resolv.conf’: Device or resource busy 错误的处
错误现象
在 docker 容器中想要修改 /etc/resolv.conf
中的 namesever,使用 sed 命令进行执行时遇到错误:
/ # sed -i 's/192.168.1.1/192.168.1.254/g' /etc/resolv.conf
sed: can't move'/etc/resolv.conf73UqmG'to'/etc/resolv.conf': Device or resource busy
但是可以通过 vi/vim 直接修改这个文件 /etc/resolv.conf
这个文件的内容。
问题原因
sed 命令的实质并不是修改文件,而是产生一个新的文件替换原有的文件。这里我们做了一个实验。
我先创建了一个 test.txt
的文件,文件内容是 123
。然后我使用sed
命令对文件内容进行了替换。再次查看test.txt
。
/ # stat test.txt
File: test.txt
Size: 4 Blocks: 8 IO Block: 4096 regular file
Device: fd28h/64808d Inode: 265 Links: 1
Access: (0644/-rw-r--r--) Uid: (0/ root) Gid: (0/ root)
Access: 2017-07-04 06:28:35.000000000
Modify: 2017-07-04 06:28:17.000000000
Change: 2017-07-04 06:29:03.000000000
/ # cat test.txt
123
/ # sed -i 's/123/321/g' test.txt
/ # stat test.txt
File: test.txt
Size: 4 Blocks: 8 IO Block: 4096 regular file
Device: fd28h/64808d Inode: 266 Links: 1
Access: (0644/-rw-r--r--) Uid: (0/ root) Gid: (0/ root)
Access: 2017-07-04 06:29:31.000000000
Modify: 2017-07-04 06:29:31.000000000
Change: 2017-07-04 06:29:31.000000000
/ # cat test.txt
321
可以看到文件内容被正确修改了,但是同时,文件的 inode 也修改了。说明了实质上是新生成的文件替换了原有的文件。但是 vim/vi 是在原文件基础上修改的,所以 inode 没有变化。
在 docker 中,/etc/resolv.conf
是通过挂载入容器的。所以当你想去删除这个挂载文件,也就是挂载点时,自然就会报Device or resource busy
。
这个跟是不是特权 privilege 没有关系。即使是 privilege 的容器,也会有这个问题。
/ # rm /etc/resolv.conf
rm: can't remove'/etc/resolv.conf': Device or resource busy
其实不仅仅 /etc/resolv.conf
,还有/etc/hostname
,/etc/hosts
等文件都是通过挂载方式挂载到容器中来的。所以想要用 sed 对他们进行修改,都会遇到这样的问题。我们可以通过 df -h
查看容器内的挂载情况。
/ # df -h
Filesystem Size Used Available Use% Mounted on
/dev/mapper/docker-253:2-807144231-37acfcd86387ddcbc52ef8dac69d919283fc5d9d8ab5f55fd23d1c782e3b1c70
10.0G 33.8M 10.0G 0% /
tmpfs 15.4G 0 15.4G 0% /dev
tmpfs 15.4G 0 15.4G 0% /sys/fs/cgroup
/dev/mapper/CentOS-home
212.1G 181.8G 30.3G 86% /run/secrets
/dev/mapper/centos-home
212.1G 181.8G 30.3G 86% /dev/termination-log
/dev/mapper/centos-home
212.1G 181.8G 30.3G 86% /etc/resolv.conf
/dev/mapper/centos-home
212.1G 181.8G 30.3G 86% /etc/hostname
/dev/mapper/centos-home
212.1G 181.8G 30.3G 86% /etc/hosts
shm 64.0M 0 64.0M 0% /dev/shm
tmpfs 15.4G 0 15.4G 0% /proc/kcore
tmpfs 15.4G 0 15.4G 0% /proc/timer_stats
如何解决
使用 vi 固然可以,但是对于批量操作就不是很合适了。可以通过 sed 和 echo 的组合命令echo "$(sed's/192.168.1.1/192.168.1.254/g'/etc/resolv.conf)" > /etc/resolv.conf
即可实现替换。
/ # cat /etc/resolv.conf
search default.svc.games.local svc.games.local games.local
nameserver 192.168.1.1
options ndots:5
/ # echo "$(sed's/192.168.1.1/192.168.1.254/g'/etc/resolv.conf)" > /etc/resolv.conf
/ # cat /etc/resolv.conf
search default.svc.games.local svc.games.local games.local
nameserver 192.168.1.254
options ndots:5
这里如果使用
sed 's/192.168.1.1/192.168.1.254/g' /etc/resolv.conf > /etc/resolv.conf
是无效的。最终会导致/etc/resolv.conf
内容为空。
更多 Docker 相关教程见以下内容:
Docker 安装应用(CentOS 6.5_x64) http://www.linuxidc.com/Linux/2014-07/104595.htm
Ubuntu 16.04 服务器上配置使用 Docker http://www.linuxidc.com/Linux/2017-06/145176.htm
Ubuntu 15.04 下安装 Docker http://www.linuxidc.com/Linux/2015-07/120444.htm
Docker 安装实例 http://www.linuxidc.com/Linux/2017-04/142666.htm
Docker 创建基础镜像 http://www.linuxidc.com/Linux/2017-05/144112.htm
在 Ubuntu 15.04 上如何安装 Docker 及基本用法 http://www.linuxidc.com/Linux/2015-09/122885.htm
Ubuntu 16.04 上 Docker 使用手记 http://www.linuxidc.com/Linux/2016-12/138490.htm
使用 Docker 分分钟启动常用应用 http://www.linuxidc.com/Linux/2017-04/142649.htm
Ubuntu 16.04 下 Docker 修改配置文件不生效解决办法 http://www.linuxidc.com/Linux/2017-05/143862.htm
Docker 的详细介绍:请点这里
Docker 的下载地址:请点这里
本文永久更新链接地址:http://www.linuxidc.com/Linux/2017-10/147489.htm