ให้สคริปต์ทุบตีรอข้อความสถานะก่อนดำเนินการต่อ


10

ฉันยิงเซิร์ฟเวอร์ Selenium ด้วยสคริปต์ทุบตีและอย่างที่คุณเห็นจากการประทับเวลาในบันทึกด้านล่างใช้เวลาประมาณ 32 วินาทีสำหรับสิ่งที่จะมาออนไลน์อย่างสมบูรณ์:

Feb 28, 2012 10:19:02 PM org.openqa.grid.selenium.GridLauncher main
INFO: Launching a standalone server
22:19:02.835 INFO - Java: Sun Microsystems Inc. 20.0-b11
22:19:02.836 INFO - OS: Linux 2.6.32-220.4.1.el6.x86_64 amd64
22:19:02.852 INFO - v2.19.0, with Core v2.19.0. Built from revision 15849
22:19:02.988 INFO - RemoteWebDriver instances should connect to: http://127.0.0.1:4444/wd/hub
22:19:02.990 INFO - Version Jetty/5.1.x
22:19:02.992 INFO - Started HttpContext[/selenium-server/driver,/selenium-server/driver]
22:19:02.993 INFO - Started HttpContext[/selenium-server,/selenium-server]
22:19:02.993 INFO - Started HttpContext[/,/]
22:19:34.552 INFO - Started org.openqa.jetty.jetty.servlet.ServletHandler@488e32e7
22:19:34.552 INFO - Started HttpContext[/wd,/wd]
22:19:34.555 INFO - Started SocketListener on 0.0.0.0:4444
22:19:34.555 INFO - Started org.openqa.jetty.jetty.Server@7d29f3b5

แทนที่จะใช้คำสั่ง "sleep 32" หลังจากเริ่มเซิร์ฟเวอร์ (เพื่อหน่วงเวลาสคริปต์ก่อนที่จะย้าย) ฉันต้องการสคริปต์ทุบตีของฉันรอจนกว่าจะเห็นสตริง "เริ่มต้น SocketListener" แล้วดำเนินการต่อ เป็นไปได้ไหม

คำตอบ:


8

คุณสามารถใช้tail -fเพื่ออ่านจากไฟล์ในขณะที่มันเติบโต ระวังสิ่งที่คุณป้อนtail -fเข้าไป คุณสามารถไพพ์tail -fลงในตัวกรองที่รอจนกระทั่งบรรทัดบันทึกที่ต้องการและออก สิ่งที่จะไม่ทำงานคือถ้าคุณไพพ์tail -fเข้าสู่ตัวกรองที่ไปป์ไลน์ในตัวกรองอื่นเนื่องจากตัวกรองระดับกลางจะบัฟเฟอร์เอาต์พุตของมัน งานนี้:

: >file.log  # create an empty log file
start-selenium-session --log-file=file.log &
{ tail -n +1 -f file.log & } | sed -n '/Started SocketListener/q'
speak-to-socket

โปรดทราบว่าฉันใส่tailในพื้นหลัง นี่เป็นเพราะเมื่อsedพบบรรทัดที่ต้องการมันจะออก แต่ไปป์ไลน์ยังคงทำงานตราบใดที่tailกำลังรอบรรทัดถัดไปซึ่งอาจไม่มาทันทีหากเลย¹ เมื่อจะออกจากบรรทัดถัดมาและมันได้รับtail SIGPIPEสิ่งนี้อาจทำให้tailกระบวนการหลงทางถ้าบันทึกถูกลบโดยไม่มีบรรทัดใด ๆ ที่ถูกเขียนลงไป (รับ PID ของtailกระบวนการเพื่อฆ่ามันเมื่อsedออกมาจะเป็นไปได้ แต่หากิน)

¹ ขอบคุณPeter.Oสำหรับการชี้จุดบกพร่องในรุ่นก่อนหน้า


บันทึกย่อ (pedantry หรือบางที) - ฉันไม่รู้จักเชลล์ที่ต้องการ noop เพื่ออนุญาตให้เขียนไฟล์เปล่า
Chris Down

@ChrisDown ไม่ทำเหมือนกันทั้งนั้น แต่ฉันคิดว่ามันชัดเจนกว่าถ้าจะเขียนว่าไม่มี op อย่างชัดเจน
Gilles 'หยุดความชั่วร้าย'

ดี (+1) ... กำลังพูดถึงบัฟเฟอร์: ฉันไม่เข้าใจการกำหนดบัฟเฟอร์ แต่มันมีปัญหาหนึ่งที่ต้องระวังหากบรรทัดเป้าหมายไม่ได้ตามมาทันทีด้วยบรรทัดบันทึกเพิ่มเติม มันแฮงค์จนถึงอีกหลายบรรทัดเขียนแม้ว่า sed ได้จับคู่รูปแบบแล้ว (<- ฉันไม่เข้าใจส่วนนั้น) sedคำสั่งที่ปรับเปลี่ยนซึ่งเขียนมากพอที่จะบันทึกเพื่อบังคับให้ล้างข้อมูล (?) เปิดใช้งานได้ทันที (ฉันทดสอบ) แต่ฉันคิดว่ามีความเป็นไปได้ของข้อมูลที่แทรกเพื่อสลับกับเซเลเนียมเซสชัน .
Peter.O

@ Peter.O IIRC การปรับใช้บางอย่างอ่านบรรทัดถัดไปล่วงหน้าเนื่องจากมีบางกรณีที่มีประโยชน์ (ที่$อยู่หนึ่ง) ฉันไม่เห็นว่าเกิดขึ้นในการทดสอบของฉัน แต่ (กับ GNU sed) คุณแสดงข้อผิดพลาดได้อย่างไรในระบบปฏิบัติการอะไร
Gilles 'SO- หยุดความชั่วร้าย'

@Gilles: paste.ubuntu.com/863326 .. และ: GNU sed เวอร์ชั่น 4.2.1 , tail (GNU coreutils) 7.4
Peter.O

3

มันยากขึ้นเล็กน้อยในสคริปต์ shell แบบตรงๆ แต่นี่คือสิ่งที่ฉันใช้เป็นระยะเวลาหนึ่งสำหรับ tomcat และ oc4j:

perlscr='
alarm 120;
open F, "<$ARGV[0]";
seek F -($ARGV[1]*80),2;
while (1) {exit if (<F>=~$ARGV[2]);}'

window=10
scanfor="^INFO: Server startup in \d+ ms"
perl -e "$perlscr" $logfile $window "$scanfor" 2>&1 0<&1

alarmจะจัดการแขวนศักยภาพใด ๆ ที่คราวล้มเหลว จำนวนบรรทัดที่จะย้อนกลับจาก EOF สามารถปรับได้ (จากไฟล์ปรับแต่ง)

ในที่สุดฉันก็ย้ายสิ่งทั้งหมดไปยังงูหลาม; ในขณะที่มันใช้เวลานานกว่านี้อีกเล็กน้อย แต่ก็มีประสิทธิภาพมากกว่า:

class Alarm:
    import signal
    signal_signal = signal.signal
    signal_SIGALRM = signal.SIGALRM
    signal_SIG_DFL = signal.SIG_DFL
    del signal
    def __init__(self, delay)
       self.howlong = delay
       self.clear()
    def __del__(self):
       self.reset_signals()
    def __nonzero__(self):
       return self.state
    def clear(self):
       self.state = False
       self.reset_signals()
    def _start_alarm(self):
       from signal import alarm
       alarm(self.howlong)
    def _set_sigalarm(self, handler):
        if handler:
            self.signal_signal(self.signal_SIGALRM, handler)
        else:
            self.signal_signal(self.signal_SIGALRM, self.signal_SIG_DFL)
    def reset_signals(self):
        self._set_sigalarm(None)
    def set_signals(self):
        self._set_sigalarm(self.handler)
    def handler(self, signo, frame):
        self.state = False
    def start(self):
        self.state = True
        self.set_signals()
        self._start_alarm()
    def stop(self):
        self.reset_signals()
        self.state = False
found = False
scanfor = re.compile('^INFO: Server startup in \d+ ms')
window = 10
logfile = open(logfilename, 'r')
logfile.seek(window * 80, 2)
alarm = Alarm(timeout)
try:
    alarm.start()
    while alarm:
        line = logfile.readline()
        if line:
            m = scanfor.search(line)
            if m:
                alarm.stop()
                found = True
                break
        time.sleep(0.1)
finally:
    alarm.clear()

1

คุณสามารถเพิ่มสิ่งนี้ลงในสคริปต์ของคุณเพื่อดำเนินการหยุดชั่วคราว:

perl -e 'use File::Tail;
    my $ref=tie *FH,"File::Tail",(name=>"/var/log/messages",maxinterval=>1);
    while(<FH>) { exit if /Started SocketListener/ };'

ทำให้การใช้ของ perl ไฟล์ :: หางtail -f logfile | grep Started SocketListenerโมดูลจะทำตัวเหมือน

แทนที่ / var / log / ข้อความด้วยไฟล์บันทึกที่เหมาะสม โปรดทราบว่ามันจะหยุดตลอดไปหาก "Started SocketListener" ไม่ปรากฏขึ้น


1

บางทีคุณควรใช้การหมดเวลาแทนการรออย่างไม่มีกำหนด

ฟังก์ชั่นทุบตีด้านล่างจะบล็อกจนกว่าข้อความค้นหาที่ระบุจะปรากฏขึ้นหรือถึงระยะหมดเวลาที่กำหนด

สถานะการออกจะเป็น 0 หากพบสตริงภายในระยะหมดเวลา

wait_str() {
  local file="$1"; shift
  local search_term="$1"; shift
  local wait_time="${1:-5m}"; shift # 5 minutes as default timeout

  (timeout $wait_time tail -F -n0 "$file" &) | grep -q "$search_term" && return 0

  echo "Timeout of $wait_time reached. Unable to find '$search_term' in '$file'"
  return 1
}

บางทีล็อกไฟล์ยังไม่มีอยู่หลังจากเปิดซีลีเนียมแล้ว ในกรณีนั้นคุณควรรอให้ปรากฏก่อนค้นหาสตริง:

wait_selenium_server() {
  echo "Waiting for Selenium server..."
  local server_log="$1"; shift
  local wait_time="$1"; shift

  wait_file "$server_log" 10 || { echo "Selenium log file missing: '$server_log'"; return 1; }

  wait_str "$server_log" "Started SocketListener" "$wait_time"
}

wait_file() {
  local file="$1"; shift
  local wait_seconds="${1:-10}"; shift # 10 seconds as default timeout

  until test $((wait_seconds--)) -eq 0 -o -f "$file" ; do sleep 1; done

  ((++wait_seconds))
}

นี่คือวิธีการใช้งาน:

wait_selenium_server "/var/log/selenium.log" 5m && \
echo -e "\n-------------------------- Selenium READY --------------------------\n"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.