Apa cara terbaik untuk memeriksa apakah volume sudah dipasang di skrip Bash?

103

Apa cara terbaik untuk memeriksa apakah volume sudah dipasang di skrip Bash?

Apa yang benar-benar saya sukai adalah metode yang dapat saya gunakan seperti ini:

if <something is mounted at /mnt/foo> 
then
   <Do some stuff>
else
   <Do some different stuff>
fi
Mark Biek
sumber
Saya baru saja akan menulis naskah untuk melakukan ini sendiri. Pikiran pertama saya adalah untuk mendapatkan info dari / etc / mtab Tapi saya belum membaca buku bash saya untuk melihat apakah ada cara yang lebih langsung.
3dinfluence
@ 3dinfluence - ya saya tahu ini sejak dulu, tapi /etc/mtab, /proc/mountsterkait dengan /proc/self/mounts. (minimal pada Fedora 20 itu)
Wilf
Pertanyaan serupa ada di Server Fault , Stack Overflow dan Unix & Linux Stack Exchange .
Sasha

Jawaban:

113

Hindari penggunaan /etc/mtabkarena mungkin tidak konsisten.

Hindari perpipaan mountkarena tidak perlu yang rumit.

Secara sederhana:

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

(Ruang setelah /mnt/fooadalah untuk menghindari pencocokan misalnya /mnt/foo-bar.)

Dan Carley
sumber
7
Belum lagi, panggilan untuk memasang bisa hang jika titik mount terjepit.
Chad Huneycutt
8
Baik untuk linux, bukan untuk freebsd atau solaris.
chris
4
Ini benar, chris. Meskipun pertanyaan itu ditandai linux.
Dan Carley
3
Saya kira ini adalah pertanyaan filosofis - haruskah kita mencoba membuat hal-hal portabel jika mungkin atau kita hanya berasumsi bahwa semua dunia menjalankan windows / linux dan bertindak sesuai?
chris
18
Sebenarnya, Anda harus menguji untuk '/ mnt / foo', yaitu. dengan spasi atau Anda mungkin mendapatkan false positif jika Anda telah memasang volume bernama eg. 'orang bodoh'. Saya baru saja mendapat masalah dengan dua mount point, 'lmde' dan 'lmde-home'.
marlar
58
if mountpoint -q /mnt/foo 
then
   echo "mounted"
else
   echo "not mounted"
fi

atau

mountpoint -q /mnt/foo && echo "mounted" || echo "not mounted"
Zaptac
sumber
4
Sekadar informasi: mountpointberasal dari paket "skrip init" di Ubuntu / Debian.
blueyed
1
Tidak bekerja untuk saya - :-(
Wilf
Ini adalah panggilan, bahwa Vagrant saya digantung.
dhill
Masalahnya dengan mountpointitu memeriksa, pada kenyataannya, jika titik mount sudah terpasang, tetapi tidak jika perangkat sudah terpasang. Jika suatu perangkat disahkan dengan -xopsi itu memberitahu Anda nomor perangkat utama / minor, tetapi tidak jika itu dipasang.
vegatripy
@blueyed Di Debian Buster itu disediakan oleh paketutil-linux
elboulangero
18

findmnt -rno SOURCE,TARGET "$1"menghindari semua masalah dalam jawaban lainnya. Itu bersih melakukan pekerjaan hanya dengan satu perintah.


Pendekatan lain memiliki kelemahan ini:

  • grep -qdan grep -smerupakan langkah ekstra yang tidak perlu dan tidak didukung di mana-mana.
  • /proc/\* tidak didukung di mana-mana.
  • mountinfo didasarkan pada / proc / ..
  • cut -f3 -d' ' mengacaukan spasi dalam nama jalur
  • Parsing mount white space bermasalah. Halaman manualnya sekarang mengatakan:

.. mode listing dipertahankan hanya untuk kompatibilitas.

Untuk hasil yang lebih kuat dan dapat disesuaikan gunakan findmnt (8), terutama di skrip Anda.


Fungsi bash:

#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

Contoh penggunaan:

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
Pandangan elips
sumber
1
Khusus untuk Linux, ini benar-benar pendekatan terbaik. Saya telah melihat findmnt(8)perintah tetapi saya tidak pernah benar-benar bermain dengannya. Terus terang jika saya memperbarui beberapa skrip saya yang melakukan hal semacam ini (atau membuat yang baru) pada kotak Linux (atau di mana perintah tersedia) inilah yang akan saya lakukan.
Pryftan
1
Perhatikan bahwa untuk encf, findmntharus disertakan dengan parameter --source encfs, jika tidak akan selalu mempertimbangkan direktori untuk dipasang karena jatuh kembali ke mount induk.
Burkart
Ini juga lebih baik daripada grepsolusinya karena jika path mount aneh, Anda bisa mendapatkan false positive: misalnya jika saya mount /dev/mmcblk0p1on ~/mnt/dev/sda1, saya bisa salah melakukan hal yang di /dev/sda1-mount oleh perintah mount | grep '/dev/sda1'. Saya tidak bisa mendapatkan hasil positif palsu findmnt. Jawaban yang bagus!
Cody Piersall
7

Skrip seperti ini tidak akan portabel. Rahasia kotor di unix adalah bahwa hanya kernel yang tahu sistem file mana, dan kekurangan / proc (tidak portabel) itu tidak akan pernah memberi Anda jawaban langsung.

Saya biasanya menggunakan df untuk menemukan apa mount-point dari subdirektori, dan filesystem apa yang ada di dalamnya.

Misalnya (memerlukan shell posix seperti ash / AT&T ksh / bash / dll)

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

Agak memberitahu Anda informasi yang berguna.

chris
sumber
1
Pertanyaannya adalah ditandai linux, jadi mungkin itu tidak harus portabel
Rory
6

berikut ini adalah apa yang saya gunakan di salah satu cs-job backup rsync saya. ia memeriksa untuk melihat apakah / backup sudah di-mount, dan mencoba untuk memasangnya jika tidak (mungkin gagal karena drive berada dalam ruang hot-swap dan bahkan mungkin tidak ada dalam sistem)

CATATAN: yang berikut ini hanya berfungsi di linux, karena greps / proc / mounts - versi yang lebih portabel akan menjalankan 'mount | grep / backup ', seperti pada jawaban Matthew ..

  jika! grep -q / backup / proc / mounts; kemudian
    jika! mount / cadangan; kemudian
      gema "gagal"
      keluar 1
    fi
  fi
  gema "berhasil."
  lakukan di sini
cas
sumber
2
Terpilih sebagai alternatif pemeriksaan kewarasan yang baik.
Dan Carley
Agaknya metode ini mengalami masalah yang sama dengan jawaban Matthew Bloch.
mwfearnley
ya, kecuali untuk masalah space-in-filename yang disebutkan oleh "Eliptical view" (ini menangkap seluruh baris, bukan hanya bidang yang diekstraksi). Masalah sub-string bukanlah masalah besar kecuali Anda entah bagaimana lupa bahwa mengutip argumen adalah hal yang dapat Anda lakukan. misalnya grep -q ' /backup ' /proc/mountsatau mount | grep -q ' /backup '. Atau redirect ke / dev / null jika grep Anda tidak mendukung -q(yang ada dalam spesifikasi POSIX untuk grep hari ini).
cas
2

Karena untuk me-mount, Anda harus memiliki direktori di sana, yang akan dipasang, strategi saya adalah selalu membuat file palsu dengan nama file aneh yang tidak akan pernah digunakan, dan hanya memeriksa keberadaannya. Jika file itu ada di sana, maka tidak ada yang dipasang di tempat itu ...

Saya tidak berpikir ini berfungsi untuk memasang drive jaringan atau hal-hal seperti itu. Saya menggunakannya untuk flash drive.

Brian Postow
sumber
2

Bagaimana dengan membandingkan nomor perangkat? Saya hanya mencoba memikirkan cara yang paling esoteris ..

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

Ada cacat dalam logika saya dengan itu ...

Sebagai fungsi:

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

Pesan kesalahan gema mungkin berlebihan, karena stat akan menampilkan kesalahan juga.

Kyle Brandt
sumber
Sebenarnya, mungkin harus memeriksa status keluar dari stat terlebih dahulu untuk setiap panggilan untuk memastikan file ada di sana ... tidak novel seperti yang saya pikir :-(
Kyle Brandt
1

Tak satu pun dari ini memenuhi use case di mana direktori yang diberikan adalah sub direktori dalam mount point lain. Sebagai contoh, Anda mungkin memiliki / hal yang merupakan mount NFS untuk di-host: / real_thing. Menggunakan grep untuk tujuan ini di / proc / mounts / etc / mtab atau 'mount' tidak akan berfungsi, karena Anda akan mencari titik mount yang tidak ada. Sebagai contoh, / thing / thingy bukan mount point, tapi / thing di-mount pada host: / real_thing. Jawaban terbaik yang dipilih di sini sebenarnya BUKAN "cara terbaik untuk menentukan apakah direktori / volumne dipasang". Saya akan memilih menggunakan 'df -P' (-P mode standar POSIX) sebagai strategi yang lebih bersih:

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

Output dari menjalankan ini adalah:

Mounted via: host:/real_thing

Jika Anda ingin tahu apa sebenarnya mount point, tidak masalah:

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

Output dari perintah itu adalah:

Mounted on: /thing

Ini semua sangat berguna jika Anda mencoba membuat semacam chroot yang mencerminkan titik mount di luar chroot, di dalam chroot, melalui beberapa direktori atau daftar file yang sewenang-wenang.

Craig
sumber
1

Maaf karena mengemukakan ini tetapi saya pikir ini cukup berguna:

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

Ini mendapatkan kolom ke-2 dari / proc / mounts (kolom ke-2 = mount points).

Kemudian ia menangkap output. Catat ^ dan $, ini mencegah / backup dari pencocokan / mnt / backup atau / backup lama dll.

David
sumber
0

grep / etc / mtab untuk titik mount Anda mungkin?

Ophidian
sumber
1
mtab bisa menjadi usang atau tidak diperbarui oleh mount, seperti ketika Anda menggunakan mount -n karena / hanya-baca.
chris
Saya setuju, tapi itu sepertinya tempat pertama untuk mulai mencari.
Ophidian
0

Ini?:

volume="/media/storage"
if mount|grep $volume; then
echo "mounted"
else
echo "not mounted"
if

Dari: Forum Ubuntu

RateControl
sumber
0

Meskipun ini adalah pertanyaan Linux, mengapa tidak membuatnya portabel ketika mudah dilakukan?

Halaman manual grepmengatakan:

Skrip shell portabel harus menghindari -q dan -s dan harus mengarahkan standar dan output kesalahan /dev/nullsebagai gantinya.

Jadi saya mengusulkan solusi berikut:

if grep /mnt/foo /proc/mounts > /dev/null 2>&1; then
        echo "Mounted"
else
        echo "NOT mounted"
fi
fex
sumber
3
Banyak sistem UNIX tidak menyediakan sistem file / proc
Dmitri Chubarov
@DmitriChubarov Memang. Yang membuat konsep portabilitas ironis bukan? Dan mungkin itu update lebih baru tapi -qdan -sditentukan oleh POSIX sehingga tidak boleh ada masalah portabilitas dengan itu pula (jika tidak sebelum - aku sudah tidak terus melacak perubahan apa yang terjadi ketika).
Pryftan
0

Apakah perlu lebih rumit dari ini?

mount \
    | cut -f 3 -d ' ' \
    | grep -q /mnt/foo \
  && echo "mounted" || echo "not mounted"
Matthew Bloch
sumber
1
grep -q /mnt/foojuga akan cocok dengan poin pemasangan /mnt/fooddan /not/mnt/foo... Bagaimana grep -qx /mnt/foo?
rakslice
@ rakslice: itu tidak akan berhasil. -xmembuat pertandingan grep hanya jika seluruh baris cocok.
mivk
1
cut -f 3 -d ' 'tersandung ketika mount path memiliki spasi dalam nama file.
Tampilan elips
0

Tergantung apa yang Anda ketahui tentang volume yang Anda periksa.

Dalam kasus khusus yang saya teliti baru-baru ini, di mana saya prihatin untuk menemukan apakah flash drive tertentu dipasang, yang paling mudah adalah memeriksa keberadaan / dev / disk / oleh-label /. Jika perangkat dicolokkan, skrip udev pastikan tautannya ada (dan dihapus saat perangkat dicabut).

(Ini BUKAN jawaban yang sangat portabel; itu bekerja pada banyak distribusi Linux modern, dan pertanyaannya ditandai untuk Linux, dan ini merupakan pendekatan yang sangat berbeda dari apa pun yang disebutkan sejauh ini sehingga memperluas kemungkinan.)

David Dyer-Bennet
sumber
0

Buat file di bawah mountpoint Anda seperti check_mountdan kemudian coba apakah itu ada?

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

Saya harus melakukan ini di Chef untuk idempotensi karena ketika chef-client akan berjalan, run akan gagal karena volume yang sudah terpasang. Pada saat saya menulis ini, mountsumber daya Chef memiliki beberapa jenis bug yang tidak akan berfungsi dengan atribut seperti yang saya butuhkan, jadi saya memasang volume menggunakan executesumber daya sebagai gantinya. Begini cara saya melakukannya:

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

Dalam hal terjadi kebingungan, dalam file atribut saya, saya memiliki yang berikut:

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

Ini if not node['docker-server']['mountpoint'] == "none"adalah bagian dari casepernyataan di mana jika titik mount di server tidak ditentukan, titik mount default ke none.

KLaw
sumber
... dan apa hubungannya ini dengan pertanyaan aslinya?!?
Massimo
Hubungan dari resep resep Chef saya dengan pertanyaan awal adalah bahwa orang-orang semakin bergerak menuju otomatisasi. Karena itu, jika seseorang datang ke sini bertanya-tanya bagaimana cara membuat ini dalam resep Chef, mereka akan memiliki jawaban. Dalam hidup ada dua pilihan: 1) Lakukan seminimal mungkin dan buat sebagian orang bahagia, dan 2) Lakukan yang terbaik. Oleh karena itu, alih-alih menandai posting saya, terima apa adanya: informasi tambahan yang mendukung jawaban yang diterima.
KLaw
Pertanyaannya adalah tentang skrip bash, jawaban Anda adalah tentang skrip Chef. Meskipun mungkin bermanfaat bagi seseorang, tetap saja tidak ada relevansinya dengan pertanyaan.
Massimo
@KLaw 'Oleh karena itu, alih-alih menandai posting saya, terima apa adanya: informasi tambahan yang mendukung jawaban yang diterima.' Saya setuju dan saya bukan orang yang biasanya memilih turun (dan saya juga belum di sini), tetapi jika Anda memiliki masalah dengan hal semacam itu, Anda harus menambahkannya sebagai tambahan pada poin Anda yang lain? Bisa menyimpan komentar lainnya. Tetapi untuk otomatisasi itulah yang diizinkan oleh skrip bash, jadi saya gagal memahami maksud Anda. Tentu saja programmer di dalam saya berpikir bahwa skrip di atas adalah mengerikan tetapi itu masalah bahasa lebih dari apa pun ...
Pryftan