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

Viewed 8060

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? Thank you advance.

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

2 Answers

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.

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 does not require sudo since it is taking advantage of the super user privileges available by default inside the container.

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.

Related