Я пытаюсь написать скрипт bash, который опрашивает btmon на предмет подключений устройств. У меня есть работающее решение, но оно абсурдно медленное, и похоже, что проблема в том, что grep очень медленно завершает работу после нахождения совпадения (около 25 секунд). Что я могу сделать, чтобы ускорить его grep
или вообще отказаться от его использования?
#!/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
edit: Для ясности, btmon
and — это инструмент мониторинга Bluetooth, входящий в пакет Bluez, а cec-client — это утилита, которая упакована с libCEC для выдачи команд по последовательной шине HDMI-CEC (помимо прочего).
решение1
В:
cmd1 | cmd2
Большинство оболочек (Bourne shell, (t)csh, а также yash и некоторые версии AT&T ksh при определенных условиях являются заметными исключениями) ожидают и , cmd1
и cmd2
.
В bash
, вы заметите, что
sleep 1 | uname
возвращается через одну секунду.
В:
btmon | grep -m 1 '@ Device Disconnected'
grep
завершит работу, как только найдет одно вхождение шаблона, но bash
все равно будет ждать btmon
.
btmon
обычно завершается из-за сигнала SIGPIPE при следующей записи в канал после grep
возврата, но если он больше ничего не пишет, он никогда не получит этот сигнал.
Вы можете заменить #! /bin/bash
на , #! /bin/ksh93 -
так как это оболочка, совместимая с bash
и которая ждет только последний компонент конвейера. Затем в
btmon | grep -m 1 '@ Device Disconnected'
после grep
возврата btmon
останется работающим в фоновом режиме, а оболочка продолжит выполнение оставшейся части скрипта.
Если вы хотите завершить работу btmon
сразу после grep
возврата, то в POSIXly вы можете сделать что-то вроде:
sh -c 'echo "$$"; exec btmon' | (
read pid
grep -m1 '@ Device Disconnected' || exit
kill "$pid" 2> /dev/null
true)