경기를 찾은 후 Grep이 천천히 종료됩니까?


20

장치 연결을 위해 btmon을 폴링하는 bash 스크립트를 작성하려고합니다. 작동하는 솔루션을 가지고 있지만 터무니없이 느리며 일치하는 항목을 찾은 후 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는 HDMI-CEC 직렬 버스를 통해 명령을 실행하기 위해 libCEC와 함께 패키지 된 유틸리티입니다.


2
얼마나 "물건"이 btmon출력됩니까? 버퍼링의 문제가 아니라고 확신하십니까?
— steeldriver

@steeldriver Seconded. 파이프에서 버퍼링 을 비활성화 하려고 했습니까 ?
— l0b0

btmon은 초당 약 250자를 출력합니다.
— Rob

@ l0b0 unbuffer 명령으로 버퍼링을 비활성화하려고 시도했지만 grep이 전혀 종료되지 않는 것 같습니다. 또한 grep을 --line-buffer 모드로 설정하려고 시도했지만 도움이되지 않는 것 같습니다.
— Rob

btmon버퍼링 자체 를 구현할 수 있습니다 .이 경우 운이 좋지 않습니다.
— l0b0

답변:


28

에서:

cmd1 | cmd2

대부분의 쉘 (Bourne 쉘 (t) CSH뿐만 아니라 YASH과 주목할만한 예외 인 어떤 조건에서 AT & T KSH의 일부 버전) 모두 대기 cmd1하고 cmd2.

에서 bash, 당신은 알 수 있습니다

sleep 1 | uname

1 초 후에 돌아갑니다.

에서:

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백그라운드에서 실행 상태로 유지되고 쉘은 나머지 스크립트를 계속 수행합니다.

POSIXly 반납 btmon하자마자 죽이고 싶다면 grep다음과 같이 할 수 있습니다.

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

3
이것이 왜 그렇게 동작하는지 설명해 주셔서 감사합니다. bash가 btmon이 종료되기를 기다리는 것은 나에게 일어나지 않았습니다. ksh93으로 바꾸면 아름답게 작동합니다!
— Rob
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.