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內容為空。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM