Grep lento para sair depois de encontrar correspondência?

20

Estou tentando escrever um script bash que monitora o btmon para conexões de dispositivos. Eu tenho uma solução de trabalho, mas é absurdamente lenta, e parece que o problema é que o grep está muito lento para sair depois de encontrar uma correspondência (cerca de 25 segundos). O que posso fazer para acelerar grep ou evitar usá-lo completamente?

#!/bin/bash
COUNTER=0
while :
  do
    until btmon | grep -m 1 '@ Device Connected'
      do :
    done
    let COUNTER=COUNTER+1
    echo on 0 | cec-client RPI -s -d 1
    sleep 5
    echo as | cec-client RPI -s -d 1
    until btmon | grep -m 1 '@ Device Disconnected'
      do :
    done
    let COUNTER=COUNTER-1
    if [ $COUNTER -eq 0 ];
      then echo standby 0 | cec-client RPI -s -d 1;
    fi
done

edit: Para esclarecer, btmon e é uma ferramenta de monitoramento bluetooth que faz parte da suíte Bluez, e cec-client é um utilitário que vem com libCEC para emissão de comandos através do barramento serial HDMI-CEC (entre outras coisas) .

    
por Rob 23.05.2017 / 17:27

1 resposta

27

Em:

cmd1 | cmd2

A maioria das shells (shell Bourne, (t) csh, assim como yash e algumas versões do AT & T ksh, sob algumas condições, são exceções notáveis), aguarde tanto cmd1 como cmd2 .

Em bash , você notará que

sleep 1 | uname

retorna após um segundo.

Em:

btmon | grep -m 1 '@ Device Disconnected'

grep sairá assim que encontrar uma ocorrência do padrão, mas bash ainda aguardará btmon .

btmon normalmente morrerá de um SIGPIPE da próxima vez que gravar no pipe após grep ter retornado, mas se ele nunca escrever nada novamente, ele nunca receberá esse sinal.

Você pode substituir #! /bin/bash por #! /bin/ksh93 , pois esse é um shell compatível com bash e um que aguarda apenas o último componente de um pipeline. Então em

btmon | grep -m 1 '@ Device Disconnected'

depois que grep retornar, btmon seria executado em segundo plano e o shell continuaria com o restante do script.

Se você quisesse matar btmon assim que grep retornasse, POSIXly, você poderia fazer algo como:

sh -c 'echo "$$"; exec btmon' | (
   read pid
   grep -m1 '@ Device Disconnected' || exit
   kill "$pid" 2> /dev/null
   true)
    
por 23.05.2017 / 18:21

Tags