我正在尝试编写一个 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
编辑:澄清一下,btmon
cec-client 是一个蓝牙监控工具,属于 Bluez 套件的一部分,而 cec-client 是一个与 libCEC 打包在一起的实用程序,用于通过 HDMI-CEC 串行总线(除其他外)发出命令。
答案1
在:
cmd1 | cmd2
大多数 shell(Bourne shell、(t)csh、以及 yash 和某些版本的 AT&T ksh 在某些情况下是值得注意的例外)都会等待cmd1
和cmd2
。
在 中bash
,你会注意到
sleep 1 | uname
一秒后返回。
在:
btmon | grep -m 1 '@ Device Disconnected'
grep
一旦发现该模式出现一次就会退出,但bash
仍会等待btmon
。
btmon
grep
返回后,下次写入管道时通常会死于 SIGPIPE ,但如果它不再写入任何内容,则它永远不会收到该信号。
您可以替换#! /bin/bash
为,#! /bin/ksh93 -
因为这是一个兼容的 shell bash
,并且只等待管道的最后一个组件。然后在
btmon | grep -m 1 '@ Device Disconnected'
grep
返回后,btmon
将在后台运行,并且 shell 将继续执行脚本的其余部分。
如果你想btmon
在返回后立即杀死grep
,POSIXly,你可以这样做:
sh -c 'echo "$$"; exec btmon' | (
read pid
grep -m1 '@ Device Disconnected' || exit
kill "$pid" 2> /dev/null
true)