tail -f e, em seguida, sair na string correspondente

1

Estou tentando configurar um script de inicialização que irá inicializar o tomcat, monitorar o catalina.out para a cadeia "Inicialização do servidor" e depois executar outro processo. Eu tenho tentado várias combinações de tail -f com grep e awk, mas ainda não tenho nada funcionando. A principal questão que estou tendo parece ser forçar a cauda a morrer depois de grep ou awk ter correspondido a string.

Eu simplifiquei o seguinte caso de teste.

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

O comportamento que estou vendo é que o grep sai depois de 20 segundos, no entanto, a cauda leva mais 40 segundos para morrer. Eu entendo porque isso está acontecendo - a cauda só vai notar que o pipe sumiu quando ele escreve, o que só acontece quando os dados são anexados ao arquivo. Isso é agravado pelo fato de que tail deve estar armazenando os dados em buffer e exibindo os caracteres B e C como uma única gravação (confirmei isso por strace). Eu tentei consertar isso com soluções que encontrei em outro lugar, como usar o comando unbuffer, mas isso não ajudou.

Alguém tem alguma idéia de como fazer isso funcionar como eu esperava? Ou ideias para esperar pelo início bem-sucedido do Tomcat (pensando em esperar por uma porta TCP saber que ela foi iniciada, mas suspeite que isso se tornará mais complexo do que estou tentando fazer agora). Eu consegui trabalhar com o awk fazendo um "killall tail" no jogo, mas não estou feliz com essa solução. Observe que estou tentando fazer com que isso funcione no RHEL4.

    
por Patrick 21.12.2010 / 03:01

3 respostas

5

Algo parecido com isto?

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

na íntegra:

#!/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 ser executado em 20 segundos.

$ time ./test2.sh

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

UPDATE

Este caminho parece funcionar também:

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

E se você estiver vendo sair imediatamente, tente adicionar um sleep 1, por exemplo

#!/bin/sh
rm -f child.out
./child.sh > child.out &
sleep 1
(tail -f child.out | grep -q B child.out)
    
por 21.12.2010 / 03:14
2

Tudo em uma linha, substitua 'do foo' por comando '

# service tomcat6 start
# tail -f /var/log/tomcat6/catalina.out | awk '/Server startup/{system("do foo"); exit 0}'
    
por 24.06.2012 / 02:49
1

Perca a cauda. Desde que você começa com uma criança vazia. Você não precisa dela e (como você descobriu) complica as coisas. Apenas grep para a primeira instância em um loop de sono.

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

Se você precisa manter a cauda porque nem sempre começa com uma catalina.out vazia, coloque a cauda dentro do loop:

until tail child.out| fgrep -q "Server startup"; do sleep 1; done
    
por 24.06.2012 / 07:56