Grep chậm để thoát sau khi tìm thấy trận đấu?


20

Tôi đang cố gắng viết một tập lệnh bash để thăm dò btmon cho các kết nối thiết bị. Tôi đã có một giải pháp hiệu quả, nhưng nó chậm một cách vô lý và có vẻ như vấn đề là grep rất chậm thoát ra sau khi tìm thấy một trận đấu (khoảng 25 giây). Tôi có thể làm gì để tăng tốc grephoặc tránh sử dụng nó hoàn toàn?

#!/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

chỉnh sửa: Để làm rõ btmonvà là một công cụ giám sát bluetooth là một phần của bộ Bluez và cec-client là một tiện ích được đóng gói với libCEC để phát lệnh trên bus nối tiếp HDMI-CEC (trong số những thứ khác).


2
Làm thế nào nhiều "công cụ" không btmonđầu ra? bạn có chắc không chỉ là vấn đề đệm?
Steeldo

@steel ấn Thứ hai. Bạn đã thử vô hiệu hóa bộ đệm trong đường ống?
l0b0

btmon xuất ra khoảng 250 ký tự mỗi giây.
Cướp

@ l0b0 Tôi đã thử vô hiệu hóa bộ đệm bằng lệnh unbuffer, nhưng điều đó dường như ngăn grep thoát khỏi tất cả? Tôi cũng đã thử buộc grep sang chế độ - line-buffer, nhưng điều đó dường như không có ích.
Cướp

Nó có thể là btmonthực hiện đệm chính nó, trong trường hợp bạn không gặp may.
l0b0

Câu trả lời:


28

Trong:

cmd1 | cmd2

Hầu hết các shell (shell Bourne, (t) csh, cũng như yash và một số phiên bản của AT & T ksh trong một số điều kiện là ngoại lệ đáng chú ý) chờ cả hai cmd1cmd2.

Trong bash, bạn sẽ nhận thấy rằng

sleep 1 | uname

trở lại sau một giây.

Trong:

btmon | grep -m 1 '@ Device Disconnected'

grepsẽ thoát ngay sau khi tìm thấy một lần xuất hiện của mẫu, nhưng bashvẫn sẽ chờ btmon.

btmonThông thường sẽ chết vì SIGPIPE vào lần tiếp theo nó ghi vào đường ống sau khi grepquay trở lại, nhưng nếu nó không bao giờ viết lại bất cứ điều gì, nó sẽ không bao giờ nhận được tín hiệu đó.

Bạn có thể thay thế #! /bin/bashbằng #! /bin/ksh93lớp vỏ tương thích bashvà lớp vỏ chỉ chờ thành phần cuối cùng của đường ống. Sau đó trong

btmon | grep -m 1 '@ Device Disconnected'

sau khi greptrả về, btmonsẽ được chạy ở chế độ nền và shell sẽ tiếp tục với phần còn lại của tập lệnh.

Nếu bạn muốn giết btmonngay khi greptrở về, POSIXly, bạn có thể làm một cái gì đó như:

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

3
Cảm ơn đã giải thích lý do tại sao điều này là hành xử theo cách nó làm. Nó đã không xảy ra với tôi rằng bash có thể đang chờ btmon thoát ra. Trao đổi với ksh93 hoạt động rất đẹp!
Cướp
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.