What is the difference between ln -s and mount --bind?

I am trying to understand difference between using ln -s and mount --bind. In basic scenario I can use both to access one directory from somewhere else. In what scenarios those two will behave differently ?


Solution 1:

They will behave differently in at least two cases:

  • In a chroot, if the link target is outside the chroot, the link will be dead. A bind mount will still be accessible.
  • Several programs can distinguish between symbolic links and actual directories or files. Few (if any) can distinguish between a directory or file and the one mounted on it. This also extends to symbolic links to something (A) which have something else (B) mounted on them. The link will show the contents of mount target (B) instead of the original (A).

Also, you can bind mount a directory or file on an existing directory or file, masking the original contents (rendering the original contents inaccessible unless the original was bind mounted elsewhere). A symbolic link requires that the original be moved or deleted.

Solution 2:

Well, ln -s creates a symbolic link, whereas mount --bind creates a mount.

A symbolic link is a special type of file. If you do ln -s /var/target /var/link, then /var/link will be a file containing the path "/var/target" in it. The only difference between a symbolic link and an ordinary file is that when a program tries to perform an operation on a symbolic link, the operation is usually performed on the target instead of the file. So now if you do ls /var/link, the ls program will try to get a directory listing for /var/link, but will actually get a directory listing for /var/target instead.

Symbolic links are still just files, though. They can be renamed and deleted and all that jazz. Note that you can't create a symbolic link (or an ordinary file, for that matter) called /var/link if there's already a file called /var/link; you'd need to get rid of it first.

A mount isn't a file; it's a record that the kernel keeps in memory. If you do mount --bind /var/target /var/mount, the kernel will record the fact that /var/mount is now a new name for /var/target. (I don't know the details; in particular, I don't know if mounting something in a subdirectory of /var/target will make it show up in /var/mount as well, or why or why not. Edits to this answer would be appreciated.) So now if you do ls /var/mount, the same thing will happen as if you did ls /var/target, because /var/mount and /var/target are the same directory.

Mounts aren't files. I don't know what would happen if you tried to rename or delete /var/mount. Note that you can't mount anything at /var/mount unless there's already a directory at /var/mount.

Solution 3:

Additionally, ln -s would survive a reboot; whereas mount --bind would not, unless you edit /etc/fstab to make it persistent.