Grep lambat untuk keluar setelah menemukan kecocokan?


20

Saya mencoba menulis skrip bash yang memilih btmon untuk koneksi perangkat. Saya punya solusi yang berfungsi, tetapi ini sangat lambat, dan sepertinya masalahnya adalah sangat lambat untuk keluar setelah menemukan kecocokan (sekitar 25 detik). Apa yang bisa saya lakukan untuk mempercepat grepatau menghindari menggunakannya sama sekali?

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

sunting: Untuk memperjelas, btmondan merupakan alat pemantauan bluetooth yang merupakan bagian dari paket Bluez, dan cec-client adalah utilitas yang dikemas dengan libCEC untuk mengeluarkan perintah di bus serial HDMI-CEC (di antara hal-hal lain).


2
Berapa banyak "barang" yang btmondihasilkan? apakah Anda yakin itu bukan hanya masalah buffering?
steeldriver

@steeldriver diperbantukan. Sudahkah Anda mencoba menonaktifkan buffering di dalam pipa?
l0b0

btmon menghasilkan sekitar 250 karakter per detik.
Rob

@ l0b0 Saya mencoba menonaktifkan buffering dengan perintah unbuffer, tapi itu sepertinya mencegah grep keluar sama sekali? Saya juga mencoba memaksa grep ke mode --line-buffer, tapi itu sepertinya tidak membantu.
Rob

Bisa jadi itu btmonmengimplementasikan buffering sendiri, dalam hal ini Anda kurang beruntung.
l0b0

Jawaban:


28

Di:

cmd1 | cmd2

Sebagian besar shell (shell Bourne, (t) csh, serta yash dan beberapa versi AT&T ksh dalam beberapa kondisi menjadi pengecualian yang menonjol) menunggu keduanya cmd1dan cmd2.

Di bash, Anda akan melihat itu

sleep 1 | uname

kembali setelah satu detik.

Di:

btmon | grep -m 1 '@ Device Disconnected'

grepakan keluar segera setelah menemukan satu kemunculan pola, tetapi bashmasih akan menunggu btmon.

btmonbiasanya akan mati karena SIGPIPE saat berikutnya ia menulis ke pipa setelah grepkembali, tetapi jika ia tidak pernah menulis apapun lagi, ia tidak akan pernah menerima sinyal itu.

Anda bisa menggantinya #! /bin/bashdengan #! /bin/ksh93shell yang kompatibel dengan bashdan yang hanya menunggu komponen terakhir pipa. Lalu masuk

btmon | grep -m 1 '@ Device Disconnected'

setelah grepkembali, btmonakan dibiarkan berjalan di latar belakang dan shell akan melanjutkan dengan sisa skrip.

Jika Anda ingin membunuh btmonsegera setelah greppengembalian, POSIXly, Anda dapat melakukan sesuatu seperti:

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

3
Terima kasih telah menjelaskan mengapa ini berperilaku seperti itu. Tidak terpikir oleh saya bahwa bash mungkin sedang menunggu btmon untuk keluar. Bertukar dengan ksh93 bekerja dengan indah!
Rob
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.