Ich versuche, ein Bash-Skript zu schreiben, das btmon nach Geräteverbindungen abfragt. Ich habe eine funktionierende Lösung, aber sie ist absurd langsam, und das Problem scheint darin zu liegen, dass grep nach dem Finden einer Übereinstimmung sehr langsam beendet wird (etwa 25 Sekunden). Was kann ich tun, um grep
es zu beschleunigen oder ganz zu vermeiden?
#!/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
Bearbeiten: Zur Klarstellung: btmon
und ist ein Bluetooth-Überwachungstool, das Teil der Bluez-Suite ist, und cec-client ist ein Dienstprogramm, das mit libCEC gepackt ist, um (unter anderem) Befehle über den seriellen HDMI-CEC-Bus auszugeben.
Antwort1
In:
cmd1 | cmd2
Die meisten Shells (die Bourne-Shell, (t)csh sowie yash und unter bestimmten Bedingungen einige Versionen von AT&T ksh sind bemerkenswerte Ausnahmen) warten sowohl auf als auch cmd1
auf cmd2
.
In bash
werden Sie feststellen, dass
sleep 1 | uname
kehrt nach einer Sekunde zurück.
In:
btmon | grep -m 1 '@ Device Disconnected'
grep
wird beendet, sobald es ein Vorkommen des Musters gefunden hat, bash
wartet aber noch auf btmon
.
btmon
bricht normalerweise beim nächsten Schreiben in die Pipe nach grep
der Rückkehr aufgrund eines SIGPIPE zusammen, aber wenn es nie wieder etwas schreibt, würde es dieses Signal nie empfangen.
Sie könnten es #! /bin/bash
durch ersetzen #! /bin/ksh93 -
, da dies eine Shell ist, die mit kompatibel ist bash
und nur auf die letzte Komponente einer Pipeline wartet. Dann in
btmon | grep -m 1 '@ Device Disconnected'
nach grep
der Rückgabe btmon
würde es im Hintergrund weiterlaufen und die Shell würde mit dem Rest des Skripts fortfahren.
btmon
Wenn Sie POSIX-mäßig sofort beenden möchten grep
, können Sie Folgendes tun:
sh -c 'echo "$$"; exec btmon' | (
read pid
grep -m1 '@ Device Disconnected' || exit
kill "$pid" 2> /dev/null
true)