Wird Grep nach dem Finden einer Übereinstimmung langsam beendet?

Wird Grep nach dem Finden einer Übereinstimmung langsam beendet?

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 grepes 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: btmonund 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 cmd1auf cmd2.

In bashwerden Sie feststellen, dass

sleep 1 | uname

kehrt nach einer Sekunde zurück.

In:

btmon | grep -m 1 '@ Device Disconnected'

grepwird beendet, sobald es ein Vorkommen des Musters gefunden hat, bashwartet aber noch auf btmon.

btmonbricht normalerweise beim nächsten Schreiben in die Pipe nach grepder 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/bashdurch ersetzen #! /bin/ksh93 -, da dies eine Shell ist, die mit kompatibel ist bashund nur auf die letzte Komponente einer Pipeline wartet. Dann in

btmon | grep -m 1 '@ Device Disconnected'

nach grepder Rückgabe btmonwürde es im Hintergrund weiterlaufen und die Shell würde mit dem Rest des Skripts fortfahren.

btmonWenn 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)

verwandte Informationen