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

Rob*_*Rob 20 grep bash

我正在尝试编写一个 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
Run Code Online (Sandbox Code Playgroud)

编辑:澄清btmon一下,它是Bluez套件的一部分的蓝牙监控工具,而cec-client是一个与libCEC一起打包的实用程序,用于通过HDMI-CEC串行总线(除其他外)发出命令。

Sté*_*las 29

在:

cmd1 | cmd2
Run Code Online (Sandbox Code Playgroud)

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

在 中bash,您会注意到

sleep 1 | uname
Run Code Online (Sandbox Code Playgroud)

一秒后返回。

在:

btmon | grep -m 1 '@ Device Disconnected'
Run Code Online (Sandbox Code Playgroud)

grep将在发现模式出现一次后立即退出,但bash仍会等待btmon.

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

你可以替换#! /bin/bash#! /bin/ksh93作为与兼容的外壳bash和一个只有等待管道的最后一个组件。然后在

btmon | grep -m 1 '@ Device Disconnected'
Run Code Online (Sandbox Code Playgroud)

grep返回后,btmon将在后台运行,shell 将继续执行脚本的其余部分。

如果您想在返回后btmon立即杀死grep,POSIXly,您可以执行以下操作:

sh -c 'echo "$$"; exec btmon' | (
   read pid
   grep -m1 '@ Device Disconnected' || exit
   kill "$pid" 2> /dev/null
   true)
Run Code Online (Sandbox Code Playgroud)

  • 感谢您解释为什么会这样。我没有想到 bash 可能正在等待 btmon 退出。切换到 ksh93 效果很好! (4认同)