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


10

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"라는 문자열이 나타날 때까지 기다렸다가 계속 진행하고 싶습니다. 가능합니까?

답변:


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원하는 라인을 찾아 그것을 종료,하지만만큼으로 파이프 라인은 계속 실행 tailall¹ 즉시 경우 제공되지 않을 수 다음 줄을 기다리고 있습니다. tail다음 줄이 오면 종료되고가 ​​나타납니다 SIGPIPE. tail로그에 줄을 쓰지 않고 제거하면 길 잃은 프로세스 가 남을 수 있습니다 ( 종료가 가능하지만 까다로운 경우 로그 tail를 죽이는 프로세스 의 PID를 얻음 sed).

¹ 이전 버전의 버그를 지적한 Peter.O 에게 감사합니다 .


메모 (아마도 보육)-나는 빈 파일을 쓸 수 있도록 실제로 noop이 필요한 쉘을 모른다 .
Chris Down

@ChrisDown 나도 마찬가지입니다. 그러나 no-op을 명시 적으로 작성하는 것이 더 명확합니다.
Gilles 'SO- 악마 중지'

Nice (+1) ... 버퍼 말하기 : 버퍼링 가공을 이해하지 못하지만 대상 줄 바로 뒤에 더 많은 로그 줄이 없으면 알아 두어야 할 한 가지 문제가 있습니다. sed가 이미 패턴과 일치하더라도 더 많은 줄이 쓰여질 때까지 중단됩니다 (<-나는 그 부분을 이해하지 못합니다). sed플러시 (?)를 강제로 수행하기 위해 로그에 충분히 쓰는 수정 된 명령은 즉시 쫓아 버리지 만 (테스트했습니다) 삽입 된 데이터가 셀레늄 세션 줄에 산재 할 수 있다고 생각합니다. .
Peter.O

@ Peter.O IIRC 일부 sed 구현은 다음 행을 미리 읽습니다. 유용한 경우가 있기 때문입니다 ( $주소). 그래도 (GNU sed 사용) 테스트에서 이런 일이 발생하지는 않았습니다. 어떤 OS에서 정확히 버그를 표시 했습니까?
Gilles 'SO- 악의를 그만두십시오

@Gilles : paste.ubuntu.com/863326 .. 및 : GNU sed 버전 4.2.1 , tail (GNU coreutils) 7.4
Peter.O

3

스트레이트 쉘 스크립트에서는 조금 더 어렵지만 이것은 바람둥이와 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 File :: Tail 모듈을 사용하여처럼 동작합니다 tail -f logfile | grep Started SocketListener.

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


1

무한정 기다리는 대신 타임 아웃을 사용해야 할 수도 있습니다.

아래의 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"
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.