"Device or resource busy" when i try move /etc/resolv.conf in ubuntu:18.04. How fix it?
Asked Answered
L

4

11

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

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

Can this be fixed?

P.S.: I can 't change the VPN client code.

Lucialucian answered 5/3, 2020 at 16:18 Comment(0)
G
18

Within the Docker container the /etc/resolv.conf file is not an ordinary regular file. Docker manages it in a special manner: the container engine writes container-specific configuration into the file outside of the container and bind-mounts it to /etc/resolv.conf inside the container.

When your VPN client runs mv /etc/resolv.conf /etc/resolv.conf.orig, things boil down to the rename(2) syscall (or similar call from this family), and, according to the manpage for this syscall, EBUSY (Device or resource busy) error could be returned by few reasons, including the situation when the original file is a mountpoint:

EBUSY

The rename fails because oldpath or newpath is a directory that is in use by some process (perhaps as current working directory, or as root directory, or because it was open for reading) or is in use by the system (for example as mount point), while the system considers this an error. (Note that there is no requirement to return EBUSY in such cases — there is nothing wrong with doing the rename anyway — but it is allowed to return EBUSY if the system cannot otherwise handle such situations.)

Though there is a remark that the error is not guaranteed to be produced in such circumstances, it seems that it always fires for bind-mount targets (I guess that probably this happens here):

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

So, similarly, you cannot move /etc/resolv.conf inside the container, for it is a bind-mount, and there is no straight solution.

Given that the bind-mount of /etc/resolv.conf is a read-write mount, not a read-only one, it is still possible to overwrite this file:

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

So, the possible fix could be to try copying this file to the .orig backup and then rewriting the original one instead of renaming the original file and then re-creating it.

Unfortunately, this does not meet your restrictions (I can 't change the VPN client code.), so I bet that you are out of luck here.

Gilbertine answered 7/3, 2020 at 9:39 Comment(2)
This answer helped me, as I forgot to remove a bind mount I had in place for debugging purposes. Thank you!Mcgriff
As @vin shows, we can cp+umount+cp. Not pretty, but it works for Cisco Systems VPN Agent (secureclient) v5.1, which tries to do this: mv /etc/resolv.conf /etc/resolv.conf.vpnbackupInhaler
L
6

Any method that requires moving a file onto /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.

For example, use the following at a bash prompt:

(rc=$(sed 's/^\(nameserver 192\.168\.\)/# \1/' /etc/resolv.conf)
     echo "$rc" > /etc/resolv.conf)

This works by rewriting /etc/resolv.conf as follows:

  • read and modify the current contents of /etc/resov.conf through the stream editor, sed
  • the sed script in this example is for commenting out lines starting with nameserver 192.168.
  • save the updated contents in a variable, rc
  • overwrite the original file /etc/resolv.conf with updated contents in "$rc"

The command list is in parentheses to operate in a sub-shell to avoid polluting the current shell's name space with a variable name rc, just in case it happens to be in use.

Note that this command did not require sudo since it took advantage of the super user privileges available by default inside the container. Otherwise, use

sudo sh -c 'rc=$(sed 's/^\(nameserver 192\.168\.\)/# \1/' /etc/resolv.conf); echo "$rc" > /etc/resolv.conf'

as Michael Johansen clarifies below.

Note that sed -i (editing in-place) involves moving the updated file onto the original and will not work.

But if the visual editor, vi, is available in the container, editing and saving /etc/resolv.conf with vi works, since vi modifies the original file directly.

Levin answered 23/6, 2022 at 14:41 Comment(2)
Please include an explanation with your answer to help readers understand how this works, and solves the problem. You can click the edit button at the bottom of your answer to add an explanation. Additionally, you may find it beneficial reading how to answerRoderica
I got permission denied, so I had to use sudo: sudo sh -c 'rc=$(sed "s/^\(nameserver 192\.168\.\)/# \1/" /etc/resolv.conf); echo "$rc" > /etc/resolv.conf'Pourboire
B
1

⚠️ Use this with caution.

Check if the /etc/resolv.conf is a mount or not.
# mount | grep resolv.conf
/dev/mapper/ubuntu--vg-ubuntu--lv on /etc/resolv.conf type ext4 (rw,relatime)

Back up the resolv.conf file.

# cp /etc/resolv.conf /root/resolv.conf.ori

Unmount the mounted file.

# umount /etc/resolv.conf
OR
# umount -f /etc/resolv.conf
(-f is for force unmount)

Now try again.

Buckwheat answered 14/5 at 13:4 Comment(0)
A
0

I had the same problem. The following did the trick

Within my docker file, I did the following:

ADD resolv.conf /tmp/resolv.conf then, under RUN one of my command was:

RUN echo "Hello" && \
    cat /tmp/resolv.conf > /etc/resolv.conf && \
    echo "more commands here" && \
    cat -n /etc/resolv.conf && \
    yum clean all && yum upgrade && yum clean all && \
    rm -fr /tmp/*
Apoplexy answered 15/8 at 5:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.