Bash scripting - loop até o valor de retorno ser 0

21

Eu preciso desmontar algo no meu script, mas às vezes ele desmonta antes que todos os dados tenham sido copiados e faz com que o umount falhe. Procurei uma maneira de fazer um "bloqueio", mas não encontrei nada. Então, eu tentei escrever um script para fazer um loop até que ele pudesse ser desmontado, mas não funciona.

while [ 'sudo umount mount' ]
do
    sleep 0.1
done
rmdir mount

Quando executar saídas:

umount: /home/evantandersen/mount: device is busy.
        (In some cases useful info about processes that use
         the device is found by lsof(8) or fuser(1))
rmdir: failed to remove 'mount': Device or resource busy

Ele não deve fazer um loop até que o valor de retorno de sudo umount mount seja 0, o que significa que foi com êxito umount?

    
por charliehorse55 07.06.2013 / 00:32

2 respostas

51

O comando [ é avaliar expressões condicionais. Não tem utilidade aqui.

Como umount não produz nada em sua saída padrão (os erros vão para stderr), 'sudo umount mount' se expande para nada.

Então é como:

while [ ]
do
  sleep 0.1
done

O comando [ , quando não passou nenhum argumento ao lado de [ e ] retorna falso (um status de saída diferente de zero), portanto você não inserirá o loop.

Mesmo se umount tivesse produzido seus erros no stdout, usar o comando [ não faria sentido, porque as palavras resultantes dessa saída nunca teriam criado uma expressão condicional válida.

Aqui você quer:

until sudo umount mount
do
  sleep 0.1
done

Ou seja, você deseja verificar o status de saída de sudo / umount, não de um comando [ .

Se você quisesse verificar se umount gerou algum erro ou aviso no seu stderr, é aí que o [ poderia ter sido útil. O -n "some-string" é uma expressão condicional reconhecida pelo comando [ para testar se "some-string" está vazio ou não, então algo como:

while [ -n "$(sudo umount mount 2>&1 > /dev/null)" ]; do
  sleep 0.1
done

Mas procurar a presença de mensagens de erro ou de aviso é geralmente uma má ideia. O comando umount nos informa se ele é ou não bem-sucedido com seu código de saída, isso é muito mais confiável. Pode ter sucesso e ainda produzir alguma mensagem de aviso. Pode falhar e não produzir um erro (como quando é morto).

Nesse caso em particular, observe que umount pode falhar porque o diretório não está montado e você daria um loop para sempre nesse caso, portanto, poderia tentar outra abordagem como:

while mountpoint -q mount && ! sudo umount mount; do
  sleep 0.1
done

Ou se "montar" pode ser montado várias vezes e você deseja desmontar todos:

while mountpoint -q mount; do
  sudo umount mount || sleep 0.1
done
    
por 07.06.2013 / 00:46
4

função reutilizável e tempo limite em 'n' segundos

_umount() {
    [[ $# -lt 2 ]] && { 
        echo "Usage: ${FUNCNAME} <timeout_secs> <mnt_point>"; return 1
    }
    timeout=$(($(date +%s) + ${1}))
    until umount "${2}" 2>/dev/null || [[ $(date +%s) -gt $timeout ]]; do
       :
    done
}

não precisa dormir

    
por 08.06.2013 / 01:01