2015-06-11 4 views
0

Я хотел бы создать скрипт, который greps для определенной строки в файле журнала, на который записывается. Я хотел бы взять первый результат и поместить его в переменную для последующего использования. Это будет использоваться, хотя соединение SSH так:Использование tail -f в файле журнала с grep в скрипте bash

ssh '[email protected]' 'bash -s' < /usr/local/bin/checklog.sh string 

Команда в обычном терминале

tail -f /var/log/named.log | grep $1 > $var 
echo "${var}" 

Когда я пытаюсь выше метод, нет нет Выход

+0

Как я могу поместить это в скрипт? Я попытался сделать это таким образом, и это не отразится на выходе –

+2

'tail -f file | grep ... 'никогда не выйдет, поэтому ваш оператор echo' никогда не выполняется. – larsks

+0

'tail -f' выйдет, если файл исчезнет, ​​но не хватает такого рода вещей, на котором он работает вечно. –

ответ

1

> $var не делает что вы думаете.
Он перенаправляет вывод предыдущей команды в файл с именем того, что содержит $var.
Чтобы записать вывод команды и поместить ее в переменную, используйте variableName="$(...)".

var="$(tail -f /var/log/named.log | grep $1)" 
-1

Благодарим вас за ввод. Вы помогли выяснить, лучший способ сделать это, используя время и хвост без -f

werd=$1 
var="" 
while [ "${var}" == "" ] 
do 
var=$(tail -1 /var/log/named.log | grep "${werd}"); 
done 
echo "${var}"; 

Это просто читает последнюю строку в файле. Поскольку файл записывается, последняя строка изменяется, что является результатом, который я искал.

+0

FYI, '==' недействителен в POSIX 'test' (aka' ['); единственным стандартно-гарантированным оператором сравнения строк является '='. –

+0

Это очень дорого с точки зрения производительности, кстати; Я не могу рекомендовать его другим, даже за пределами условий гонки (где он может пропустить линии, если их присоединяют достаточно быстро. –

1

Использование цикла 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" 
+0

Я мог бы считать 'read -r' вместо голого' read', чтобы избежать удаления символов обратной косой черты, и в то время как использование фигурных скобок не имеет никакой пользы, когда они не активно устраняют двузначное имя переменной, вам не хватает кавычек в тех местах, где они _до_ материи (предоставлено с именем файла журнала без пробелов или символов глобуса, они будут иметь значение только с странным значением для IFS, но это не является неслыханным для 'IFS = /' или что-то, что должно быть оставлено другим кодом). '' $ logFile "' следует использовать, чтобы избежать расширения разделов строк/glob. –

+0

Кроме того, в то время как я ношу свою шляпу педанта, 'echo '$ {logLine}" 'не будет делать правильную вещь для строки, которая содержит только' -e' (с GNU в отличие от POSIX 'echo') или' -n '. Кроме того, XSI-расширенное эхо-сообщение POSIX будет по-разному расширять последовательности обратного слэша-escape, которые вы, вероятно, не хотите. sider 'printf '% s \ n'" $ logLine "вместо этого - и просмотрите разделы ПРИМЕНЕНИЕ ИСПОЛЬЗОВАНИЕ И ОБОСНОВАНИЕ http://pubs.opengroup.org/onlinepubs/009604599/utilities/echo.html для интересного чтения. –

+0

Тем не менее, я только педант с этим ответом, потому что это действительно очень хороший. :) –