Estoy intentando escribir un script bash que sondee btmon para detectar conexiones de dispositivos. Tengo una solución que funciona, pero es absurdamente lenta y parece que el problema es que grep tarda mucho en salir después de encontrar una coincidencia (alrededor de 25 segundos). ¿Qué puedo hacer para acelerarlo grep
o evitar su uso por completo?
#!/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 aclarar, btmon
es una herramienta de monitoreo de bluetooth que forma parte de la suite Bluez, y cec-client es una utilidad incluida con libCEC para emitir comandos a través del bus serie HDMI-CEC (entre otras cosas).
Respuesta1
En:
cmd1 | cmd2
La mayoría de los shells (el shell Bourne, (t)csh, así como yash y algunas versiones de AT&T ksh bajo algunas condiciones son excepciones notables) esperan tanto cmd1
y cmd2
.
En bash
, notarás que
sleep 1 | uname
regresa después de un segundo.
En:
btmon | grep -m 1 '@ Device Disconnected'
grep
Saldrá tan pronto como encuentre una aparición del patrón, pero bash
aún esperará btmon
.
btmon
Por lo general, un SIGPIPE morirá la próxima vez que escriba en la tubería después de grep
haber regresado, pero si nunca vuelve a escribir nada, nunca recibirá esa señal.
Puede reemplazarlo #! /bin/bash
con, #! /bin/ksh93 -
ya que es un shell compatible bash
y que solo espera el último componente de una canalización. Luego en
btmon | grep -m 1 '@ Device Disconnected'
después de grep
regresar, btmon
se dejaría ejecutándose en segundo plano y el shell continuaría con el resto del script.
Si quisieras matar btmon
tan pronto como grep
regrese, POSIXly, podrías hacer algo como:
sh -c 'echo "$$"; exec btmon' | (
read pid
grep -m1 '@ Device Disconnected' || exit
kill "$pid" 2> /dev/null
true)