tail -f und dann bei übereinstimmender Zeichenfolge beenden

tail -f und dann bei übereinstimmender Zeichenfolge beenden

Ich versuche, ein Startskript zu konfigurieren, das Tomcat startet, catalina.out auf die Zeichenfolge „Serverstart“ überwacht und dann einen anderen Prozess ausführt. Ich habe verschiedene Kombinationen von tail -f mit grep und awk ausprobiert, aber bisher hat nichts funktioniert. Das Hauptproblem, das ich habe, scheint darin zu liegen, dass ich tail zum Beenden zwinge, nachdem grep oder awk die Zeichenfolge gefunden haben.

Ich habe es auf den folgenden Testfall vereinfacht.

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

Das Verhalten, das ich sehe, ist, dass grep nach 20 Sekunden beendet wird, tail jedoch weitere 40 Sekunden braucht, um zu sterben. Ich verstehe, warum das passiert – tail bemerkt nur, dass die Pipe weg ist, wenn es darauf schreibt, was nur passiert, wenn Daten an die Datei angehängt werden. Dies wird dadurch verstärkt, dass tail die Daten puffern und die Zeichen B und C als einzelnes Schreiben ausgeben soll (ich habe dies durch strace bestätigt). Ich habe versucht, das mit Lösungen zu beheben, die ich anderswo gefunden habe, wie z. B. mit dem Befehl unbuffer, aber das hat nicht geholfen.

Hat jemand eine Idee, wie ich das so hinbekomme, wie ich es erwarte? Oder Ideen, wie man auf einen erfolgreichen Tomcat-Start wartet (ich denke darüber nach, auf einen TCP-Port zu warten, der weiß, dass er gestartet ist, aber ich vermute, das wird komplizierter als das, was ich jetzt versuche). Ich habe es geschafft, es mit awk zum Laufen zu bringen, indem ich bei Übereinstimmung ein „killall tail“ ausführe, aber ich bin mit dieser Lösung nicht zufrieden. Beachten Sie, dass ich versuche, dies auf RHEL4 zum Laufen zu bringen.

Antwort1

Etwas wie das?

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

vollständig:

#!/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

Scheint in 20 Sekunden zu laufen.

$ time ./test2.sh

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

AKTUALISIEREN

Dieser Weg scheint auch zu funktionieren:

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

Und wenn Sie sehen, dass es manchmal sofort beendet wird, versuchen Sie, ein sleep 1 hinzuzufügen, d. h.

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

Antwort2

Alles in einer Zeile, ersetzen Sie „do foo“ durch „command“

# Dienst Tomcat6 starten
# tail -f /var/log/tomcat6/catalina.out | awk '/Serverstart/{system("do foo"); exit 0}'

Antwort3

Verlieren Sie das Ende. Da Sie mit einem leeren child.out beginnen, brauchen Sie es nicht und (wie Sie festgestellt haben) macht es die Sache komplizierter. Suchen Sie einfach in einer Sleep-Schleife nach der ersten Instanz.

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

Wenn Sie das Ende behalten müssen, weil Sie nicht immer mit einem leeren catalina.out beginnen, platzieren Sie das Ende innerhalb der Schleife:

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

verwandte Informationen