Я пытаюсь настроить скрипт запуска, который будет запускать tomcat, отслеживать catalina.out на наличие строки "Server startup", а затем запускать другой процесс. Я пробовал различные комбинации tail -f с grep и awk, но пока ничего не работает. Основная проблема, с которой я сталкиваюсь, заключается в принудительном завершении tail после того, как grep или awk сопоставили строку.
Я упростил тестовый пример до следующего.
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
Поведение, которое я наблюдаю, заключается в том, что grep завершается через 20 секунд, однако tail потребуется еще 40 секунд, чтобы умереть. Я понимаю, почему это происходит — tail заметит, что канал исчез, только когда он запишет в него, что произойдет только тогда, когда данные будут добавлены в файл. Это усугубляется тем фактом, что tail должен буферизировать данные и выводить символы B и C как одну запись (я подтвердил это с помощью strace). Я пытался исправить это с помощью решений, которые нашел в другом месте, например, с помощью команды unbuffer, но это не помогло.
У кого-нибудь есть идеи, как заставить это работать так, как я ожидаю? Или идеи, как дождаться успешного запуска Tomcat (думаю о том, чтобы дождаться, пока порт TCP узнает, что он запущен, но подозреваю, что это станет сложнее, чем то, что я пытаюсь сделать сейчас). Мне удалось заставить это работать с помощью awk, выполняющего "killall tail" при совпадении, но меня это решение не устраивает. Обратите внимание, что я пытаюсь заставить это работать на RHEL4.
решение1
Что-то вроде этого?
mkfifo child.fifo
tail -f child.out > child.fifo &
pid=$!
grep -q B child.fifo && kill $pid
в полном объеме:
#!/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
Кажется, это занимает 20 секунд.
$ time ./test2.sh
real 0m20.156s
user 0m0.033s
sys 0m0.058s
ОБНОВЛЯТЬ
Кажется, этот способ тоже работает:
#!/bin/sh
rm -f child.out
./child.sh > child.out &
(tail -f child.out | grep -q B child.out)
И если вы видите, что иногда он немедленно завершает работу, попробуйте добавить sleep 1, т.е.
#!/bin/sh
rm -f child.out
./child.sh > child.out &
sleep 1
(tail -f child.out | grep -q B child.out)
решение2
Все в одной строке, замените «do foo» на «command»
# запуск службы tomcat6 # tail -f /var/log/tomcat6/catalina.out | awk '/Запуск сервера/{system("do foo"); выход 0}'
решение3
Отбросьте хвост. Поскольку вы начинаете с пустого child.out, он вам не нужен и (как вы обнаружили) это усложняет ситуацию. Просто выполните grep для первого экземпляра в цикле сна.
until fgrep -q "Server startup" child.out; do sleep 1; done
Если вам действительно нужно сохранить хвост, поскольку вы не всегда начинаете с пустого catalina.out, поместите хвост внутрь цикла:
until tail child.out| fgrep -q "Server startup"; do sleep 1; done