Porównaj ceny domen i usług IT, sprzedawców z całego świata

jak napisać skrypt, który działa tylko na nowych wpisach dziennika


Czuję, że powinno to być łatwe, ale trudno mi to zrozumieć.
Próbuję napisać skrypt, który będzie monitorował jeden z plików dziennika Apache i podejmował określone działania. Ale jak mogę śledzić plik dziennika?
Za każdym razem, gdy w dzienniku zapisywany jest nowy wiersz, chcę, aby ten wpis był sprawdzany, aby sprawdzić, czy pasuje do tego, czego szukam, a jeśli tak, to x się dzieje. Kiedy robię to ręcznie, użyłem kota lub ogona -f. Nie chcę uruchamiać skryptu co 30 sekund przez cron i przeglądać cały dziennik (lub nawet ostatnie 5 wierszy), dowiedzieć się, które z tych wierszy są nowe od czasu ostatniego uruchomienia skryptu, a potem trochę rzeczy .
Czy istnieje sposób sprawdzenia, czy jest tylko jeden nowy wpis w dzienniku?
Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Możesz użyć już dostępnych narzędzi Linuksa, takich jak
         tail
,
         grep
i
         named pipes
... Najpierw utwórz nazwany potok (FIFO) za pomocą:
$ mkfifo/tmp/myfifo

Po drugie, utwórz prosty skrypt, który czyta z tego pliku FIFO. Oto prosty przykład:
#!/bin/bash
pipe=/tmp/myfifowhile true
do
if read line <$pipe; then
if [[ "$line" == 'quit' ]]; then
break
fi
echo $line
fi
done
echo "Reader exiting"

Ten skrypt czyta z nazwanego potoku i wypisuje wiersz na standardowe wyjście, dopóki nie otrzyma słowa „wyjście”. To tylko przykład, który można dostosować.
Po trzecie, użyj
         tail
aby przeczytać nowe wiersze dodane do pliku dziennika Apache i przekierować dane wyjściowe do nazwanego potoku.
$ tail -n0 -F/var/log/apache2/access.log | grep some_text >/tmp/myfifo

W
         -F
opcja oznacza śledzenie pliku po nazwie, co powinno uczynić go odpornym na logrotate. W związku z tym zawsze będzie mieć tę samą nazwę pliku. W
         -n0
oznacza nie otrzymanie starego sznurka. W
         grep
przydatne jest kierowanie tylko pasujących linii.
Korzystając z tego rozwiązania, nie potrzebujesz żadnego zadania cron. Po prostu uruchom skrypt i powyższe polecenie tail.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Uruchamianie skryptu przez cron, ale przy użyciu
         logtail
lub
           logtail2
http://linux.die.net/man/8/logtail2
czytanie pliku pozwoli uniknąć czytania całego pliku co minutę. Logtail śledzi, gdzie ostatnio czytał i przeskakuje do tego punktu przy następnym użyciu.
Jeśli chcesz pracować nad nowymi wierszami dziennika, zamiast czekać 59 sekund między wywołaniami crona, będziesz musiał użyć
         tail -f
lub podobne.
Odpowiedzi Janne i Khaleda dobrze rozwiązują ten problem.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Jeśli masz
         syslog-ng
(prawdopodobnie
         rsyslogd
zrobi też) jako demon syslog, możesz tego użyć.
Po prostu skonfiguruj go, aby obserwował plik dziennika Apache, lub alternatywnie skonfiguruj Apache, aby wysyłał dzienniki do narzędzia syslog za pomocą
         CustomLog
dyrektywy i
         logger
.
Syslog-daemon użyje wtedy dopasowania wzorców i wykona $ foo, jeśli znajdzie jakieś dopasowanie. Na przykład w syslog-ng możesz ustawić przechwytywanie pliku dziennika i filtrowanie go w następujący sposób:
source apache_log { file("/var/log/apache2/access.log"); };
filter apache_match { match("GET/evilscript.php"); };

Następnie syslog-ng wywołuje zewnętrzny skrypt
destination apache_logmatch_script { program("/usr/local/bin/apachematch.pl"); };

Na koniec połącz to wszystko razem:
log { source(apache_log); filter(apache_match); destination apache_logmatch_script); };

Jeśli użyjesz tej techniki, syslog-ng utworzy tło twojego skryptu, czekając na pojawienie się nowego materiału. Z tego powodu musisz zmodyfikować swoje skrypty, aby oczekiwały danych wejściowych od STDIN; oto mały przykład w Perlu:
#!/usr/bin/perl -w$|=1;
while (<>) {
printf "Stuff happened, I got this entry: %s!\n", $_;
}

Nie będę zagłębiać się w moją odpowiedź, dopóki nie dowiem się, że chcesz wypróbować tę technikę.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Możesz napisać ostatnią przeczytaną linię. Przy każdym nowym początku czytaj od ostatniej linii + 1 do końca pliku i aktualizuj rekord.
Należy jednak pamiętać, że plik dziennika można obrócić. Musisz więc prowadzić rejestr, na przykład, numerów i-węzłów.
fail2ban
http://www.fail2ban.org/wiki/index.php/Main_Page
monitoruje pliki dziennika tak, jak myślisz. Możesz na to spojrzeć? Możesz pożyczyć kilka pomysłów lub z nich skorzystać.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Możesz użyć diff. Skopiuj plik dziennika do pliku tymczasowego.
Weźmy różnicę między plikiem dziennika na żywo a plikiem tymczasowym.
Uruchom dopasowywanie wzorców na wynikowym pliku różnicowym.
Pomysł zaczerpnięty z wtyczki nagios check_log. Widzieć

http://www.kilala.nl/Sysadmin/index.php?id=715
http://www.kilala.nl/Sysadmin/index.php?id=715
Więcej szczegółów.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Jeśli fail2ban nie odpowiada Twoim potrzebom, możesz spróbować zmienić

flog.c
http://pastebin.com/8hxSmTCE
które Marcus J. Ranum napisał:

„To małe narzędzie działa podobnie jak tail -f, ale jest wystarczająco inteligentne, aby obsługiwać zmiany plików, jeśli rotator dziennika przesunie plik spod użytkownika w czasie wykonywania. Ponadto, w przeciwieństwie do "tail -f", ten program jest wystarczająco inteligentny, aby zakończyć pracę, gdy użytkownik jest wylogowany (!) I nie będzie wypluwał dzienników na pty na zawsze. Nie podejmuje się żadnego wysiłku w celu uzyskania elegancji lub wydajności ”

Możesz zmodyfikować, aby sprawdzić, czy jakikolwiek znak nowej linii pasuje do żądanego wzorca i odpowiednio postępować.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Jeśli potrzebujesz rozwiązania w Pythonie, wypróbuj Pygtail:

https://github.com/bgreenlee/pygtail
https://github.com/bgreenlee/pygtail
Jest to oparte na
         logcheck
z
         logtail2
narzędzie
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

#!/bin/bashwhile read line;
do
echo $line >/tmp/output.log
mail -s 'Event Msg.' 'email@gmail.com' </tmp/output.log
done < <(tail -n0 -F/var/adm/messages)

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się