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