Daftar hanya ikatan mount

24

Daripada menggunakan mount | grep, saya ingin menggunakan mount -l -t bind, tapi itu tidak berhasil, dan -t nonemenunjukkan semua tunggangan.

l0b0
sumber

Jawaban:

28

Bind mounts bukan tipe sistem file, atau parameter dari sistem file yang dipasang; mereka adalah parameter operasi mount . Sejauh yang saya tahu, urutan perintah berikut mengarah pada status sistem yang pada dasarnya identik sejauh menyangkut kernel:

mount /dev/foo /mnt/one; mount --bind /mnt/one /mnt/two
mount /dev/foo /mnt/two; mount --bind /mnt/two /mnt/one

Jadi satu-satunya cara untuk mengingat mount apa yang mengikat mount adalah log dari mountperintah yang tersisa /etc/mtab. Operasi mount bind ditunjukkan oleh opsibind mount (yang menyebabkan tipe sistem file diabaikan). Tetapi tidak memiliki opsi untuk mendaftar hanya sistem file yang dipasang dengan seperangkat set opsi tertentu. Karena itu Anda perlu melakukan pemfilteran sendiri.mount

mount | grep -E '[,(]bind[,)]'
</etc/mtab awk '$4 ~ /(^|,)bind(,|$)/'

Perhatikan bahwa /etc/mtabini hanya berguna di sini jika file teks dikelola oleh mount. Beberapa distribusi ditetapkan /etc/mtabsebagai tautan simbolik /proc/mountssebagai gantinya; /proc/mountssebagian besar setara dengan /etc/mtabtetapi memang memiliki beberapa perbedaan, salah satunya adalah tidak melacak bind mounts.

Salah satu informasi yang disimpan oleh kernel, tetapi tidak ditampilkan /proc/mounts, adalah ketika titik mount hanya memperlihatkan bagian dari pohon direktori pada sistem file yang di-mount. Dalam praktiknya ini kebanyakan terjadi dengan bind mounts:

mount --bind /mnt/one/sub /mnt/partial

Di /proc/mounts, entri untuk /mnt/onedan /mnt/partialmemiliki perangkat yang sama, jenis sistem file yang sama dan opsi yang sama. Informasi yang /mnt/partialhanya memperlihatkan bagian dari sistem file yang di-root /subdapat dilihat pada informasi titik mount per-proses di /proc/$pid/mountinfo(kolom 4). Entri di sana terlihat seperti ini:

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
Gilles 'SANGAT berhenti menjadi jahat'
sumber
1
@Gilles Sebenarnya, Anda bisa melakukan ini hanya menggunakan findmnt | fgrep [seperti yang dijelaskan di sini .
aculich
@Gilles Apa mount --versionyang Anda gunakan yang merekam bindinformasi /etc/mtab? Saya menggunakan versi 2.20.1 dan saya melihat sumber-sumber terbaru dan dalam kasus apa pun saya tidak melihat informasi yang direkam di mana saja yang akan memungkinkan Anda untuk menerima bind. Di sisi lain, apa yang saya sarankan dalam jawaban saya sebenarnya daftar mengikat gunung dibuat dengan --bindserta menggunakan bind opsi .
aculich
@aculich </etc/mtab awk …adalah POSIX-compliant (Saya lupa apakah itu didukung di Bourne). Periksa fakta Anda. Saya dapat mengonfirmasi bahwa /etc/mtabmemiliki bindopsi untuk sistem file yang terpasang mount --bind /source /targetpada pada Debian stable (mount dari util-linux-ng 2.17.2).
Gilles 'SANGAT berhenti menjadi jahat'
@Gilles Saya menghapus komentar saya yang salah untuk menghilangkan kebingungan. Anda benar, ini memang sesuai dengan POSIX. Juga sekarang saya mengerti alasan kita melihat perilaku berbeda dari mountdan /etc/mtab. Anda menggunakan stabil Debian yang memiliki versi util-linux-ng yang lebih lama; Saya menggunakan pengujian Debian yang memiliki versi yang lebih baru yang tidak lagi tampaknya memiliki sama /etc/mtabperilaku, yang mungkin mengapa @rozcietrzewiacz tidak melihat binddi dalam /etc/mtabjika distribusi nya juga menggunakan versi yang lebih baru?
aculich
1
@aculich Anda harus memposting findmntsebagai jawaban. Ngomong-ngomong, direktori target bukan titik mount yang lain. Coba misalnyasudo mount --bind / foo && findmnt | grep foo
l0b0
21

Mungkin ini bisa melakukan trik:

findmnt | grep  "\["

Contoh:

$ mkdir /tmp/foo
$ sudo mount --bind /media/ /tmp/foo
$ findmnt | grep  "\["
│ └─/tmp/foo                     /dev/sda2[/media] ext4            rw,relatime,data=ordered
olopopo
sumber
1
Rupanya, ini hanya berfungsi ketika subdirektori dari mountpoint di-mount. Jika /itu sendiri diikat bind, misalnya, output tidak memiliki [...].
muru
8

Kernel tidak menangani mount bind berbeda dari mount normal setelah fakta. Satu-satunya perbedaan dalam apa yang terjadi saat mountberjalan.

Ketika Anda memasang sistem file (mis. Dengan mount -t ext4 /dev/sda1 /mnt) kernel (sedikit disederhanakan) melakukan tiga langkah:

  1. Kernel mencari driver sistem file untuk tipe sistem file yang ditentukan (jika Anda menghilangkan -tatau menggunakan -t auto mounttipe tebakan untuk Anda dan memberikan tipe tebakan ke kernel)
  2. Kernel menginstruksikan driver filesystem untuk mengakses filesystem menggunakan jalur sumber dan opsi yang disediakan. Pada titik ini, sistem file hanya diidentifikasi oleh pasangan nomor mayor: minor.
  3. Sistem file terikat ke jalur (titik mount). Kernel juga menggunakan beberapa opsi mount di sini. ( nodevcontohnya adalah opsi pada mountpoint, bukan pada filesystem. Anda dapat memiliki bind mount dengan nodevdan tanpa itu)

Jika Anda melakukan bind mount (mis. Dengan mount --bind /a /b) hal berikut ini terjadi:

  1. Kernel menyelesaikan sistem file mana yang berisi jalur sumber dan jalur relatif dari mountpoint ke direktori.
  2. Sistem file terikat ke mountpoint baru menggunakan opsi dan jalur relatif.

(Saya akan lewati mount --move, karena tidak relevan dengan pertanyaan.)

Ini mirip dengan bagaimana file dibuat di Linux:

  1. Kernel menyelesaikan sistem file mana yang bertanggung jawab untuk direktori di mana file harus dibuat.
  2. File baru di sistem file dibuat. Pada titik ini file hanya memiliki nomor inode.
  3. File baru ini ditautkan dengan nama file di direktori.

Jika Anda membuat tautan keras, hal berikut terjadi:

  1. Kernel menyelesaikan nomor inode dari file sumber.
  2. File ini ditautkan dengan nama file tujuan.

Seperti yang Anda lihat, file yang dibuat dan tautan keras tidak bisa dibedakan:

$ 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

Tetapi , karena Anda dapat mengidentifikasi semua hardlink ke file dengan membandingkan nomor inode, Anda dapat mengidentifikasi semua mount ke sistem file dengan membandingkan utama: jumlah mount yang kecil.

Anda dapat melakukan ini dengan findmnt -o TARGET,MAJ:MINatau dengan melihat langsung /proc/self/mountinfo( lihat dokumentasi kernel Linux untuk informasi lebih lanjut ).

Skrip Python berikut mencantumkan semua bind mounts. Ini mengasumsikan bahwa titik pemasangan tertua dengan jalur relatif terpendek ke akar sistem file yang dipasang adalah pemasangan asli.

#!/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))
cg909
sumber
0
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")
n3rdopolis
sumber
0

Ini mirip dengan jawaban findmnt lainnya, tetapi menghindari masalah pemformatan.

Untuk menampilkan semua submount:

findmnt --kernel -n --list | grep '\['

Untuk menampilkan semua submount sistem file tipe ext4:

findmnt --kernel -t ext4 -n --list | grep '\['

Untuk menampilkan semua mount kecuali submount:

findmnt --kernel -n --list | grep -v '\['

Untuk menampilkan semua mount sistem file tipe ext4 tidak termasuk submount:

findmnt --kernel -t ext4 -n --list | grep -v '\['

"-N" menghapus header dan "--list" menghapus baris dari format "tree".

Diuji pada regangan Debian.

sg23
sumber