docker中執行sed報Device or resource busy錯誤的處理原因及方式

原文出處:https://www.cnblogs.com/xuxinkun/p/7116737.html

錯誤現象

在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 fileDevice: fd28h/64808d    Inode: 265         Links: 1Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)Access: 2017-07-04 06:28:35.000000000Modify: 2017-07-04 06:28:17.000000000Change: 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 fileDevice: fd28h/64808d    Inode: 266         Links: 1Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)Access: 2017-07-04 06:29:31.000000000Modify: 2017-07-04 06:29:31.000000000Change: 2017-07-04 06:29:31.000000000/ # cat test.txt321

可以看到文件內容被正確修改了,但是同時,文件的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% /devtmpfs                    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/hostsshm                      64.0M         0     64.0M   0% /dev/shmtmpfs                    15.4G         0     15.4G   0% /proc/kcoretmpfs                    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.localnameserver 192.168.1.1options 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.localnameserver 192.168.1.254options ndots:5

這裏如果使用sed 's/192.168.1.1/192.168.1.254/g' /etc/resolv.conf > /etc/resolv.conf是無效的。最終會導致/etc/resolv.conf內容爲空。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章