계속하기 전에 Bash 스크립트가 상태 메시지를 기다리도록 합니다.

계속하기 전에 Bash 스크립트가 상태 메시지를 기다리도록 합니다.

나는 bash 스크립트를 사용하여 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" 명령을 사용하는 대신(계속하기 전에 스크립트를 지연시키기 위해) 계속하기 전에 bash 스크립트가 "Started SocketListener" 문자열을 볼 때까지 기다리기를 원합니다. 그게 가능합니까?

답변1

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파이프라인은 즉시 나타나지 않을 수도 있는 다음 행을 기다리는 동안 계속 실행되기 때문입니다. 다음 줄이 와서 하나를 받으면 종료됩니다. 어떤 줄도 작성하지 않고 로그를 삭제하면 잘못된 프로세스가 남을 수 있습니다(종료 시 프로세스를 종료하기 위해 프로세스의 PID를 얻는 것은 가능하지만 까다롭습니다).tailtailSIGPIPEtailtailsed

1 감사합니다피터 오이전 버전의 버그를 지적합니다.

답변2

직접 쉘 스크립트에서 수행하는 것은 조금 더 어렵지만 이것은 오랫동안 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

alarmTomcat이 실패하면 잠재적인 정지 상황이 처리 됩니다 . EOF에서 반환된 행 수는 구성 파일에서 조정 가능합니다.

결국 모든 것을 Python으로 옮겼습니다. 조금 더 길지만 조금 더 효율적입니다.

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()

답변3

일시 중지를 구현하려면 스크립트에 다음을 추가할 수 있습니다.

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

그것은 펄을 활용한다파일::꼬리모듈은 비슷하게 동작합니다 tail -f logfile | grep Started SocketListener.

/var/log/message를 적절한 로그 파일로 바꾸십시오. "Started SocketListener"가 전혀 나타나지 않으면 영원히 정지됩니다.

답변4

무기한 기다리는 대신 시간 초과를 사용해야 할 수도 있습니다.

다음 bash 기능은 지정된 검색어가 발생하거나 지정된 시간 초과에 도달할 때까지 차단됩니다.

제한 시간 내에 문자열을 찾으면 종료 상태는 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
}

Selenium을 시작한 후에도 로그 파일이 아직 존재하지 않을 수 있습니다. 이 경우 문자열을 검색하기 전에 해당 문자열이 나타날 때까지 기다려야 합니다.

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"

관련 정보