Como posso usar um pipe em uma condição while?

4

Eu quero fazer um loop, enquanto o grep faz ou não encontra algo que eu possa escrever:

while grep 'matches' inLogFile.txt
do
  echo good.
  sleep 10
done

Ou

while grep -v 'notHereYet' inLogFile.txt
do
  sleep 2
done
echo -e '\a'Yo! It is here now.

Eu estou digitando estes no prompt do shell interativo.

Então eu queria verificar repetidamente df para quando um volume realmente foi montado, como:

while df | grep -v '/toBeMounted'
do
  sleep 2
done
echo -e '\a'Hey, I think you wanted to know that /toBeMounted is available finally.

Estou com problemas para descobrir como agrupar o tubo na condição.

Eu sei que posso fazer algo como:

while [ -z "$(df|grep '/toBeMounted')" ]
do
  sleep 2
done
echo -e '\a'Okay that is finally present now.

No entanto, sinto que deve haver uma maneira de fazer isso usando valores de saída em vez da comparação de string.

    
por dlamblin 17.09.2016 / 08:05

2 respostas

8

Para acertar a lógica, apenas pequenas alterações são necessárias. Use:

while ! df | grep '/toBeMounted'
do
  sleep 2
done
echo -e '\a'Hey, I think you wanted to know that /toBeMounted is available finally.

Discussão

O código correspondente na pergunta foi:

while df | grep -v '/toBeMounted'

O código de saída de um pipeline é o código de saída do último comando no pipeline. grep -v '/toBeMounted' retornará verdadeiro (código = 0) se pelo menos uma linha de entrada não corresponder a /toBeMounted . Assim, isso testa se há outras coisas montadas além de /toBeMounted . Isto não é nada do que você está procurando.

Para usar df e grep para testar se /toBeMounted está montado, precisamos

df | grep '/toBeMounted'

Isso retorna true se /toBeMounted estiver montado. O que você realmente precisa é a negação disso: você precisa de uma condição que seja verdadeira se /toBeMounted não estiver montado. Para fazer isso, só precisamos usar a negação, denotada por ! :

! df | grep '/toBeMounted'

E isso é o que usamos no código acima.

Documentação

De manual do Bash :

The return status of a pipeline is the exit status of the last command, unless the pipefail option is enabled. If pipefail is enabled, the pipeline's return status is the value of the last (rightmost) command to exit with a non-zero status, or zero if all commands exit successfully. If the reserved word ! precedes a pipeline, the exit status of that pipeline is the logical negation of the exit status as described above. The shell waits for all commands in the pipeline to terminate before returning a value.

    
por John1024 17.09.2016 / 08:14
4

O fato de você estar usando df com grep me diz que você está filtrando a saída de df até que algum dispositivo seja montado em um diretório específico, ou seja, esteja ou não na lista.

Em vez de filtrar o foco da lista no diretório que você deseja. Para nossa sorte, o utilitário mountpoint nos permite fazer exatamente isso e permite lidar com o status de saída desse comando. Considere isso:

$ mountpoint  /mnt/HDD/                                                        
/mnt/HDD/ is a mountpoint
$ echo $?
0
$ mountpoint  ~                                                                
/home/xieerqi is not a mountpoint
$ echo $?
1

Seu script, portanto, pode ser reescrito como

while ! mountput /toBeMounted > /dev/null
do
   sleep 3
done
echo "Yup, /toBeMounted got mounted!"

Exemplo executado com meu próprio disco:

$ while ! mountpoint /mnt/HDD > /dev/null
> do 
>     echo "Waiting"
>     sleep 1
> done && echo "/mnt/HDD is mounted"
Waiting
Waiting
Waiting
Waiting
Waiting
/mnt/HDD is mounted

Em uma nota lateral, você pode facilmente implementar sua própria versão do comando mountpoint , por exemplo, em python, como eu fiz:

#!/usr/bin/env python3
from os import path
import sys

def main():

    if not sys.argv[1]:
       print('Missing a path')
       sys.exit(1)

    full_path = path.realpath(sys.argv[1])
    with open('/proc/self/mounts') as mounts:
       print
       for line in mounts:
           if full_path in line:
              print(full_path,' is mountpoint')
              sys.exit(0)
    print(full_path,' is not a mountpoint')
    sys.exit(1)

if __name__ == '__main__':
    main()

Execução da amostra:

$ python3 ./is_mountpoint.py /mnt/HDD                                          
/mnt/HDD  is mountpoint
$ python3 ./is_mountpoint.py ~                                                 
/home/xieerqi  is not a mountpoint
    
por Sergiy Kolodyazhnyy 17.09.2016 / 11:03

Tags