找到匹配项后Grep缓慢退出?


20

我正在尝试编写一个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一下,它是Bluez套件的一部分,是一个蓝牙监视工具,而cec-client是libCEC附带的实用程序,用于通过HDMI-CEC串行总线发布命令(以及其他操作)。


2
btmon输出多少“东西” ?您确定这不只是缓冲问题吗?
钢铁司机

@steeldriver借调。您是否尝试过在管道中禁用缓冲
l0b0

btmon每秒输出约250个字符。
罗布

@ l0b0我尝试使用unbuffer命令禁用缓冲,但是这似乎完全阻止了grep退出?我还尝试将grep强制设为--line-buffer模式,但这似乎无济于事。
罗布

可能是自己btmon实现了缓冲,在这种情况下,您很不走运。
l0b0

Answers:


28

在:

cmd1 | cmd2

大多数shell(Bourne shell,(t)csh以及yash和AT&T ksh的某些版本,在某些情况下是明显的例外)都同时等待cmd1cmd2

在中bash,您会注意到

sleep 1 | uname

一秒钟后返回。

在:

btmon | grep -m 1 '@ Device Disconnected'

grep一旦发现该模式出现,它将立即退出,但bash仍将等待btmon

btmon通常,它在grep返回后的下一次写入管道时通常会死于SIGPIPE ,但如果再也不写入任何内容,它将永远不会收到该信号。

你可以替换#! /bin/bash#! /bin/ksh93作为与兼容的外壳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)

3
感谢您解释为什么这种行为方式。在我看来,bash可能正在等待btmon退出。切换到ksh93效果很好!
罗布
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.