Использование цикла while
может работать в вашей ситуации, но имейте в виду, что не гарантировано поймать каждую строку файла журнала. Рассмотрим ситуацию, когда журнал писатель включает в себя одно действие, что выписывает две строки:
Something bad just happened:\nError xyz on line 22
Это очень вероятно, что ваш цикл будет видеть только вторую строку, когда он выполняет tail -1
действие.
Не только это, но реализация мертвой, а значит, ваш спиннинг процессора в цикле, постоянно стреляя tail
команды (обратите внимание на top
в то время как while
реализация работает, по сравнению с tail -f
).
This question имеет несколько хороших предложений, если вы просто хотите остановить мониторинг после согласования шаблона. (Обратите внимание на проблемы хвостового процесса, висящие вокруг.)
Это чудовище, вероятно, не оптимально, но оно ловит каждую линию, использует минимальный процессор в ожидании новых строк, завершает хвост, когда это делается, и дает вам гибкость для записи в некоторой дополнительной логике (например, при выполнении действий на основе разных совпадающих шаблонов):
watchPattern=$1
logFile=/var/log/named.log
logLine=""
while read -r logLine ; do
#Do we have a match?
if [[ "$logLine" == *"$watchPattern"* ]] ; then
#Confirmation message, written to console (for example, not needed)
echo "Found a match."
#Kill off the tail process (a bit of a hack that assumes one at a time)
kill $(ps -eo pid,command | awk -v pattern="tail -fn0 $logFile" '$0 ~ pattern && !/awk/ {print $1}')
#Get out of here
break
fi
done< <(exec tail -fn0 "$logFile")
#logLine will be the matched value
echo "match = $logLine"
Как я могу поместить это в скрипт? Я попытался сделать это таким образом, и это не отразится на выходе –
'tail -f file | grep ... 'никогда не выйдет, поэтому ваш оператор echo' никогда не выполняется. – larsks
'tail -f' выйдет, если файл исчезнет, но не хватает такого рода вещей, на котором он работает вечно. –