Grep lento para sair depois de encontrar a correspondência?

Grep lento para sair depois de encontrar a correspondência?

Estou tentando escrever um script bash que pesquisa o btmon em busca de conexões de dispositivos. Eu tenho uma solução funcional, mas é absurdamente lenta e parece que o problema é que o grep demora muito para sair depois de encontrar uma correspondência (cerca de 25 segundos). O que posso fazer para acelerar grepou 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

editar: Para esclarecer, btmone é uma ferramenta de monitoramento de bluetooth que faz parte do pacote Bluez, e cec-client é um utilitário empacotado com libCEC para emitir comandos através do barramento serial HDMI-CEC (entre outras coisas).

Responder1

Em:

cmd1 | cmd2

A maioria dos shells (o shell Bourne, (t)csh, bem como o yash e algumas versões do AT&T ksh sob algumas condições sendo as exceções notáveis) esperam por ambos cmd1e cmd2.

Em bash, você notará que

sleep 1 | uname

retorna após um segundo.

Em:

btmon | grep -m 1 '@ Device Disconnected'

grepsairá assim que encontrar uma ocorrência do padrão, mas bashainda aguardará por btmon.

btmonnormalmente morrerá de um SIGPIPE na próxima vez que gravar no pipe após grepretornar, mas se nunca mais gravar nada, nunca receberá esse sinal.

Você pode substituir #! /bin/bashpor #! /bin/ksh93 -, pois é um shell compatível bashe que aguarda apenas o último componente de um pipeline. Então em

btmon | grep -m 1 '@ Device Disconnected'

após grepo retorno, btmonseria deixado em execução em segundo plano e o shell continuaria com o resto do script.

Se você quisesse matar btmonassim que grepretornasse, POSIXly, poderia fazer algo como:

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

informação relacionada