วิธีที่ดีที่สุดในการตรวจสอบว่าติดตั้งไดรฟ์ข้อมูลในสคริปต์ Bash อย่างไร


103

วิธีที่ดีที่สุดในการตรวจสอบว่าติดตั้งไดรฟ์ข้อมูลในสคริปต์ Bash อย่างไร

สิ่งที่ฉันชอบจริงๆคือวิธีการที่ฉันสามารถใช้สิ่งนี้:

if <something is mounted at /mnt/foo> 
then
   <Do some stuff>
else
   <Do some different stuff>
fi

ฉันเพิ่งจะเขียนสคริปต์เพื่อทำสิ่งนี้เอง ความคิดแรกของฉันคือการดึงข้อมูลออกมาจาก / etc / mtab แต่ฉันไม่ได้นิ้วหัวแม่มืออ่านหนังสือทุบตีของฉันเพื่อดูว่ามีวิธีที่ตรงกว่านี้ไหม
3dinfluence

@ 3dinfluence - ใช่ฉันรู้นี้จากเวลานานที่ผ่านมา แต่/etc/mtab, จะเชื่อมโยงกับ/proc/mounts (อย่างน้อยในวันที่ 20 ของ Fedora)/proc/self/mounts
วิลฟ์

คำถามที่คล้ายกันอยู่บนเซิร์ฟเวอร์ Fault , Stack มากเกินและUnix และ Linux Stack แลกเปลี่ยน
Sasha

คำตอบ:


113

หลีกเลี่ยงการใช้/etc/mtabเพราะอาจไม่สอดคล้องกัน

หลีกเลี่ยงการวางท่อmountเพราะมันไม่จำเป็นต้องซับซ้อนขนาดนั้น

เพียง:

if grep -qs '/mnt/foo ' /proc/mounts; then
    echo "It's mounted."
else
    echo "It's not mounted."
fi

(ช่องว่างหลัง/mnt/fooคือเพื่อหลีกเลี่ยงการจับคู่เช่น/mnt/foo-bar.)


7
ไม่ต้องพูดถึงการโทรเพื่อเมาท์สามารถวางได้หากเมานต์ถูกจด
Chad Huneycutt

8
เหมาะสำหรับ linux ไม่ใช่สำหรับ freebsd หรือ solaris
chris

4
นี่คือความจริงคริส แม้ว่าคำถามถูกติดแท็กลินุกซ์
Dan Carley

3
ฉันเดาว่านี่เป็นคำถามเชิงปรัชญา - เราควรพยายามทำให้พกพาสะดวกถ้าเป็นไปได้หรือเราควรจะสมมติว่า windows / linux ที่ทำงานอยู่ทั่วโลก
chris

18
ที่จริงแล้วคุณควรทดสอบ '/ mnt / foo' เช่น ด้วยช่องว่างหรือคุณอาจได้รับผลบวกปลอมหากคุณติดตั้งวอลลุ่มชื่อเช่น 'fooks' ฉันเพิ่งได้รับปัญหานั้นด้วยจุดยึดสองจุด 'lmde' และ 'lmde-home'
marlar

58
if mountpoint -q /mnt/foo 
then
   echo "mounted"
else
   echo "not mounted"
fi

หรือ

mountpoint -q /mnt/foo && echo "mounted" || echo "not mounted"

4
สำหรับข้อมูลเท่านั้น: mountpointมาในแพ็คเกจ "initscripts" ใน Ubuntu / Debian
blueyed

1
ใช้งานไม่ได้สำหรับฉัน - :-(
วิลฟ์

นี่คือการโทรที่คนจรจัดของฉันค้างไว้
dhill

ปัญหาmountpointคือว่ามันจะตรวจสอบในความเป็นจริงหากมีการติดตั้งจุดเชื่อมต่อ แต่ไม่ได้หากอุปกรณ์ที่ติดตั้ง หากอุปกรณ์ถูกส่งผ่านพร้อมกับ-xตัวเลือกอุปกรณ์จะบอกหมายเลขอุปกรณ์หลัก / รอง แต่ไม่ได้ติดตั้งไว้
vegatripy

@blueyed ใน Debian Buster จัดทำโดยแพ็คเกจutil-linux
elboulangero

18

findmnt -rno SOURCE,TARGET "$1"หลีกเลี่ยงปัญหาทั้งหมดในคำตอบอื่น ๆ มันทำงานอย่างหมดจดด้วยคำสั่งเดียว


วิธีการอื่นมีข้อเสียเหล่านี้:

  • grep -qและgrep -sเป็นขั้นตอนที่ไม่จำเป็นเป็นพิเศษและไม่ได้รับการสนับสนุนทุกที่
  • /proc/\* ไม่รองรับทุกที่
  • mountinfo ขึ้นอยู่กับ / proc / ..
  • cut -f3 -d' ' เลอะช่องว่างในชื่อเส้นทาง
  • การแยกพื้นที่สีขาวของเมานต์เป็นปัญหา มันเป็นหน้าคนตอนนี้พูดว่า:

.. โหมดการแสดงรายการได้รับการปรับปรุงเพื่อความเข้ากันได้ย้อนหลังเท่านั้น

เพื่อให้ได้ผลลัพธ์ที่แข็งแกร่งและปรับแต่งได้ให้ใช้findmnt (8) โดยเฉพาะในสคริปต์ของคุณ


ฟังก์ชั่นทุบตี:

#These functions return exit codes: 0 = found, 1 = not found

isMounted    () { findmnt -rno SOURCE,TARGET "$1" >/dev/null;} #path or device
isDevMounted () { findmnt -rno SOURCE        "$1" >/dev/null;} #device only
isPathMounted() { findmnt -rno        TARGET "$1" >/dev/null;} #path   only

#where: -r = --raw, -n = --noheadings, -o = --output

ตัวอย่างการใช้งาน:

if isPathMounted "/mnt/foo bar";      #Spaces in path names are ok.
   then echo "path is mounted"
   else echo "path is not mounted"
fi

if isDevMounted "/dev/sdb4"; 
   then echo "device is mounted"
   else echo "device is not mounted"
fi

#Universal:
if isMounted "/mnt/foo bar"; 
   then echo "device is mounted"
   else echo "device is not mounted"
fi

if isMounted "/dev/sdb4";
   then echo "device is mounted"
   else echo "device is not mounted"
fi

1
สำหรับ Linux โดยเฉพาะนี่เป็นวิธีที่ดีที่สุด ฉันเห็นfindmnt(8)คำสั่งแล้ว แต่ไม่เคยเล่นด้วย ตรงไปตรงมาถ้าฉันต้องอัปเดตสคริปต์บางอย่างที่ทำสิ่งนี้ (หรือสร้างสคริปต์ใหม่) บนกล่อง Linux (หรือที่มีคำสั่งอยู่) นี่คือสิ่งที่ฉันต้องการ
Pryftan

1
โปรดทราบว่าสำหรับการเข้ารหัสfindmntจะต้องมาพร้อมกับพารามิเตอร์--source encfsมิฉะนั้นจะพิจารณาไดเรกทอรีที่จะติดตั้งเพราะมันกลับไปที่แม่เมานต์
Burkart

นอกจากนี้ยังจะดีกว่าgrepการแก้ปัญหาเพราะถ้าเป็นเส้นทางภูเขาเป็นลางคุณจะได้รับผลบวกปลอม: เช่นถ้าผมติด/dev/mmcblk0p1อยู่กับ~/mnt/dev/sda1ผมได้สิ่งที่ไม่ถูกต้องที่จะติดตั้งโดยคำสั่ง/dev/sda1 mount | grep '/dev/sda1'ฉันไม่สามารถใช้การบวกเชิงลบfindmntได้ คำตอบที่ดี!
Cody Piersall

7

สคริปต์เช่นนี้ไม่สามารถพกพาไปไหนได้เลย ความลับสกปรกในยูนิกซ์คือเคอร์เนลเท่านั้นที่รู้ว่าระบบไฟล์อยู่ที่ไหนและขาดสิ่งต่าง ๆ เช่น / proc (ไม่ใช่พกพา) มันจะไม่มีคำตอบให้คุณเลย

ฉันมักจะใช้ df เพื่อค้นหาว่าจุดเมานท์ของไดเรกทอรีย่อยคืออะไรและระบบไฟล์นั้นเป็นอะไร

ตัวอย่าง (ต้องใช้เชลล์ posix เช่น ash / AT&T ksh / bash / ฯลฯ )

case $(df  $mount)
in
  $(df  /)) echo $mount is not mounted ;;
  *) echo $mount has a non-root filesystem mounted on it ;;
esac

คินดาบอกข้อมูลที่เป็นประโยชน์กับคุณ


1
คำถามคือแท็กลินุกซ์ดังนั้นบางทีมันไม่ได้มีที่จะพกพา
Rory

6

ต่อไปนี้คือสิ่งที่ฉันใช้ในหนึ่งในงานสำรองข้อมูล rsync cron-jobs มันจะตรวจสอบเพื่อดูว่ามีการติดตั้ง / backup หรือไม่และพยายามติดตั้งหากไม่ได้ (อาจล้มเหลวเนื่องจากไดรฟ์อยู่ในช่องเสียบ hot-swap และอาจไม่มีอยู่ในระบบ)

หมายเหตุ: ข้อมูลต่อไปนี้ใช้งานได้บน linux เท่านั้นเนื่องจากมัน greps / proc / mounts - เวอร์ชั่นพกพาจะเรียกใช้ 'mount | grep / backup 'เช่นเดียวกับในคำตอบของ Matthew

  ถ้า! grep -q / backup / proc / mounts; แล้วก็
    ถ้า! เมานต์ / สำรอง แล้วก็
      เสียงสะท้อน "ล้มเหลว"
      ทางออก 1
    Fi
  Fi
  echo "suceeded."
  # ทำสิ่งต่างๆที่นี่

2
โหวตขึ้นเป็นทางเลือกการตรวจสุขภาพที่ดี
Dan Carley

วิธีนี้น่าจะเป็นปัญหาเดียวกับคำตอบของ Matthew Bloch
mwfearnley

ใช่ยกเว้นปัญหาช่องว่างในชื่อไฟล์ที่กล่าวถึงโดย "มุมมอง Eliptical" (สิ่งนี้ทำให้ทั้งบรรทัดไม่ใช่แค่เพียงฟิลด์ที่แยกออกมา) ปัญหาย่อยสตริงไม่ใช่เรื่องใหญ่เว้นแต่คุณจะลืมว่าข้อโต้แย้งการอ้างถึงเป็นสิ่งที่คุณสามารถทำได้ เช่นหรือgrep -q ' /backup ' /proc/mounts mount | grep -q ' /backup 'หรือเปลี่ยนเส้นทางไปที่ / dev / null หาก grep ของคุณไม่รองรับ-q(ซึ่งอยู่ในข้อมูลจำเพาะ POSIX สำหรับ grep วันนี้)
cas

2

เนื่องจากเพื่อที่จะเมานต์คุณต้องมีไดเร็กตอรี่อยู่ที่นั่น, ที่เมาท์, กลยุทธ์ของฉันคือการสร้างไฟล์ปลอมด้วยชื่อไฟล์แปลก ๆ ที่ไม่เคยใช้, และตรวจสอบว่ามันมีอยู่จริง. หากไฟล์อยู่ที่นั่นแสดงว่าไม่มีสิ่งใดติดตั้งในจุดนั้น ...

ฉันไม่คิดว่ามันจะใช้งานได้กับการติดตั้งไดรฟ์เครือข่ายหรืออะไรทำนองนั้น ฉันใช้มันสำหรับแฟลชไดรฟ์


2

วิธีเปรียบเทียบหมายเลขอุปกรณ์ ฉันแค่พยายามคิดวิธีที่ลึกลับที่สุด..

#!/bin/bash
if [[ $(stat -c "%d" /mnt) -ne $(stat -c "%d" /mnt/foo) ]]; then
    echo "Somethin mounted there I reckon"
fi

ตรรกะของฉันมีข้อบกพร่องในเรื่องนั้น ...

ในฐานะที่เป็นฟังก์ชั่น:

#!/usr/bin/bash
function somethingMounted {
        mountpoint="$1"
        if ! device1=$(stat -c "%d" $mountpoint); then
                echo "Error on stat of mount point, maybe file doesn't exist?" 1>&2
                return 1
        fi
        if ! device2=$(stat -c "%d" $mountpoint/..); then
                echo "Error on stat one level up from mount point, maybe file doesn't exist?" 1>&2
                return 1
        fi

        if [[ $device1 -ne $device2 ]]; then
                #echo "Somethin mounted there I reckon"
                return 0
        else
                #echo "Nothin mounted it seems"
                return 1
        fi
}

if somethingMounted /tmp; then
        echo "Yup"
fi

ข้อความแสดงข้อผิดพลาด echo อาจซ้ำซ้อนเนื่องจาก stat จะแสดงข้อผิดพลาดเช่นกัน


ที่จริงแล้วอาจจะต้องตรวจสอบสถานะทางออกของ stat ก่อนสำหรับการโทรแต่ละครั้งเพื่อให้แน่ใจว่าไฟล์อยู่ที่นั่น ... ไม่แปลกอย่างที่ฉันคิด :-(
Kyle Brandt

1

สิ่งเหล่านี้ไม่เป็นไปตามกรณีการใช้งานซึ่งไดเรกทอรีที่กำหนดเป็นไดเรกทอรีย่อยภายในจุดเชื่อมต่ออื่น ตัวอย่างเช่นคุณอาจมี / สิ่งซึ่งเมาท์ NFS ไปยังโฮสต์: / real_thing การใช้ grep เพื่อจุดประสงค์นี้ใน / proc / mounts / etc / mtab หรือ 'mount' จะไม่ทำงานเพราะคุณจะมองหาจุดเมานต์ที่ไม่มีอยู่ ตัวอย่างเช่น / Things / thingy ไม่ใช่จุดเชื่อมต่อ แต่ / Things ถูกเมาท์บนโฮสต์: / real_thing คำตอบที่ดีที่สุดที่ลงคะแนนไว้ที่นี่ไม่ใช่ "วิธีที่ดีที่สุดในการตรวจสอบว่ามีการติดตั้งไดเรกทอรี / volumne" หรือไม่ ฉันต้องการให้คะแนนโดยใช้ 'df -P' (โหมดมาตรฐาน -P POSIX) เป็นกลยุทธ์ที่สะอาดกว่า:

dev=`df -P /thing/thingy | awk 'BEGIN {e=1} $NF ~ /^\/.+/ { e=0 ; print $1 ; exit } END { exit e }'` && {
    echo "Mounted via: $dev"
} || {
    echo "Not mounted"
}

ผลลัพธ์จากการรันสิ่งนี้จะเป็น:

Mounted via: host:/real_thing

หากคุณต้องการทราบว่าจุดเชื่อมต่อจริงคืออะไรไม่มีปัญหา:

mp=`df -P /thing/thingy | awk 'BEGIN {e=1} $NF ~ /^\/.+/ { e=0 ; print $NF ; exit } END { exit e }'` && {
    echo "Mounted on: $mp"
} || {
    echo "Not mounted"
}

ผลลัพธ์จากคำสั่งนั้นจะเป็น:

Mounted on: /thing

ทั้งหมดนี้มีประโยชน์มากหากคุณพยายามสร้าง chroot บางชนิดที่ทำหน้าที่เป็นจุดเชื่อมต่อภายนอก chroot ภายใน chroot ผ่านทางไดเรกทอรีหรือรายการไฟล์โดยพลการ


1

ขออภัยที่นำสิ่งนี้มา แต่ฉันคิดว่านี่ค่อนข้างมีประโยชน์:

if awk '{print $2}' /proc/mounts | grep -qs "^/backup$"; then
    echo "It's mounted."
else
    echo "It's not mounted."
fi

นี่คือคอลัมน์ที่ 2 ของ / proc / mounts (คอลัมน์ที่ 2 = จุดเมานท์)

จากนั้นก็ greps เอาท์พุท หมายเหตุ ^ และ $ สิ่งนี้จะป้องกัน / สำรองจากการจับคู่ / mnt / backup หรือ / backup-old เป็นต้น


0

grep / etc / mtab สำหรับจุดเมานท์ของคุณอาจจะ?


1
mtab อาจล้าสมัยหรือไม่ได้รับการอัพเดตโดย mount เช่นเมื่อคุณใช้ mount -n เพราะ / เป็นแบบอ่านอย่างเดียว
chris

ฉันเห็นด้วย แต่นั่นดูเหมือนเป็นสถานที่แรกที่เริ่มมอง
Ophidian


0

แม้ว่านี่เป็นคำถาม Linux ทำไมไม่ทำให้พกพาเมื่อทำได้ง่าย?

หน้าคู่มือของgrepsays:

สคริปต์เชลล์แบบพกพาควรหลีกเลี่ยงทั้ง -q และ -s และควรเปลี่ยนทิศทางเอาต์พุตมาตรฐานและข้อผิดพลาดไปที่/dev/nullแทน

ดังนั้นฉันจึงเสนอวิธีแก้ปัญหาต่อไปนี้:

if grep /mnt/foo /proc/mounts > /dev/null 2>&1; then
        echo "Mounted"
else
        echo "NOT mounted"
fi

3
ระบบ UNIX หลายระบบไม่มีระบบไฟล์ / proc
Dmitri Chubarov

@DmitriChubarov แน่นอน ซึ่งทำให้แนวคิดเรื่องการพกพาแดกดันไม่ได้หรือไม่ และบางทีมันอาจจะมีการปรับปรุงเมื่อเร็ว ๆ นี้ แต่-qและ-sถูกกำหนดโดย POSIX จึงไม่ควรมีปัญหาใด ๆ ในการพกพาด้วยนั่นเองล่ะค่ะ (ตอนนี้หากไม่ได้มาก่อน - ฉันไม่ได้เฝ้าติดตามสิ่งที่เปลี่ยนแปลงที่เกิดขึ้นเมื่อ)
Pryftan

0

มันจำเป็นต้องมีอะไรซับซ้อนกว่านี้อีกไหม?

mount \
    | cut -f 3 -d ' ' \
    | grep -q /mnt/foo \
  && echo "mounted" || echo "not mounted"

1
grep -q /mnt/fooจะจับคู่จุดเชื่อมต่อ/mnt/foodกับ/not/mnt/foo... และจะเป็นgrep -qx /mnt/fooอย่างไร
rakslice

@rakslice: มันไม่ทำงาน -xทำให้ grep ตรงกันก็ต่อเมื่อทั้งสายตรงกัน
mivk

1
cut -f 3 -d ' 'สะดุดเมื่อเส้นทางภูเขามีที่ว่างในชื่อไฟล์
มุมมองรูปไข่

0

ขึ้นอยู่กับสิ่งที่คุณรู้เกี่ยวกับปริมาณที่คุณกำลังตรวจสอบ

ในกรณีเฉพาะที่ฉันวิจัยเมื่อเร็ว ๆ นี้ที่ฉันกังวลว่าจะหาแฟลชไดรฟ์ที่ติดตั้งสิ่งที่ทำงานได้ง่ายที่สุดคือการตรวจสอบการมีอยู่ของ / dev / ดิสก์ / by-label / หากเสียบปลั๊กอุปกรณ์สคริปต์ udev จะตรวจสอบให้แน่ใจว่ามีลิงก์อยู่ (และจะถูกลบออกเมื่อไม่ได้เสียบปลั๊กอุปกรณ์)

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


0

สร้างไฟล์ภายใต้ mountpoint ของคุณเช่นcheck_mountนั้นและทดสอบว่ามีอยู่หรือไม่

if [[ -f /something/check_mount ]]; then
   echo "Mounted
   RC=$?
else
   Echo "Not mounted"
   RC=0
fi
exit $RC

-1

ฉันต้องทำสิ่งนี้ใน Chef เพื่อ idempotence ตั้งแต่เมื่อพ่อครัว - ลูกค้าจะทำงานการรันจะล้มเหลวเนื่องจากไดรฟ์ข้อมูลติดตั้งอยู่แล้ว ในขณะที่ฉันเขียนสิ่งนี้mountทรัพยากรChef มีข้อผิดพลาดบางอย่างซึ่งไม่สามารถทำงานกับคุณลักษณะที่ฉันต้องการได้ดังนั้นฉันจึงติดตั้งไดรฟ์ข้อมูลโดยใช้executeทรัพยากรแทน นี่คือวิธีที่ฉันทำ:

if not node['docker-server']['mountpoint'] == "none"
  execute "set up mount" do
    user "root"
    command "mount -t ext4 #{node['docker-server']['mountpoint']} #{node['docker-server']['data-dir']}"
    not_if "grep -qs #{node['docker-server']['data-dir']} /proc/mounts"
  end
end

ในกรณีที่มีความสับสนในไฟล์คุณลักษณะของฉันฉันมีดังต่อไปนี้:

default['docker-server']['mountpoint'] = "/dev/vdc"
default['docker-server']['data-dir'] = "/data"

if not node['docker-server']['mountpoint'] == "none"เป็นส่วนหนึ่งของเป็นคำสั่งที่ถ้าจุดเชื่อมต่อบนเซิร์ฟเวอร์ไม่ได้ระบุภูเขาค่าเริ่มต้นชี้ไปที่casenone


... และสิ่งนี้เกี่ยวข้องกับคำถามเดิมหรือไม่?
Massimo

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

คำถามเกี่ยวกับสคริปต์ทุบตีคำตอบของคุณเกี่ยวกับการเขียนสคริปต์เชฟ แม้ว่ามันอาจจะมีประโยชน์กับใครบางคน แต่ก็ยังไม่มีความเกี่ยวข้องกับคำถาม
Massimo

@KLaw 'ดังนั้นแทนที่จะทำเครื่องหมายโพสต์ของฉันให้ยอมรับว่ามันคืออะไร: ข้อมูลเพิ่มเติมที่รองรับคำตอบที่ยอมรับ' ฉันเห็นด้วยและฉันไม่ได้เป็นหนึ่งในการลงคะแนนเสียง (และฉันก็ไม่ได้อยู่ที่นี่ด้วย) แต่ถ้าคุณมีปัญหากับสิ่งประเภทนั้นคุณควรจะเพิ่มมันเป็นส่วนเสริมของประเด็นอื่น ๆ ของคุณ? อาจบันทึกความคิดเห็นอื่น ๆ แต่สำหรับระบบอัตโนมัตินั้นเป็นสิ่งที่สคริปต์ทุบตีอนุญาตดังนั้นฉันจึงไม่เห็นจุดของคุณ แน่นอนว่าโปรแกรมเมอร์ในตัวฉันคิดว่าสคริปต์ด้านบนเป็นเรื่องน่ารังเกียจ แต่นั่นเป็นปัญหาทางภาษามากกว่าสิ่งอื่นใด ...
Pryftan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.