Я пытаюсь настроить сценарий запуска, который запускает tomcat, отслеживает в catalina.out строку «Запуск сервера», а затем запускает другой процесс. Я пробовал различные комбинации tail -f с grep и awk, но пока ничего не работает. Основная проблема, с которой я столкнулся, заключается в том, чтобы заставить хвост умирать после того, как 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 секунд, однако хвосту потребуется еще 40 секунд, чтобы умереть. Я понимаю, почему это происходит - tail заметит, что канал пропал, только когда он пишет в него, что происходит только тогда, когда данные добавляются в файл. Это усугубляется тем фактом, что tail должен буферизовать данные и выводить символы B и C как одну запись (я подтвердил это с помощью strace). Я попытался исправить это с помощью решений, которые нашел в другом месте, например, с помощью команды unbuffer, но это не помогло.
У кого-нибудь есть идеи, как заставить это работать, как я этого ожидаю? Или идеи для ожидания успешного запуска Tomcat (подумайте о том, чтобы дождаться, пока порт TCP узнает, что он запущен, но подозреваю, что это станет более сложным, чем то, что я пытаюсь сделать сейчас). Мне удалось заставить его работать с awk, выполняющим "killall tail" при совпадении, но я не доволен этим решением. Примечание. Я пытаюсь заставить это работать на RHEL4.
Что-то вроде этого?
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)
И если вы иногда видите, что он немедленно завершается, попробуйте добавить сон 1, т.е.
#!/bin/sh
rm -f child.out
./child.sh > child.out &
sleep 1
(tail -f child.out | grep -q B child.out)
Все в одной строке замените do foo на command
# service tomcat6 start # tail -f /var/log/tomcat6/catalina.out | awk '/Server startup/{system("do foo"); exit 0}'
Терять хвост. Поскольку вы начинаете с пустого 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