Estoy tratando de escribir un script bash que sondee btmon para 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 acelerar grep
o evitar usarlo 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
y es una herramienta de monitoreo de bluetooth que forma parte de la suite Bluez, y cec-client es una utilidad que se incluye con libCEC para emitir comandos a través del bus serie HDMI-CEC (entre otras cosas).
Respuesta aceptada:
en:
cmd1 | cmd2
La mayoría de los shells (el Bourne shell, (t)csh, así como yash y algunas versiones de AT&T ksh en algunas condiciones son las 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 haya encontrado una ocurrencia del patrón, pero bash
seguirá esperando btmon
.
btmon
normalmente morirá de un SIGPIPE la próxima vez que escriba en la tubería después de grep
ha regresado, pero si nunca vuelve a escribir nada, nunca recibiría esa señal.
¡Podrías reemplazar #! /bin/bash
con #! /bin/ksh93
ya que es un shell compatible con bash
y uno que solo espera el último componente de una canalización. Luego en
btmon | grep -m 1 '@ Device Disconnected'
después de grep
devuelve, btmon
se dejaría ejecutándose en segundo plano y el shell continuaría con el resto del script.
Si quisieras matar a btmon
tan pronto como grep
regresa, POSIXly, podría hacer algo como:
sh -c 'echo "$$"; exec btmon' | (
read pid
grep -m1 '@ Device Disconnected' || exit
kill "$pid" 2> /dev/null
true)