I'm trying to write a bash script that polls btmon for device connections. I've got a working solution, but it's absurdly slow, and it seems like the issue is grep being very slow to exit after finding a match (around 25 seconds). What can I do to either speed grep
up or avoid using it altogether?
#!/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: To clarify, btmon
and is a bluetooth monitoring tool that's part of the Bluez suite, and cec-client is a utility that's packaged with libCEC for issuing commands across the HDMI-CEC serial bus (amongst other things).
Best Answer
In:
Most shells (the Bourne shell, (t)csh, as well as yash and some versions of AT&T ksh under some conditions being the notable exceptions) wait for both
cmd1
andcmd2
.In
bash
, you'll notice thatreturns after one second.
In:
grep
will exit as soon as it has found one occurrence of the pattern, butbash
will still wait forbtmon
.btmon
will typically die of a SIGPIPE the next time it writes to the pipe aftergrep
has returned, but if it never writes anything again, it would never receive that signal.You could replace
#! /bin/bash
with#! /bin/ksh93
as that's a shell compatible withbash
and one that only waits for the last component of a pipeline. Then inafter
grep
returns,btmon
would be left running in background and the shell would carry on with the rest of the script.If you wanted to kill
btmon
as soon asgrep
returns, POSIXly, you could do something like: