Grep ช้าที่จะออกหลังจากพบการแข่งขัน?


20

ฉันกำลังพยายามเขียนสคริปต์ทุบตีที่สำรวจ 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

@steeldriver Seconded คุณได้ลองปิดการใช้งานการบัฟเฟอร์ในไพพ์หรือไม่?
l0b0

btmon มีเอาต์พุตประมาณ 250 ตัวอักษรต่อวินาที
Rob

@ l0b0 ฉันลองปิดการใช้งานการบัฟเฟอร์ด้วยคำสั่ง unbuffer แต่ดูเหมือนว่าจะป้องกันไม่ให้ grep ออกจากโปรแกรมเลย? ฉันยังพยายามบังคับให้โหมด grep เป็น - line-buffer แต่ดูเหมือนว่าจะไม่ช่วย
Rob

อาจเป็นได้ว่าbtmonการดำเนินการบัฟเฟอร์ตัวเองซึ่งในกรณีที่คุณโชคไม่ดี
l0b0

คำตอบ:


28

ใน:

cmd1 | cmd2

เปลือกหอยส่วนใหญ่ (บอร์นเชลล์ (t) csh เช่นเดียวกับ Yash และบางรุ่นของ AT & T ksh ภายใต้เงื่อนไขบางอย่างเป็นข้อยกเว้น) รอให้ทั้งสองและcmd1cmd2

ในbashคุณจะสังเกตเห็นว่า

sleep 1 | uname

ผลตอบแทนหลังจากหนึ่งวินาที

ใน:

btmon | grep -m 1 '@ Device Disconnected'

grepจะออกทันทีที่พบรูปแบบหนึ่งเกิดขึ้น แต่bashจะยังรอbtmonอยู่

btmonโดยทั่วไปแล้วจะตายจาก SIGPIPE ในครั้งถัดไปที่เขียนไปยังไพพ์หลังจากgrepกลับมาแล้ว แต่ถ้ามันไม่เคยเขียนอะไรอีกมันจะไม่ได้รับสัญญาณนั้น

คุณสามารถแทนที่#! /bin/bashด้วย#! /bin/ksh93เนื่องจากเป็นเชลล์ที่ใช้งานร่วมกันได้bashและสามารถแทนที่ด้วยองค์ประกอบสุดท้ายของไปป์ไลน์เท่านั้น จากนั้นใน

btmon | grep -m 1 '@ Device Disconnected'

หลังจากgrepส่งคืนbtmonจะถูกปล่อยให้รันในพื้นหลังและเชลล์จะดำเนินการกับสคริปต์ที่เหลือ

หากคุณต้องการฆ่าbtmonทันทีที่ได้grepรับผลตอบแทน POSIXly คุณสามารถทำสิ่งต่อไปนี้:

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

3
ขอขอบคุณที่อธิบายว่าทำไมสิ่งนี้จึงเป็นไปในแบบที่มันเป็น มันไม่ได้เกิดขึ้นกับฉันว่าทุบตีอาจรอ btmon เพื่อออก การสลับไปใช้ ksh93 นั้นทำงานได้อย่างสวยงาม!
Rob
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.