tail -f y luego salir en la cadena coincidente

tail -f y luego salir en la cadena coincidente

Estoy intentando configurar un script de inicio que iniciará Tomcat, monitoreará catalina.out en busca de la cadena "Inicio del servidor" y luego ejecutará otro proceso. He estado probando varias combinaciones de tail -f con grep y awk, pero todavía no funciona nada. El principal problema que tengo parece ser forzar la muerte de la cola después de que grep o awk hayan coincidido con la cadena.

Lo he simplificado al siguiente caso de prueba.

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

El comportamiento que estoy viendo es que grep sale después de 20 segundos, sin embargo, la cola tardará 40 segundos más en morir. Entiendo por qué sucede esto: tail solo notará que la tubería desapareció cuando escribe en ella, lo que solo sucede cuando se agregan datos al archivo. Esto se ve agravado por el hecho de que tail almacenará los datos en el buffer y generará los caracteres B y C como una sola escritura (lo confirmé por strace). Intenté solucionarlo con soluciones que encontré en otros lugares, como usar el comando unbuffer, pero eso no ayudó.

¿Alguien tiene alguna idea sobre cómo hacer que esto funcione como lo espero? O ideas para esperar el inicio exitoso de Tomcat (pensando en esperar a que un puerto TCP sepa que se ha iniciado, pero sospecho que será más complejo que lo que estoy tratando de hacer ahora). Me las arreglé para que funcione con awk haciendo un "killall tail" en el partido, pero no estoy contento con esa solución. Tenga en cuenta que estoy intentando que esto funcione en RHEL4.

Respuesta1

¿Algo como esto?

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

en su totalidad:

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

Parece funcionar en 20 segundos.

$ time ./test2.sh

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

ACTUALIZAR

Esta forma también parece funcionar:

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

Y si a veces ve que sale inmediatamente, intente agregar un sueño 1, es decir

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

Respuesta2

Todo en una línea, reemplace 'do foo' con comando'

# inicio del servicio tomcat6
# cola -f /var/log/tomcat6/catalina.out | awk '/Inicio del servidor/{sistema("do foo"); salir 0}'

Respuesta3

Pierde la cola. Dado que comienza con un child.out vacío, no lo necesita y (como ha descubierto) complica las cosas. Simplemente busque la primera instancia en un ciclo de sueño.

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

Si necesitas conservar la cola porque no siempre comienzas con un archivo catalina.out vacío, coloca la cola dentro del bucle:

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

información relacionada