Qual é a melhor maneira de verificar se um volume está montado em um script Bash?

103

Qual é a melhor maneira de verificar se um volume está montado em um script Bash?

O que eu realmente gostaria é de um método que eu possa usar assim:

if <something is mounted at /mnt/foo> 
then
   <Do some stuff>
else
   <Do some different stuff>
fi
Mark Biek
fonte
Eu estava prestes a escrever um script para fazer isso sozinho. Meu primeiro pensamento é obter informações do / etc / mtab Mas ainda não folheei meus livros do bash para ver se há uma maneira mais direta.
3dinfluence
@ 3dinfluence - sim, eu sei disso por um longo tempo, mas /etc/mtab, /proc/mountsestão ligados a /proc/self/mounts. (pelo menos no Fedora 20) #
Wilf 16/01
Perguntas semelhantes estão relacionadas a Falha no servidor , Estouro de pilha e Unix e Linux Stack Exchange .
Sasha

Respostas:

113

Evite usar, /etc/mtabpois pode ser inconsistente.

Evite tubulações, mountporque não precisa ser tão complicado.

Simplesmente:

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

(O espaço após o /mnt/fooé evitar correspondência, por exemplo /mnt/foo-bar.)

Dan Carley
fonte
7
Sem mencionar, uma chamada para montagem pode travar se o ponto de montagem estiver em cunha.
Chad Huneycutt 5/08/09
8
Bom para linux, não para freebsd ou solaris.
chris
4
Isso é verdade, Chris. Embora a pergunta tenha sido marcada como linux.
21719 Dan Carley
3
Eu acho que essa é uma pergunta filosófica - devemos tentar tornar as coisas portáteis, se possível, ou devemos simplesmente assumir que todas as janelas / linux em execução no mundo e agir de acordo?
chris
18
Na verdade, você deve testar '/ mnt / foo', ie. com um espaço ou você poderá obter um falso positivo se tiver montado um volume chamado por exemplo. 'fooks'. Acabei de receber esse problema com dois pontos de montagem, 'lmde' e 'lmde-home'.
Marlar
58
if mountpoint -q /mnt/foo 
then
   echo "mounted"
else
   echo "not mounted"
fi

ou

mountpoint -q /mnt/foo && echo "mounted" || echo "not mounted"
Zaptac
fonte
4
Apenas para informação: mountpointorigina-se no pacote "initscripts" no Ubuntu / Debian.
blueyed 25/09/12
1
Não funcionou para mim - :-(
Wilf
Este é o chamado, sobre o qual meu Vagrant se apega.
dhill
O problema mountpointé que ele verifica, de fato, se um ponto de montagem está montado, mas não se um dispositivo está montado. Se um dispositivo for aprovado com a -xopção, ele informará o número do dispositivo principal / secundário, mas não se ele estiver montado.
vegatripy
@blueyed No Debian Buster, ele é fornecido pelo pacoteutil-linux
elboulangero
18

findmnt -rno SOURCE,TARGET "$1"evita todos os problemas nas outras respostas. Ele limpa o trabalho com apenas um comando.


Outras abordagens têm as seguintes desvantagens:

  • grep -qe grep -ssão uma etapa extra desnecessária e não são suportadas em todos os lugares.
  • /proc/\* não é suportado em qualquer lugar.
  • mountinfo é baseado em / proc / ..
  • cut -f3 -d' ' bagunça espaços nos nomes dos caminhos
  • A análise do espaço em branco da montagem é problemática. É página de manual agora diz:

.. o modo de listagem é mantido apenas para compatibilidade com versões anteriores.

Para uma saída mais robusta e personalizável, use findmnt (8), especialmente em seus scripts.


Funções do 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

Exemplos de uso:

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
Vista elíptica
fonte
1
De qualquer maneira, para Linux específico, essa é realmente a melhor abordagem. Vi o findmnt(8)comando, mas nunca brinquei com ele. Francamente, se eu atualizasse alguns dos meus scripts que fazem esse tipo de coisa (ou fazem novos) em uma caixa Linux (ou onde o comando está disponível), é isso que eu faria.
Pryftan
1
Observe que, para encfs, findmntdeve ser fornecido com o parâmetro --source encfs, caso contrário, ele sempre considerará o diretório a ser montado porque ele retorna à montagem pai.
Burkart
Isso também é melhor do que a grepsolução, porque se um caminho de montagem é estranho, você pode obter falsos positivos: por exemplo, se eu montar /dev/mmcblk0p1em ~/mnt/dev/sda1, eu poderia incorretamente coisa que /dev/sda1é montado pelo comando mount | grep '/dev/sda1'. Não consigo obter um falso positivo usando findmnt. Boa resposta!
Cody Piersall 15/10
7

Um script como esse nem sempre será portátil. Um segredo sujo no unix é que apenas o kernel sabe quais são os sistemas de arquivos e, além de coisas como / proc (não portável), nunca fornecerá uma resposta direta.

Normalmente, uso o df para descobrir qual é o ponto de montagem de um subdiretório e em que sistema de arquivos ele está.

Por exemplo (requer shell posix como 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

Meio que lhe informa informações úteis.

chris
fonte
1
A questão está etiquetada como linux, então talvez não precise ser portátil
Rory
6

a seguir é o que eu uso em um dos meus cron-jobs de backup rsync. ele verifica se / backup está montado e tenta montá-lo, se não estiver (pode falhar porque a unidade está em um compartimento de troca a quente e pode até não estar presente no sistema)

NOTA: o seguinte funciona apenas no linux, porque greps / proc / mounts - uma versão mais portátil executaria 'mount | grep / backup ', como na resposta de Matthew ..

  E se ! grep -q / backup / proc / montagens; então
    E se ! montagem / backup; então
      eco "falhou"
      saída 1
    fi
  fi
  eco "superado".
  # faça coisas aqui
cas
fonte
2
Promovido como uma boa alternativa de verificação de sanidade.
21711 Dan Carley
Presumivelmente, esse método tem os mesmos problemas que a resposta de Matthew Bloch.
Mkfearnley
sim, exceto pelo problema de espaço no nome do arquivo mencionado por "Visualização elíptica" (isso mostra toda a linha, não apenas um campo extraído). O problema da sub-string não é grande coisa, a menos que você esqueça de alguma forma que a citação de argumentos é algo que você pode fazer. por exemplo grep -q ' /backup ' /proc/mountsou mount | grep -q ' /backup '. Ou redirecione para / dev / null se o seu grep não suportar -q(que está na especificação POSIX para grep atualmente).
21818
2

Como para montar, você precisa ter um diretório lá de qualquer maneira, que seja montado, minha estratégia sempre foi criar um arquivo falso com um nome de arquivo estranho que nunca seria usado e apenas verificar sua existência. Se o arquivo estava lá, nada foi montado naquele local ...

Eu não acho que isso funcione para montar unidades de rede ou coisas assim. Eu usei para drives flash.

Brian Postow
fonte
2

Que tal comparar números de dispositivos? Eu só estava tentando pensar da maneira mais esotérica ..

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

Há uma falha na minha lógica com isso ...

Como uma função:

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

As mensagens de erro de eco provavelmente são redundantes, porque o stat também exibirá o erro.

Kyle Brandt
fonte
Na verdade, provavelmente teria de verificar o status de saída de status primeiro para cada chamada para garantir que o arquivo está lá ... não tão nova quanto eu pensei :-(
Kyle Brandt
1

Nenhuma delas satisfaz o caso de uso em que um determinado diretório é um subdiretório dentro de outro ponto de montagem. Por exemplo, você pode ter / coisa que é uma montagem NFS para hospedar: / real_thing. Usar grep para esse fim em / proc / mounts / etc / mtab ou 'mount' não funcionará, porque você estará procurando um ponto de montagem que não existe. Por exemplo, / thing / thingy não é um ponto de montagem, mas / thing está montado no host: / real_thing. A melhor resposta votada aqui NÃO é "a melhor maneira de determinar se um diretório / volume está montado". Eu votaria a favor usando 'df -P' (modo de padrões -P POSIX) como uma estratégia mais limpa:

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

A saída da execução disso será:

Mounted via: host:/real_thing

Se você deseja saber qual é o verdadeiro ponto de montagem, não há 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"
}

A saída desse comando será:

Mounted on: /thing

Tudo isso é muito útil se você estiver tentando criar algum tipo de chroot que espelhe pontos de montagem fora do chroot, dentro do chroot, por meio de um diretório ou lista de arquivos arbitrários.

Craig
fonte
1

Desculpe por trazer isso à tona, mas acho que isso é bastante útil:

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

Isso obtém a segunda coluna de / proc / mounts (segunda coluna = pontos de montagem).

Então ele recebe a saída. Observe ^ e $, isso impede / backup de corresponder / mnt / backup ou / backup-old etc.

David
fonte
0

grep / etc / mtab para o seu ponto de montagem, talvez?

Ophidian
fonte
1
O mtab pode ficar desatualizado ou simplesmente não ser atualizado pelo mount, como quando você usa o mount -n porque / é somente leitura.
chris
Eu concordo, mas esse parecia ser o primeiro lugar para começar a procurar.
Ophidian
0

Este?:

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

De: Um fórum do Ubuntu

Controle de taxa
fonte
0

Embora essa seja uma pergunta sobre o Linux, por que não torná-lo portátil quando é fácil?

A página do manual grepdiz:

Os scripts de shell portáteis devem evitar -q e -s e, em /dev/nullvez disso, devem redirecionar a saída padrão e de erro .

Então, proponho a seguinte solução:

if grep /mnt/foo /proc/mounts > /dev/null 2>&1; then
        echo "Mounted"
else
        echo "NOT mounted"
fi
fex
fonte
3
Muitos sistemas UNIX não fornecem o sistema de arquivos / proc
Dmitri Chubarov
@DmitriChubarov Indeed. O que torna irônico o conceito de portabilidade, não é? E talvez seja uma atualização mais recente, mas -qe -ssão especificados pelo POSIX então não deve haver qualquer problema de portabilidade com ele de qualquer maneira (agora, se não antes - Eu não tenho mantido a par de que mudanças acontecem quando).
Pryftan
0

Precisa ser mais complicado que isso?

mount \
    | cut -f 3 -d ' ' \
    | grep -q /mnt/foo \
  && echo "mounted" || echo "not mounted"
Matthew Bloch
fonte
1
grep -q /mnt/footambém combinará pontos de montagem /mnt/foode /not/mnt/foo... Que tal grep -qx /mnt/foo?
rakslice
@rakslice: isso não funcionaria. -xfaz grep corresponder apenas se a linha inteira corresponder.
mivk
1
cut -f 3 -d ' 'tropeça quando o caminho de montagem tem um espaço em um nome de arquivo.
Visualização elíptica
0

Depende do que você sabe sobre o volume que está verificando.

No caso específico que pesquisei recentemente, em que estava preocupado em descobrir se uma unidade flash específica foi montada, o que funciona mais facilmente é verificar a existência de / dev / disks / by-label /. Se o dispositivo estiver conectado, os scripts do udev garantem que o link exista (e que ele seja removido quando o dispositivo estiver desconectado).

(Essa NÃO é uma resposta altamente portátil; funciona em muitas distribuições modernas do Linux, e a pergunta foi marcada para Linux, e é uma abordagem completamente diferente de qualquer coisa mencionada até agora, para expandir as possibilidades.)

David Dyer-Bennet
fonte
0

Crie um arquivo sob o seu ponto de montagem check_mounte teste apenas se ele existe?

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

Eu tive que fazer isso no Chef por idempotência, já que quando o chef-client seria executado, a execução falharia devido ao volume já estar montado. No momento em que escrevo isso, o mountrecurso Chef possui algum tipo de erro que não funcionaria com os atributos da maneira que eu precisava, então montei o volume usando o executerecurso. Aqui está como eu fiz isso:

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

Em caso de confusão, no meu arquivo de atributos, tenho o seguinte:

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

Isso if not node['docker-server']['mountpoint'] == "none"faz parte de uma caseinstrução em que, se o ponto de montagem no servidor não for especificado, o ponto de montagem será o padrão none.

KLaw
fonte
... e o que isso tem a ver com a pergunta original?!?
Massimo
A relação do meu comentário da receita do Chef com a pergunta original é que as pessoas estão cada vez mais se movendo em direção à automação. Portanto, se alguém vier aqui se perguntando como fazer isso funcionar em uma receita de Chef, eles terão uma resposta. Na vida, existem duas opções: 1) faça o mínimo necessário e faça algumas pessoas felizes; e 2) faça o possível. Portanto, em vez de marcar minha postagem, aceite-a pelo que é: informações adicionais que suportem a resposta aceita.
Klaw
A pergunta era sobre scripts bash, sua resposta é sobre scripts de Chef. Embora possa ser útil a alguém, ainda não tem nenhuma relevância para a questão.
Massimo
@KLaw 'Portanto, em vez de marcar minha postagem, aceite-a pelo que é: informações adicionais que suportem a resposta aceita.' Eu concordo e geralmente não sou favorável a voto negativo (e também não o fiz aqui), mas se você tiver um problema com esse tipo de coisa, talvez o adicione como um complemento a seus outros pontos? Pode salvar os outros comentários. Mas, quanto à automação, é exatamente isso que os scripts do bash permitem, por isso não entendi o seu argumento. É claro que o programador em mim pensa que o script acima é hediondo, mas isso é um problema de linguagem mais do que qualquer outra coisa ...
Pryftan