Qual è il modo migliore per verificare se un volume è montato in uno script Bash?


103

Qual è il modo migliore per verificare se un volume è montato in uno script Bash?

Quello che mi piacerebbe davvero è un metodo che posso usare in questo modo:

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

Stavo per scrivere una sceneggiatura per farlo da solo. Il mio primo pensiero è di ottenere informazioni da / etc / mtab ma non ho ancora sfogliato i miei libri bash per vedere se c'è un modo più diretto.
3dinfluence

@ 3dinfluence - sì, lo so questo da molto tempo fa, ma /etc/mtab, /proc/mountssono collegate a /proc/self/mounts. (almeno il 20 di Fedora)
Wilf,

Domande simili riguardano Server Fault , StackTranslate.it e Unix & Linux Stack Exchange .
Sasha,

Risposte:


113

Evitare l'uso /etc/mtabperché potrebbe essere incoerente.

Evita le tubazioni mountperché non deve essere così complicato.

Semplicemente:

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

(Lo spazio dopo il /mnt/fooè per evitare la corrispondenza ad es /mnt/foo-bar.)


7
Per non parlare, una chiamata da montare può bloccarsi se il mountpoint è incuneato.
Chad Huneycutt,

8
Buono per Linux, non per Freebsd o Solaris.
chris,

4
Questo è vero, Chris. Anche se la domanda è stata taggata linux.
Dan Carley,

3
Immagino che questa sia una domanda filosofica: dovremmo tentare di rendere le cose portatili se possibile o dovremmo semplicemente supporre che tutto il mondo esegua Windows / Linux e agire di conseguenza?
chris,

18
In realtà, dovresti testare "/ mnt / foo", cioè. con uno spazio o potresti ottenere un falso positivo se avessi montato un volume chiamato es. 'Fooks'. Ho appena avuto quel problema con due punti di montaggio, "lmde" e "lmde-home".
marlar,

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

o

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

4
Solo per informazione: ha mountpointorigine nel pacchetto "initscripts" in Ubuntu / Debian.
bluato il

1
Non ha funzionato per me - :-(
Wilf

Questa è la chiamata su cui pende il mio vagabondo.
discesa

Il problema mountpointè che controlla, infatti, se è montato un punto di montaggio, ma non se è montato un dispositivo. Se viene passato un dispositivo con l' -xopzione, viene indicato il numero del dispositivo principale / secondario, ma non se è montato.
Vegatripy,

@blueyed In Debian Buster è fornito dal pacchettoutil-linux
elboulangero l'

18

findmnt -rno SOURCE,TARGET "$1"evita tutti i problemi nelle altre risposte. Fa chiaramente il lavoro con un solo comando.


Altri approcci hanno questi aspetti negativi:

  • grep -qe grep -ssono un ulteriore passaggio non necessario e non sono supportati ovunque.
  • /proc/\* non è supportato ovunque.
  • mountinfo si basa su / proc / ..
  • cut -f3 -d' ' incasina gli spazi nei nomi dei percorsi
  • Lo spazio bianco del supporto di analisi è problematico. La sua pagina man ora dice:

.. la modalità elenco è mantenuta solo per compatibilità con le versioni precedenti.

Per un output più robusto e personalizzabile usa findmnt (8), specialmente nei tuoi script.


Funzioni 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

Esempi di utilizzo:

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
Per Linux, comunque, questo è davvero l'approccio migliore. Ho visto il findmnt(8)comando ma non ci ho mai veramente giocato. Francamente se dovessi aggiornare alcuni dei miei script che fanno questo tipo di cose (o ne fanno di nuovi) su una scatola di Linux (o dove il comando è disponibile) questo è quello che farei.
Pryftan,

1
Nota che per encfs, findmntdeve essere fornito con il parametro --source encfs, altrimenti considererà sempre la directory da montare perché ricade sul mount genitore.
Burkart,

Questo è anche meglio della grepsoluzione perché se un percorso di montaggio è strano, puoi ottenere falsi positivi: ad esempio, se monto /dev/mmcblk0p1su ~/mnt/dev/sda1, potrei erroneamente cosa che /dev/sda1è montato dal comando mount | grep '/dev/sda1'. Non riesco a ottenere un falso positivo usando findmnt. Buona risposta!
Cody Piersall,

7

Una sceneggiatura come questa non sarà mai portatile. Un segreto sporco in unix è che solo il kernel sa dove sono i filesystem e, a meno di cose come / proc (non portatile), non ti darà mai una risposta diretta.

In genere uso df per scoprire qual è il punto di montaggio di una sottodirectory e in quale file system si trova.

Ad esempio (richiede shell posix come ash / AT&T ksh / bash / etc)

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

Kinda ti dice informazioni utili.


1
La domanda è taggata su Linux, quindi forse non deve essere portatile
Rory

6

il seguente è quello che uso in uno dei miei cron-job di backup rsync. controlla se / backup è montato e prova a montarlo in caso contrario (potrebbe non funzionare perché l'unità si trova in un alloggiamento hot-swap e potrebbe non essere presente nel sistema)

NOTA: il seguente funziona solo su Linux, perché greps / proc / monta - una versione più portatile eseguirà 'mount | grep / backup ', come nella risposta di Matthew ..

  Se ! grep -q / backup / proc / mounts; poi
    Se ! mount / backup; poi
      echo "fallito"
      uscita 1
    fi
  fi
  echo "superato".
  # fai cose qui

2
Votato come una buona alternativa al controllo della sanità mentale.
Dan Carley,

Presumibilmente questo metodo incontra gli stessi problemi della risposta di Matthew Bloch.
mwfearnley,

sì, ad eccezione del problema dello spazio nel nome file menzionato da "Vista ellittica" (questo greps l'intera riga, non solo un campo estratto). Il problema della sottostringa non è un grosso problema a meno che non dimentichi in qualche modo che la citazione degli argomenti è una cosa che puoi fare. es . grep -q ' /backup ' /proc/mountso mount | grep -q ' /backup '. Oppure reindirizza a / dev / null se il tuo grep non supporta -q(che è nelle specifiche POSIX per grep in questi giorni).
CAS

2

Dal momento che per montare, devi avere comunque una directory lì, che viene montata su, la mia strategia è sempre stata quella di creare un file fasullo con uno strano nome di file che non sarebbe mai stato usato, e controllare solo la sua esistenza. Se il file era lì, allora nulla è stato montato in quel punto ...

Non penso che questo funzioni per il montaggio di unità di rete o cose del genere. L'ho usato per le unità flash.


2

Che ne dici di confrontare i numeri dei dispositivi? Stavo solo cercando di pensare al modo più esoterico ..

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

C'è un difetto nella mia logica con quello ...

Come una funzione:

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

I messaggi di errore dell'eco sono probabilmente ridondanti, poiché stat visualizzerà anche un errore.


In realtà, probabilmente dovrebbe controllare prima lo stato di uscita di stat per ogni chiamata per assicurarsi che il file sia lì ... non così romanzo come pensavo :-(
Kyle Brandt

1

Nessuno di questi soddisfa il caso d'uso in cui una determinata directory è una sottodirectory all'interno di un altro punto di montaggio. Ad esempio, potresti avere / cosa che è un mount NFS per ospitare: / real_thing. L'uso di grep a questo scopo su / proc / mounts / etc / mtab o 'mount' non funzionerà, perché stai cercando un mount point che non esiste. Ad esempio, / cosa / cosa non è un punto di montaggio, ma / cosa è montato sull'host: / real_thing. La migliore risposta votata qui NON è in realtà "il modo migliore per determinare se una directory / volumne è montata". Voterei a favore usando 'df -P' (modalità standard POS--P) come strategia più pulita:

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

L'output dell'esecuzione sarà:

Mounted via: host:/real_thing

Se vuoi sapere qual è il vero mount point, nessun problema:

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

L'output di quel comando sarà:

Mounted on: /thing

Tutto ciò è molto utile se stai cercando di creare una sorta di chroot che rispecchi i punti di mount all'esterno del chroot, all'interno del chroot, tramite una directory o un elenco di file arbitrari.


1

Ci scusiamo per averlo sollevato, ma penso che sia abbastanza utile:

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

Questo ottiene la seconda colonna di / proc / mounts (seconda colonna = punti di mount).

Quindi greps l'output. Nota ^ e $, questo impedisce / backup di corrispondere / mnt / backup o / backup-old ecc.


0

grep / etc / mtab per il tuo mount point forse?


1
mtab può non essere aggiornato o semplicemente non essere aggiornato da mount, come quando usi mount -n perché / è di sola lettura.
chris,

Sono d'accordo, ma quello sembrava il primo posto per iniziare a cercare.
Ophidian,


0

Sebbene questa sia una domanda Linux, perché non renderla portatile quando è facile da eseguire?

La pagina di manuale di grepdice:

Gli script di shell portatili dovrebbero evitare sia -q che -s e dovrebbero invece reindirizzare l'output standard e di errore /dev/null.

Quindi propongo la seguente soluzione:

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

3
Molti sistemi UNIX non forniscono il filesystem / proc
Dmitri Chubarov il

@DmitriChubarov Effettivamente. Cosa rende ironico il concetto di portabilità? E forse è un aggiornamento più recente, ma -qe -ssono specificati dal POSIX, quindi non ci dovrebbe essere alcun problema con la portabilità comunque (ora se non prima - io non ho tenuto traccia di ciò che succede quando cambia).
Pryftan,

0

Deve essere più complicato di così?

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

1
grep -q /mnt/foocorrisponderà anche ai punti di montaggio /mnt/foode /not/mnt/foo... Che ne dici grep -qx /mnt/foo?
rakslice,

@rakslice: che non funzionerebbe. -xfa corrispondere grep solo se l'intera riga corrisponde.
marzo

1
cut -f 3 -d ' 'inciampa quando il percorso di montaggio ha uno spazio in un nome file.
Vista ellittica

0

Dipende da ciò che sai sul volume che stai cercando.

Nel caso particolare che ho studiato di recente, dove ero preoccupato di scoprire se era montata una particolare unità flash, ciò che funziona più facilmente è verificare l'esistenza di / dev / disks / by-label /. Se il dispositivo è collegato, gli script udev assicurano che il collegamento esista (e che venga rimosso quando il dispositivo viene scollegato).

(Questa NON è una risposta altamente portatile; funziona su molte moderne distribuzioni Linux, tuttavia, e la domanda è stata taggata per Linux, ed è un approccio completamente diverso da qualsiasi cosa finora menzionata, quindi espande le possibilità.)


0

Crea un file sotto il tuo mountpoint come check_mounte poi prova se esiste?

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

-1

Ho dovuto farlo in Chef per idempotenza poiché quando lo chef-client sarebbe stato eseguito, la corsa avrebbe avuto esito negativo a causa del volume già montato. Al momento in cui scrivo, la mountrisorsa Chef ha una specie di bug che non funzionerebbe con gli attributi nel modo in cui avevo bisogno, quindi ho montato il volume usando la executerisorsa. Ecco come l'ho fatto:

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

In caso di confusione, nel mio file degli attributi, ho il seguente:

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

La if not node['docker-server']['mountpoint'] == "none"è una parte di una casedichiarazione in cui, se il punto di montaggio sul server non viene specificato, le impostazioni predefinite punto di montaggio none.


... e cosa c'entra questo con la domanda originale?!?
Massimo,

La relazione tra il mio commento sulla ricetta dello Chef e la domanda originale è che le persone si stanno muovendo sempre più verso l'automazione. Pertanto, se qualcuno viene qui chiedendosi come farlo funzionare in una ricetta dello Chef, avranno una risposta. Nella vita ci sono due opzioni: 1) Fai il minimo indispensabile e rendi felici alcune persone, e 2) Vai oltre. Pertanto, invece di contrassegnare il mio post, accettalo per quello che è: informazioni aggiuntive a supporto della risposta accettata.
Kaw

La domanda era sugli script bash, la tua risposta riguarda gli script Chef. Sebbene possa essere utile a qualcuno, non ha ancora alcuna rilevanza per la domanda.
Massimo,

@KLaw 'Pertanto, anziché contrassegnare il mio post, accettalo per quello che è: informazioni aggiuntive a supporto della risposta accettata.' Sono d'accordo e di solito non sono uno a votare in basso (e non ho neanche qui) ma se hai un problema con quel tipo di cose dovresti forse aggiungerlo come aggiunta agli altri tuoi punti? Potrebbe salvare gli altri commenti. Ma per quanto riguarda l'automazione, questo è esattamente ciò che gli script bash consentono, quindi non riesco a vedere il tuo punto. Ovviamente il programmatore in me pensa che lo script sopra sia orribile, ma questo è un problema di lingua più di ogni altra cosa ...
Pryftan
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.