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 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
editar: Para esclarecer, btmon
e é 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 cmd1
e 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á por btmon
.
btmon
normalmente morrerá de um SIGPIPE na próxima vez que gravar no pipe após grep
retornar, mas se nunca mais gravar nada, nunca receberá esse sinal.
Você pode substituir #! /bin/bash
por #! /bin/ksh93 -
, pois é um shell compatível bash
e que aguarda apenas o último componente de um pipeline. Então em
btmon | grep -m 1 '@ Device Disconnected'
após grep
o retorno, btmon
seria deixado em execução em segundo plano e o shell continuaria com o resto do script.
Se você quisesse matar btmon
assim que grep
retornasse, POSIXly, poderia fazer algo como:
sh -c 'echo "$$"; exec btmon' | (
read pid
grep -m1 '@ Device Disconnected' || exit
kill "$pid" 2> /dev/null
true)