แสดงรายการการเชื่อมต่อผูกเท่านั้น


24

แทนที่จะใช้mount | grepฉันต้องการใช้mount -l -t bindแต่ไม่ได้ผลและ-t noneแสดงการเมานต์ทั้งหมด

คำตอบ:


28

Bind mounts ไม่ใช่ประเภทของระบบไฟล์หรือพารามิเตอร์ของระบบไฟล์ที่เมาท์ เป็นพารามิเตอร์ของการดำเนินการเมานต์ เท่าที่ฉันทราบลำดับของคำสั่งต่อไปนี้จะนำไปสู่สถานะของระบบที่เหมือนกันโดยพื้นฐานเท่าที่เคอร์เนลเกี่ยวข้อง:

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

ดังนั้นวิธีเดียวที่จะจำสิ่งที่ม้าเป็นม้าผูกเป็นบันทึกของคำสั่งที่เหลืออยู่ในmount /etc/mtabการดำเนินการเชื่อมต่อเชื่อมถูกระบุโดยตัวเลือกการbindเมานท์(ซึ่งทำให้ประเภทระบบไฟล์ถูกละเว้น) แต่ไม่มีตัวเลือกให้แสดงเฉพาะระบบไฟล์ที่เมาท์พร้อมชุดชุดตัวเลือกเฉพาะ ดังนั้นคุณต้องทำการกรองของคุณเองmount

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

โปรดทราบว่าจะเป็นประโยชน์เฉพาะที่นี่ถ้ามันแฟ้มข้อความที่ดูแลโดย/etc/mtab mountบางดิสทริบิวชันตั้ง/etc/mtabเป็นลิงก์สัญลักษณ์/proc/mountsแทน /proc/mountsส่วนใหญ่เทียบเท่า/etc/mtabแต่มีความแตกต่างเล็กน้อยซึ่งหนึ่งในนั้นไม่ได้ติดตามการเชื่อมโยงการผูก

ข้อมูลหนึ่งชิ้นที่เก็บรักษาไว้โดยเคอร์เนล แต่ไม่แสดงใน/proc/mountsคือเมื่อจุดเมานต์แสดงเฉพาะส่วนของแผนผังไดเรกทอรีบนระบบไฟล์ที่เมาท์ ในทางปฏิบัติสิ่งนี้ส่วนใหญ่เกิดขึ้นกับการผูกติด:

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

ใน/proc/mountsรายการสำหรับ/mnt/oneและ/mnt/partialมีอุปกรณ์เดียวกันประเภทระบบไฟล์เดียวกันและตัวเลือกเดียวกัน ข้อมูลที่/mnt/partialแสดงเฉพาะส่วนของระบบไฟล์ที่/subถูกรูทที่สามารถมองเห็นได้ในข้อมูลจุดต่อกระบวนการใน/proc/$pid/mountinfo(คอลัมน์ 4) รายการที่มีลักษณะเช่นนี้:

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

1
@Gilles ที่จริงแล้วคุณสามารถทำเช่นนี้เพียงแค่ใช้findmnt | fgrep [เป็นอธิบายที่นี่
aculich

@Gilles อะไรmount --versionที่คุณใช้บันทึกว่าbindข้อมูลในการ/etc/mtab? ฉันกำลังใช้รุ่น 2.20.1 และฉันมองไปที่แหล่งที่มาใหม่ล่าสุดและในกรณีที่ค่าใดฉันจึงเห็นข้อมูลผูกบันทึกที่ใดก็ได้ที่จะช่วยให้คุณสามารถ grep bindสำหรับ ในทางกลับกันสิ่งที่ผมแนะนำในคำตอบของฉันไม่อยู่ในรายการความจริงผูกม้าที่สร้างขึ้นด้วย--bindเช่นเดียวกับการใช้ตัวเลือกbind
aculich

@aculich </etc/mtab awk …สอดคล้องกับ POSIX (ฉันลืมว่ารองรับใน Bourne หรือไม่) โปรดตรวจสอบข้อเท็จจริงของคุณ ฉันสามารถยืนยัน/etc/mtabได้ว่ามีbindตัวเลือกสำหรับระบบไฟล์ที่ติดตั้งmount --bind /source /targetบนเดเบียนเสถียร (mount จาก util-linux-ng 2.17.2)
Gilles 'หยุดความชั่วร้าย'

@Gilles ฉันได้ลบความคิดเห็นที่ทำไปเพื่อลบความสับสน คุณพูดถูกมันเป็นไปตาม POSIX แน่นอน นอกจากนี้ตอนนี้ผมเข้าใจเหตุผลที่เราจะเห็นพฤติกรรมที่แตกต่างกันของและmount /etc/mtabคุณใช้ Debian เสถียรซึ่งมี util-linux-ng เวอร์ชั่นเก่ากว่า; ฉันกำลังใช้การทดสอบ Debian ซึ่งมีรุ่นใหม่ที่ไม่น่าจะมีเดียวกัน/etc/mtabพฤติกรรมซึ่งอาจจะเป็นเหตุผลที่ @rozcietrzewiacz ไม่เห็นbindในใน/etc/mtabถ้าการกระจายของเขายังใช้รุ่นที่ใหม่กว่า?
aculich

1
@aculich คุณควรโพสต์findmntเป็นคำตอบ ใช้ได้เฉพาะในกรณีที่ไดเรกทอรีเป้าหมายไม่ใช่จุดเชื่อมต่ออื่นเท่านั้น ลองตัวอย่างเช่นsudo mount --bind / foo && findmnt | grep foo
l0b0

21

บางทีนี่อาจเป็นการหลอกลวง:

findmnt | grep  "\["

ตัวอย่าง:

$ mkdir /tmp/foo
$ sudo mount --bind /media/ /tmp/foo
$ findmnt | grep  "\["
│ └─/tmp/foo                     /dev/sda2[/media] ext4            rw,relatime,data=ordered

1
เห็นได้ชัดว่าจะใช้งานได้เฉพาะเมื่อไดเรกทอรีย่อยของเมานต์ถูกผูกติด ถ้าตัวเองจะถูกผูกติดตัวอย่างเช่นการส่งออกไม่ได้/ [...]
muru

8

เคอร์เนลไม่ได้จัดการกับการผูกติดที่แตกต่างจากการติดตั้งปกติหลังจากข้อเท็จจริง ความแตกต่างเพียงอย่างเดียวในสิ่งที่เกิดขึ้นขณะmountทำงาน

เมื่อคุณเมานต์ระบบไฟล์ (เช่นกับmount -t ext4 /dev/sda1 /mnt) เคอร์เนล (บิตที่เรียบง่าย) ดำเนินการสามขั้นตอน:

  1. เคอร์เนลค้นหาไดรเวอร์ระบบไฟล์สำหรับประเภทระบบไฟล์ที่ระบุ (หากคุณไม่-tใช้งานหรือใช้การ-t auto mountเดาประเภทให้คุณและจัดเตรียมประเภทที่ถูกเดาให้กับเคอร์เนล)
  2. เคอร์เนลสั่งให้ไดร์เวอร์ระบบไฟล์เข้าถึงระบบไฟล์โดยใช้พา ธ ต้นทางและตัวเลือกที่มีให้ ณ จุดนี้ระบบไฟล์จะถูกระบุโดยคู่หลัก: คู่เลขรอง
  3. ระบบไฟล์ถูกผูกไว้กับพา ธ (จุดเมานท์) เคอร์เนลยังใช้ตัวเลือกการเมานท์ที่นี่ ( nodevตัวอย่างเช่นเป็นตัวเลือกใน mountpoint ไม่ใช่ในระบบไฟล์คุณสามารถมีการเชื่อมโยงกับnodevและหนึ่งโดยไม่)

หากคุณติดตั้งการเชื่อม (เช่นกับmount --bind /a /b) สิ่งต่อไปนี้จะเกิดขึ้น:

  1. เคอร์เนลแก้ไขระบบไฟล์ที่มีพา ธ ต้นทางและพา ธ สัมพัทธ์จากจุดเมานต์ไปยังไดเร็กทอรี
  2. ระบบไฟล์ถูกผูกไว้กับจุดต่อใหม่โดยใช้ตัวเลือกและเส้นทางสัมพัทธ์

(ฉันจะข้ามmount --moveเพราะไม่เกี่ยวข้องกับคำถาม)

สิ่งนี้ค่อนข้างคล้ายกับวิธีสร้างไฟล์บน Linux:

  1. เคอร์เนลจะแก้ไขระบบไฟล์ที่รับผิดชอบไดเรกทอรีที่ควรสร้างไฟล์
  2. ไฟล์ใหม่ในระบบไฟล์ถูกสร้างขึ้น ณ จุดนี้ไฟล์จะมีหมายเลขไอโหนดเท่านั้น
  3. ไฟล์ใหม่เชื่อมโยงกับชื่อไฟล์ในไดเรกทอรี

หากคุณทำการเชื่อมโยงอย่างหนักต่อไปนี้จะเกิดขึ้น:

  1. เคอร์เนลจะแก้ไขหมายเลขไอโหนดของไฟล์ต้นฉบับ
  2. ไฟล์นี้เชื่อมโยงกับชื่อไฟล์ปลายทาง

อย่างที่คุณเห็นไฟล์ที่สร้างและฮาร์ดลิงก์นั้นแยกไม่ออก

$ 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

แต่เนื่องจากคุณสามารถระบุฮาร์ดลิงก์ทั้งหมดไปยังไฟล์โดยการเปรียบเทียบหมายเลข inode คุณสามารถระบุการเมาต์ทั้งหมดกับระบบไฟล์โดยการเปรียบเทียบส่วนสำคัญ: เมานต์หลัก

คุณสามารถทำได้ด้วยfindmnt -o TARGET,MAJ:MINหรือโดยการดูโดยตรง/proc/self/mountinfo( ดูเอกสารประกอบเคอร์เนล Linux สำหรับข้อมูลเพิ่มเติม )

สคริปต์ Python ต่อไปนี้แสดงรายการการเชื่อมโยงทั้งหมด จะถือว่าจุดเมานต์ที่เก่าที่สุดที่มีพา ธ สัมพัทธ์สั้นที่สุดไปยังรูทของระบบไฟล์ที่เมาท์คือเมานต์ดั้งเดิม

#!/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))

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")

0

นี้คล้ายกับคำตอบ findmnt อื่น ๆ แต่หลีกเลี่ยงปัญหาการจัดรูปแบบ

วิธีแสดงจำนวนเงินทั้งหมด:

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

ในการแสดงจำนวนระบบไฟล์ทั้งหมดของประเภท ext4:

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

ในการแสดงการเมานท์ทั้งหมดยกเว้นการส่ง:

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

หากต้องการแสดงการเมานต์ของระบบไฟล์ทั้งหมดของประเภท ext4 ยกเว้นการส่งต่อ:

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

"-n" จะลบส่วนหัวและ "- รายการ" จะลบบรรทัดของรูปแบบ "ต้นไม้"

ทดสอบกับเดเบียนยืด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.