tail -f จากนั้นออกจากการจับคู่สตริง


1

ฉันกำลังพยายามกำหนดค่าสคริปต์เริ่มต้นซึ่งจะเริ่มต้น Tomcat ตรวจสอบ catalina.out สำหรับสตริง "Server startup" แล้วเรียกใช้กระบวนการอื่น ฉันได้ลองใช้ชุดต่าง ๆ ของ tail -f กับ grep และ awk แต่ยังไม่ได้ทำงานอะไรเลย ปัญหาหลักที่ฉันดูเหมือนจะบังคับให้หางตายหลังจาก grep หรือ awk จับคู่กับสตริง

ฉันทำให้การทดสอบต่อไปนี้ง่ายขึ้น

test.sh is listed below:

#!/bin/sh    
rm -f child.out
./child.sh > child.out &
tail -f child.out | grep -q B

child.sh is listed below:

#!/bin/sh
echo A
sleep 20
echo B
echo C
sleep 40
echo D

พฤติกรรมที่ฉันเห็นคือ grep ออกหลังจาก 20 วินาทีอย่างไรก็ตามหางจะใช้เวลาอีก 40 วินาทีในการตาย ฉันเข้าใจว่าทำไมสิ่งนี้จึงเกิดขึ้น - หางจะสังเกตเห็นว่าไปป์นั้นหายไปเมื่อมันเขียนลงไปซึ่งจะเกิดขึ้นเมื่อข้อมูลถูกผนวกเข้ากับไฟล์ นี่ประกอบไปด้วยความจริงที่ว่าหางจะต้องบัฟเฟอร์ข้อมูลและเอาท์พุทอักขระ B และ C เป็นการเขียนครั้งเดียว (ฉันยืนยันสิ่งนี้ด้วย strace) ฉันพยายามแก้ไขด้วยวิธีแก้ปัญหาที่พบที่อื่นเช่นใช้คำสั่ง unbuffer แต่ไม่ได้ช่วย

มีใครมีความคิดเห็นเกี่ยวกับวิธีทำให้การทำงานนี้เป็นไปตามที่ฉันคาดหวัง หรือแนวคิดสำหรับการรอ Tomcat ที่ประสบความสำเร็จในการเริ่มต้น (คิดเกี่ยวกับการรอให้พอร์ต TCP รู้ว่ามันเริ่มต้นแล้ว แต่สงสัยว่ามันจะซับซ้อนกว่าที่ฉันพยายามทำอยู่ตอนนี้) ฉันจัดการเพื่อให้มันทำงานกับ awk ทำ "killall tail" ในการแข่งขัน แต่ฉันไม่พอใจกับวิธีแก้ปัญหานั้น หมายเหตุฉันพยายามทำให้มันใช้งานได้กับ RHEL4

คำตอบ:


5

อะไรแบบนี้?

mkfifo child.fifo
tail -f child.out > child.fifo &
pid=$!
grep -q B child.fifo && kill $pid

เต็ม:

#!/bin/sh    
rm -f child.out
./child.sh > child.out &
mkfifo child.fifo
tail -f child.out > child.fifo &
pid=$!
grep -q B child.fifo && kill $pid
rm child.fifo

ดูเหมือนว่าจะทำงานใน 20 วินาที

$ time ./test2.sh

real    0m20.156s
user    0m0.033s
sys     0m0.058s

UPDATE

วิธีนี้ดูเหมือนจะทำงานด้วย:

#!/bin/sh
rm -f child.out
./child.sh > child.out &
(tail -f child.out | grep -q B child.out)

และถ้าคุณเห็นมันออกมาในบางครั้งลองเพิ่ม sleep 1 เช่น

#!/bin/sh
rm -f child.out
./child.sh > child.out &
sleep 1
(tail -f child.out | grep -q B child.out)

นั่นเป็นความคิดที่เจ๋งมาก แต่แค่ลองแล้วมันจะกลับมาทันทีแทนที่จะคาดหวังหลังจาก 20 วินาที นี่น่าจะเป็นเพราะพฤติกรรมของ grep ในไฟล์ Fifo บางทีฉันต้องลองวิธีนี้ด้วย awk ฉันจะอัปเดตหากใช้งานได้
Patrick

บางทีคุณอาจเห็นร่างแบบก่อนหน้านี้ที่ฉันกำลังแก้ไข รุ่นดังกล่าวข้างต้นจะใช้เวลา 20 time ./test2.shวินาทีที่แสดงโดย
มิเคล

ทำงานได้ดีในตอนนี้ขอบคุณสำหรับความช่วยเหลือของคุณ เป็นการดีที่ฉันต้องการในคำสั่ง piped เดียว แต่ฉันไม่คิดว่าเป็นไปได้และการแก้ปัญหาไม่ซับซ้อนเกินไป ไม่อยากเชื่อเลยตอนนี้ฉันใช้เวลาส่วนใหญ่ไปกับการพยายามทำให้งานวานนี้!
Patrick

ไม่มีปัญหา! ดีใจที่ได้ช่วยเหลือ
มิเคล

@ แพทริกฉันไม่รู้สึกถึงการใช้ท่อgrep -q B filenameเนื่องจากไม่ได้ตรวจสอบ STDIN เพียงแค่เนื้อหาของไฟล์ (ตามที่คาดไว้)
poige

2

ทั้งหมดในบรรทัดเดียวแทนที่ 'do foo' ด้วยคำสั่ง '

# บริการ tomcat6 เริ่มต้น
# tail -f /var/log/tomcat6/catalina.out | awk '/ เซิร์ฟเวอร์เริ่มต้น / {ระบบ ("do foo"); ออก 0} '

1

เสียหาง เมื่อคุณเริ่มต้นด้วย child.out ที่ว่างเปล่าคุณไม่จำเป็นต้องใช้มันและ (ตามที่คุณค้นพบ) มันซับซ้อนกว่า เพียงแค่ grep สำหรับอินสแตนซ์แรกใน sleep loop

until fgrep -q "Server startup" child.out; do sleep 1; done

หากคุณจำเป็นต้องรักษาหางไว้เพราะคุณไม่ได้เริ่มต้นด้วย catalina ที่ว่างเสมอออกวางหางไว้ในลูป:

until tail child.out| fgrep -q "Server startup"; do sleep 1; done
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.