Unix & Linux Asked by l0b0 on January 6, 2021
Rather than using mount | grep
, I’d like to use mount -l -t bind
, but that doesn’t work, and -t none
shows all mounts.
Bind mounts are not a filesystem type, nor a parameter of a mounted filesystem; they're parameters of a mount operation. As far as I know, the following sequences of commands lead to essentially identical system states as far as the kernel is concerned:
mount /dev/foo /mnt/one; mount --bind /mnt/one /mnt/two
mount /dev/foo /mnt/two; mount --bind /mnt/two /mnt/one
So the only way to remember what mounts were bind mounts is the log of mount
commands left in /etc/mtab
. A bind mount operation is indicated by the bind
mount option (which causes the filesystem type to be ignored). But mount
has no option to list only filesystems mounted with a particular set of sets of options. Therefore you need to do your own filtering.
mount | grep -E '[,(]bind[,)]'
</etc/mtab awk '$4 ~ /(^|,)bind(,|$)/'
Note that /etc/mtab
is only useful here if it's a text file maintained by mount
. Some distributions set up /etc/mtab
as a symbolic link to /proc/mounts
instead; /proc/mounts
is mostly equivalent to /etc/mtab
but does have a few differences, one of which is not tracking bind mounts.
One piece of information that is retained by the kernel, but not shown in /proc/mounts
, is when a mount point only shows a part of the directory tree on the mounted filesystem. In practice this mostly happens with bind mounts:
mount --bind /mnt/one/sub /mnt/partial
In /proc/mounts
, the entries for /mnt/one
and /mnt/partial
have the same device, the same filesystem type and the same options. The information that /mnt/partial
only shows the part of the filesystem that's rooted at /sub
is visible in the per-process mount point information in /proc/$pid/mountinfo
(column 4). Entries there look like this:
12 34 56:78 / /mnt/one rw,relatime - ext3 /dev/foo rw,errors=remount-ro,data=ordered
12 34 56:78 /sub /mnt/partial rw,relatime - ext3 /dev/foo rw,errors=remount-ro,data=ordered
Correct answer by Gilles 'SO- stop being evil' on January 6, 2021
This is similar to the other findmnt answer, but avoids the formatting issue.
To show all submounts:
findmnt --kernel -n --list | grep '['
To show all submounts of filesystems of type ext4:
findmnt --kernel -t ext4 -n --list | grep '['
To show all mounts excluding submounts:
findmnt --kernel -n --list | grep -v '['
To show all mounts of filesystems of type ext4 excluding submounts:
findmnt --kernel -t ext4 -n --list | grep -v '['
The "-n" removes the headers and the "--list" removes the lines of the "tree" format.
Tested on Debian stretch.
Answered by sg23 on January 6, 2021
The kernel doesn't handle bind mounts different from normal mounts after the fact. The only differ in what happens while mount
runs.
When you mount a filesystem (eg. with mount -t ext4 /dev/sda1 /mnt
) the kernel (a bit simplified) performs three steps:
-t
or use -t auto
mount
guesses the type for you and provides the guessed type to the kernel)nodev
for example is an option on the mountpoint, not on the filesystem. You can have a bind mount with nodev
and one without)If you perform a bind mount (eg. with mount --bind /a /b
) the following happens:
(I'll skip mount --move
, because it's not relevant to the question.)
This quite is similar to how files are created on Linux:
If you make a hard link the following happens:
As you can see, the created file and the hard link are indistinguishable:
$ touch first
$ ln first second
$ ls -li
1184243 -rw-rw-r-- 2 cg909 cg909 0 Feb 20 23:56 /tmp/first
1184243 -rw-rw-r-- 2 cg909 cg909 0 Feb 20 23:56 /tmp/second
But, as you can identify all hardlinks to a file by comparing the inode numbers, you can identify all mounts to a filesystem by comparing the major:minor numbers of mounts.
You can do this with findmnt -o TARGET,MAJ:MIN
or by directly looking at /proc/self/mountinfo
(see the Linux kernel documentation for more information).
The following Python script lists all bind mounts. It assumes that the oldest mount point with the shortest relative path to the root of the mounted file system is the original mount.
#!/usr/bin/python3
import os.path, re
from collections import namedtuple
MountInfo = namedtuple('MountInfo', ['mountid', 'parentid', 'devid', 'root', 'mountpoint', 'mountoptions', 'extra', 'fstype', 'source', 'fsoptions'])
mounts = {}
def unescape(string):
return re.sub(r'\([0-7]{3})', (lambda m: chr(int(m.group(1), 8))), string)
with open('/proc/self/mountinfo', 'r') as f:
for line in f:
# Parse line
mid, pid, devid, root, mp, mopt, *tail = line.rstrip().split(' ')
extra = []
for item in tail:
if item != '-':
extra.append(item)
else:
break
fstype, src, fsopt = tail[len(extra)+1:]
# Save mount info
mount = MountInfo(int(mid), int(pid), devid, unescape(root), unescape(mp), mopt, extra, fstype, unescape(src), fsopt)
mounts.setdefault(devid, []).append(mount)
for devid, mnts in mounts.items():
# Skip single mounts
if len(mnts) <= 1:
continue
# Sort list to get the first mount of the device's root dir (if still mounted)
mnts.sort(key=lambda x: x.root)
src, *binds = mnts
# Print bind mounts
for bindmount in binds:
if src.root == bindmount.root:
srcstring = src.mountpoint
else:
srcstring = src.mountpoint+':/'+os.path.relpath(bindmount.root, src.root)
print('{0} -> {1.mountpoint} ({1.mountoptions})'.format(srcstring, bindmount))
Answered by cg909 on January 6, 2021
unset DONE1FSES
FSES=$(findmnt -vUPno SOURCE,FSROOT,TARGET,MAJ:MIN)
FSES=${FSES//MAJ:MIN/MAJ_MIN}
while read SEARCH1FS
do
unset DONE2FSES
eval "$SEARCH1FS"
SEARCH1SOURCE=$SOURCE
SEARCH1FSROOT=$FSROOT
SEARCH1TARGET=$TARGET
SEARCH1MAJMIN=$MAJ_MIN
FS1WASHANDLED=0
while read DONE1FS
do
if [[ $DONE1FS == $MAJ_MIN ]]
then
FS1WASHANDLED=1
break
fi
done < <(echo "$DONE1FSES")
if [[ ($SEARCH1FSROOT == /) && ($FS1WASHANDLED == 0) ]]
then
DONE1FSES+=$MAJ_MIN$'n'
while read SEARCH2FS
do
eval "$SEARCH2FS"
SEARCH2SOURCE=$SOURCE
SEARCH2FSROOT=$FSROOT
SEARCH2TARGET=$TARGET
SEARCH2MAJMIN=$MAJ_MIN
FS2WASHANDLED=0
while read DONE2FS
do
if [[ $DONE2FS == $SEARCH2FS ]]
then
FS2WASHANDLED=1
break
fi
done < <(echo "$DONE2FSES")
if [[ ($SEARCH1MAJMIN == $SEARCH2MAJMIN) && ($SEARCH1TARGET != $SEARCH2TARGET ) && ($FS2WASHANDLED == 0 ) ]]
then
DONE2FSES+=$SEARCH2FS$'n'
echo "$SEARCH1TARGET$SEARCH2FSROOT --> $SEARCH2TARGET"
fi
done < <(echo "$FSES")
fi
done < <(echo "$FSES")
Answered by n3rdopolis on January 6, 2021
Maybe this could do the trick:
findmnt | grep "["
Example:
$ mkdir /tmp/foo
$ sudo mount --bind /media/ /tmp/foo
$ findmnt | grep "["
│ └─/tmp/foo /dev/sda2[/media] ext4 rw,relatime,data=ordered
Answered by olopopo on January 6, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP