Devam etmeden önce Bash betiğinin durum mesajını beklemesini sağlayın


10

Selenium sunucusunu bash betiği ile çalıştırıyorum ve aşağıdaki günlükteki zaman damgalarından görebileceğiniz gibi, şeyin tamamen çevrimiçi olması yaklaşık 32 saniye sürüyor:

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

Sunucuyu başlattıktan sonra "uyku 32" komutunu kullanmak yerine (devam etmeden önce komut dosyasını geciktirmek için), bash komut dosyamın "Başlatılan SocketListener" dizesini görene kadar beklemesini ve ardından devam etmesini istiyorum. Mümkün mü?

Yanıtlar:


8

tail -fDosya büyüdükçe okumaya devam etmek için kullanabilirsiniz . Ne beslediğinize dikkat edin tail -f. tail -fİstenen günlük çizgisine kadar bekleyip çıkana kadar bir filtreye boru oluşturabilirsiniz. Çalışmayan şey tail -f, başka bir filtreye boru oluşturan bir filtreye boru bağlarsanız, çünkü ara filtre çıkışını tamponlayacaktır. Bu çalışıyor:

: >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

tailArka plana koyduğumu unutmayın . Bunun nedeni sed, istenen hattı bulduğunda tailçıkmasıdır, ancak bir sonraki hattı beklediği sürece boru hattı çalışmaya devam eder , bu da hemen gelmeyebilir¹. tailbir sonraki satır geldiğinde çıkacak ve a alacaktır SIGPIPE. tailGünlük, herhangi bir satır yazılmadan kaldırılırsa, başıboş bir işlem bırakabilir ( çıkışlar mümkün tailolduğunda öldürmek için işlemin PID'sini elde etmek sedmümkün ama zor olabilir).

¹ sayesinde Peter.O önceki bir sürümünde hata işaret için.


Bir not (belki de bilgiçlik) - Boş bir dosya yazmaya izin vermek için aslında bir noop gerektiren herhangi bir kabuk bilmiyorum .
Chris Down

@ChrisDown Ben de yapmam. Ama no-op'yu açıkça yazmayı daha net buluyorum.
Gilles 'SO- kötü

Güzel (+1) ... arabelleklerden bahsetmişken: Arabelleğe alma işlemlerini anlamıyorum, ancak hedef çizginin hemen ardından daha fazla günlük çizgisi gelmemesi durumunda farkında olmak için bir sorunu var. Sed desenle zaten eşleşmesine rağmen, daha fazla satır yazılana kadar askıda kalıyor (<- Bu kısmı anlamıyorum). Bir sedsifonu zorlamak için günlüğe yeteri kadar yazılan değiştirilmiş bir komut (?), Hemen başlatır (test ettim), ancak eklenen verilerin bir selenyum-oturum satırı ile serpilme olasılığı olduğunu düşünüyorum. .
Peter.O

@ Peter.O IIRC bazı sed uygulamaları bir sonraki satırı önceden okur, çünkü yararlı olduğu durumlar vardır (biri için $adres). Bunun testlerimde olduğunu görmedim (GNU sed ile). Hangi işletim sisteminde hatayı tam olarak nasıl gösterdiniz?
Gilles 'SO- kötü'

@Gilles: paste.ubuntu.com/863326 .. ve: GNU sed sürüm 4.2.1 , kuyruk (GNU coreutils) 7.4
Peter.O

3

Düz kabuk betiğinde biraz daha zor, ama tomcat ve oc4j için bir süredir kullanıyordum:

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

alarmErkek kedi başarısız herhangi bir potansiyel asılı işleyecektir. EOF'dan geri dönecek satır sayısı ayarlanabilir (bir yapılandırma dosyasından).

Sonunda her şeyi python'a taşıdım; biraz daha uzun olsa da, biraz daha verimlidir:

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

Duraklamayı uygulamak için bunu komut dosyanıza ekleyebilirsiniz:

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

Bu gibi davranmak için perl File :: Tail modülünü kullanır tail -f logfile | grep Started SocketListener.

/ Var / log / message öğesini uygun günlük dosyasıyla değiştirin. "Başlatılan SocketListener" asla görünmezse sonsuza kadar askıda kalacağını unutmayın.


1

Belki süresiz beklemek yerine zaman aşımı kullanmalısınız.

Aşağıdaki bash işlevi, belirtilen arama terimi görünene veya belirli bir zaman aşımına ulaşılana kadar engellenir.

Dize zaman aşımı içinde bulunursa çıkış durumu 0 olur.

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
}

Belki de günlük dosyası Selenium'u başlattıktan hemen sonra mevcut değildir. Bu durumda, dizeyi aramadan önce görünmesini beklemelisiniz:

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

Bunu nasıl kullanabileceğiniz aşağıda açıklanmıştır:

wait_selenium_server "/var/log/selenium.log" 5m && \
echo -e "\n-------------------------- Selenium READY --------------------------\n"
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.