“ เฝ้าดู” เอาต์พุตของคำสั่งจนกว่าจะสังเกตเห็นสตริงเฉพาะจากนั้นออก


29

ฉันกำลังมองหาวิธีที่จะดูผลลัพธ์ของคำสั่งแบบเป็นโปรแกรมจนกว่าจะสังเกตเห็นสตริงเฉพาะและจากนั้นออก นี่คล้ายกับคำถามนี้มาก แต่แทนที่จะใช้คำสั่ง tailing file ฉันต้องการ 'tail' a command

สิ่งที่ต้องการ:

ดู -n1 my_cmd | grep -m 1 "String Im มองหา"

(แต่นี่ไม่ได้ผลสำหรับฉัน)

UPDATE:ฉันต้องการชี้แจงว่า 'my_cmd' ไม่ได้ส่งข้อความออกมาอย่างต่อเนื่อง แต่ต้องเรียกซ้ำ ๆ จนกระทั่งพบสตริง (ซึ่งเป็นสาเหตุที่ฉันคิดว่าคำสั่ง 'watch') ในแง่นี้ 'my_cmd' ก็เหมือนกับคำสั่ง unix อื่น ๆ เช่น: ps, ls, lsof, last เป็นต้น


ฉันคิดว่ามันเป็นไปได้ที่จะtail -fส่งออกโปรแกรมเช่นเดียวกับไฟล์ ... ฉันผิดหรือเปล่า?
Joanis

@Joanis คุณพูดถูก แต่ในกรณีของฉัน 'my_cmd' ไม่ได้สร้างเอาต์พุตอย่างต่อเนื่องและต้องเรียกซ้ำหลายครั้ง (เหมือนคำสั่งส่วนใหญ่: ps, ls, lsof, ฯลฯ )
gdw2

คำตอบ:


41

ใช้การวนซ้ำ:

until my_cmd | grep -m 1 "String Im Looking For"; do : ; done

แทนที่จะ:ใช้คุณสามารถใช้sleep 1(หรือ 0.2) เพื่อทำให้ CPU ง่ายขึ้น

ลูปจะทำงานจนกระทั่ง grep ค้นหาสตริงในเอาต์พุตของคำสั่ง -m 1หมายถึง "หนึ่งการจับคู่ก็เพียงพอ" เช่น grep หยุดค้นหาหลังจากพบการจับคู่ครั้งแรก

นอกจากนี้คุณยังสามารถใช้grep -qสิ่งที่ออกจากการค้นหาคู่แรก แต่ยังไม่พิมพ์บรรทัดที่ตรงกัน


คำอธิบายของคำสั่งนี้จะได้รับการชื่นชม
ทำเครื่องหมาย W

@ MarkW: อัปเดต
choroba

คนอื่นพูดถึงgrep -qซึ่งเป็นตัวเลือกอื่น grep หยุดทำงานหลังจากค้นหาสตริง
อาทิตย์

โปรดทราบว่าคำสั่งนี้จะเรียกใช้คำสั่งที่เป็นปัญหาซ้ำ ๆ ซึ่งอาจเป็นที่ต้องการหรือไม่ต้องการ
adrien

1
@A__: เป็นที่ต้องการตามที่ระบุไว้ใน OP ภายใต้ "Update"
choroba

11
watch -e "! my_cmd | grep -m 1 \"String Im Looking For\""
  • ! negates รหัสทางออกของไพพ์ไลน์คำสั่ง
  • grep -m 1 ออกเมื่อพบสตริง
  • watch -e ผลตอบแทนถ้าข้อผิดพลาดใด ๆ เกิดขึ้น

แต่สิ่งนี้สามารถปรับปรุงให้แสดงผลที่ตรงกันจริง ๆ ซึ่งถูกโยนทิ้งไป


ขอบคุณสำหรับคำอธิบายโดยละเอียด แต่มันไม่ได้ผลสำหรับฉัน watchคำสั่งของฉัน(CentOS) ไม่ได้มีการ-eตั้งค่าสถานะ แม้ว่าที่สำคัญกว่านั้นเมื่อพบสตริงดูจะทำงานต่อไปและไม่ออก มันดูเหมือนว่าเมื่อgrep -mออกก็ออกฆ่าแต่ไม่ได้my_cmd watch
gdw2

ไม่เป็นไร!, แฟล็ก "-e" เป็นคำสั่งให้ออกจากการเฝ้าดูเมื่อคำสั่งมีรหัสข้อผิดพลาดแตกต่างจาก 0 เนื่องจากนาฬิกาที่ไม่มีอยู่กำลังจะดำเนินการต่อบนแพลตฟอร์มของคุณ อย่างไรก็ตามเป็นสิ่งที่ดีที่รู้ว่าการติดตั้ง Ubuntu 11.10 ของฉันทุกอย่างดี บางครั้งฉันก็มีปัญหากับ Mac OSX เกี่ยวกับเครื่องมือ commandline ที่ล้าสมัยมากและฉันใช้พอร์ต mac จนถึงตอนนี้เพื่อรับซอฟต์แวร์ที่เป็นปัจจุบันมากขึ้น
คณิตศาสตร์

สิ่งนี้จะหยุดหากพบรูปแบบ แต่จะไม่แสดงผลลัพธ์ใด ๆ จนกว่าจะเกิดขึ้น
Mark

คุณอาจใช้teeสิ่งนั้น แต่สิ่งนี้นำเสนอบรรทัดใหม่ที่ทำให้เข้าใจผิดฉันไม่ทราบวิธีหลีกเลี่ยงในขณะนี้:watch -n1 -e "! date | tee /dev/tty | grep --color -m 1 \"17\""
คณิตศาสตร์

ใช่มันไม่ได้ผลสำหรับฉัน watchตามหน้าที่หยุดดูเมื่อพบสตริง แต่จริง ๆ แล้วมันจะไม่ออกจนกว่าคุณจะกดปุ่ม เฉียดฉิว.
mlissner

8

สำหรับผู้ที่มีโปรแกรมที่เขียนไปยัง stdout อย่างต่อเนื่องสิ่งที่คุณต้องทำคือไปที่ grep ด้วยตัวเลือก 'การจับคู่ครั้งเดียว' เมื่อ grep ค้นหาสตริงที่ตรงกันมันจะออกซึ่งจะปิด stdout ในกระบวนการที่กำลังถูกไพพ์ไปยัง grep เหตุการณ์นี้ควรจะเป็นธรรมชาติทำให้โปรแกรมอย่างสง่างามออกตราบใดที่กระบวนการเขียนอีกครั้ง

จะเกิดอะไรขึ้นคือกระบวนการจะได้รับ SIGPIPE เมื่อพยายามเขียนไปยัง stdout ปิดหลังจาก grep ได้ออก นี่คือตัวอย่างของการ ping ซึ่งจะรันแบบไม่มีกำหนด:

$ ping superuser.com | grep -m 1 "icmp_seq"

คำสั่งนี้จะตรงกับ 'พงษ์' ที่ประสบความสำเร็จครั้งแรกและจากนั้นออกในครั้งต่อไปpingพยายามเขียนถึง stdout


อย่างไรก็ตาม

ไม่รับประกันเสมอว่ากระบวนการจะเขียนไปยัง stdout อีกครั้งและอาจไม่ทำให้ SIGPIPE ถูกยกขึ้น (เช่นอาจเกิดขึ้นเมื่อทำการปรับแต่งล็อกไฟล์) ทางออกที่ดีที่สุดที่ฉันได้รับมาสำหรับสถานการณ์นี้เกี่ยวข้องกับการเขียนลงไฟล์ โปรดแสดงความคิดเห็นหากคุณคิดว่าคุณสามารถปรับปรุง:

$ { tail -f log_file & echo $! > pid; } | { grep -m1 "find_me" && kill -9 $(cat pid) && rm pid; }

ทำลายมันลง:

  1. tail -f log_file & echo $! > pid- ตัดไฟล์แนบกระบวนการเป็นพื้นหลังและบันทึก PID ( $!) ไปยังไฟล์ ฉันลองส่งออก PID ไปยังตัวแปรแทน แต่ดูเหมือนว่ามีสภาพการแข่งขันระหว่างที่นี่และเมื่อใช้ PID อีกครั้ง
  2. { ... ;}- จัดกลุ่มคำสั่งเหล่านี้เข้าด้วยกันเพื่อให้เราสามารถไพพ์เอาต์พุตเป็น grep ขณะที่รักษาบริบทปัจจุบัน (ช่วยเมื่อบันทึกและนำตัวแปรกลับมาใช้ใหม่ แต่ไม่สามารถทำงานส่วนนั้นได้)
  3. | - stdout ของท่อทางซ้ายไปยัง stdin ทางด้านขวา
  4. grep -m1 "find_me" - ค้นหาสตริงเป้าหมาย
  5. && kill -9 $(cat pid)- บังคับให้ฆ่า (SIGKILL) tailกระบวนการหลังจาก grepออกเมื่อพบสตริงที่ตรงกัน
  6. && rm pid - ลบไฟล์ที่เราสร้าง

0
my_cmd | tail +1f | sed '/String Im Looking For/q'

ถ้าtailไม่สนับสนุนไวยากรณ์ลอง+1f tail -f -n +1(ตัว-n +1บอกให้เริ่มต้นที่จุดเริ่มต้นtail -fโดยค่าเริ่มต้นจะเริ่มด้วย 10 บรรทัดสุดท้ายของเอาต์พุต)


โปรดดูการอัปเดตคำถามของฉัน
gdw2

0

ผนวกผลลัพธ์ของการเรียกโปรแกรมของคุณไปยังไฟล์ จากนั้นtail -fไฟล์นั้น ด้วยวิธีนี้ควรใช้งานได้ ... ฉันหวังว่า

เมื่อคุณเริ่มการเรียกโปรแกรมนั้นใหม่อีกครั้งคุณจะต้องลบไฟล์หรือต่อท้ายซึ่งเป็นการพูดพล่อยๆเพียงเพื่อให้มันไม่ตรงอีกครั้งในสิ่งที่คุณกำลังมองหา

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