W poprzednim artykule pokazaliśmy prosty parser wpisów syslog. Zmodyfikujemy go teraz nieco by był bardziej użyteczny. Mianowicie udoskonalimy go w taki sposób, by zamiast czytać dane z pliku logi.txt śledził na bieżąco plik z logami tworzony przez proces sysloga. Całość odbywać się musi bez blokowania pliku, aby proces sysloga mógł nadal do niego zapisywać nowe dane. Na moim serwerze logi z monitorowanego urządzenia są zapisywane w dedykowanym pliku, który będę śledził.
Biblioteka tailer
Biblioteka tailer to narzędzie w języku Python przeznaczone do monitorowania plików tekstowych w czasie rzeczywistym. Jest szczególnie przydatna do analizy logów, gdzie pliki są stale uzupełniane o nowe wpisy. tailer umożliwia łatwe implementowanie funkcjonalności podobnych do poleceń tail i tail -f znanych z systemów Unix/Linux, oferując prosty interfejs do śledzenia końca pliku i przetwarzania nowych danych w miarę ich pojawiania się.
Funkcja tail umożliwia odczytanie określonej liczby ostatnich linii z pliku. Jest to odpowiednik polecenia tail w systemach Unix/Linux. Można określić, ile ostatnich linii ma zostać zwróconych. Funkcja follow to odpowiednik polecenia tail -f, które monitoruje plik w czasie rzeczywistym i pozwala na przetwarzanie nowych linii dodawanych do pliku. follow zwraca iterator, który można użyć w pętli, aby przetwarzać nowe linie w miarę ich pojawiania się. W naszym skrypcie wykorzystamy funkcję follow, gdyż chcemy śledzić nowe wpisy w pliku sysloga.
Biblioteka tailer pozwala również na bardziej zaawansowane operacje, takie jak określanie wielkości bufora do odczytu, co może być przydatne w przypadku bardzo dużych plików lub specyficznych wymagań dotyczących wydajności. Biblioteka ta nie jest częścią zestawu bibliotek standardowych języka Python, dlatego musimy ją dodatkowo samodzielnie zainstalować korzystając z managera pakietów pip.
Skrypt Python
Skrypt będzie analizował plik /var/log/c8000v/c8000v.log i wyszukiwał w nim konkretnej frazy: „%HA_EM-6-LOG: LOG_ALL_COMMANDS: Command Executed: configure terminal„. W przypadku wykrycia tej frazy, skrypt wyświetli na konsoli odpowiedni komunikat zawierający datę, godzinę oraz nazwę urządzenia. Skrypt otworzy plik sysloga w trybie umożliwiającym czytanie nowych linii, które są dodawane do pliku, bez blokowania jego zapisu przez proces syslog. Do monitorowania pliku w czasie rzeczywistym użyjemy opisanej wcześniej biblioteki tailer.
import tailer import re from datetime import datetime log_file_path = '/var/log/c8000v/c8000v.log' def parse_log_line(line): regex = r'(\w{3} \d{1,2} \d{2}:\d{2}:\d{2}) .* %HA_EM-6-LOG: LOG_ALL_COMMANDS: Command Executed: configure terminal' match = re.search(regex, line) if match: timestamp = match.group(1) log_datetime = datetime.strptime(timestamp, '%b %d %H:%M:%S') current_year = datetime.now().year log_datetime = log_datetime.replace(year=current_year) device_name = line.split()[3] return log_datetime, device_name return None def monitor_log_file(): for line in tailer.follow(open(log_file_path)): result = parse_log_line(line) if result: log_datetime, device_name = result print(f'O godzinie {log_datetime.strftime("%H:%M:%S")} dnia {log_datetime.strftime("%Y-%m-%d")} na urządzeniu {device_name} użytkownik przeszedł w tryb konfiguracji.') if __name__ == '__main__': monitor_log_file()
Skrypt otwiera plik logów i zaczyna monitorować nowe linie dodawane do pliku. Za każdym razem, gdy pojawi się nowa linia, funkcja parse_log_line() sprawdza, czy linia zawiera interesującą nas frazę. Jeśli tak, wyciąga datę i godzinę z linii logu oraz nazwę urządzenia. Następnie skrypt wyświetla komunikat na konsoli z odpowiednimi informacjami.
Wywołanie bloku kodu z warunkiem if __name__ == '__main__’ jest standardową praktyką w Pythonie, która pozwala na określenie, czy dany skrypt jest uruchamiany jako główny program, czy też jest importowany jako moduł do innego skryptu.
Metoda parse_log_line()
Metoda parse_log_line służy do przetwarzania pojedynczej linii logu, sprawdzania, czy zawiera ona interesującą nas frazę, oraz wyciągania z niej daty, godziny i nazwy urządzenia. Wywołujemy ją dla każdej nowej linii, która pojawi się w monitorowanym pliku z logami. Ponownie używamy wyrażeń regularnych, ale ponieważ w Pythonie zawsze jest więcej niż jeden sposób na rozwiązanie problemu pokażę Ci teraz inną metodę, ale nadal z zastosowaniem biblioteki re. W naszym przypadku używamy wyrażenia regularnego do identyfikacji linii logów zawierających specyficzne informacje.
Wyrażenie (\w{3} \d{1,2} \d{2}:\d{2}:\d{2}) odpowiada za wyłapanie daty i godziny z linii logu. \w{3} dopasowuje trzy znaki alfanumeryczne (np. skróty nazw miesięcy takie jak „Jan”, „Feb”). \d{1,2} dopasowuje dzień miesiąca (jedno- lub dwucyfrowy). \d{2}:\d{2}:\d{2} dopasowuje godzinę w formacie HH:MM. .* dopasowuje dowolną liczbę znaków (zero lub więcej) między datą a interesującą nas frazą. Następnie na koniec podajemy dokładną wyszukiwaną frazę.
Wyrażenie regularne wykorzystujemy w wywołaniu metody re.search(regex, line), która przeszukuje linię logu pod kątem dopasowania do wyrażenia regularnego. Jeśli dopasowanie zostanie znalezione, zmienna match będzie zawierać obiekt Match. timestamp = match.group(1) wyciąga dopasowany fragment odpowiadający za datę i godzinę. datetime.strptime(timestamp, '%b %d %H:%M:%S’) konwertuje ten fragment na obiekt datetime. datetime.now().year pobiera bieżący rok, zaś log_datetime.replace(year=current_year) aktualizuje obiekt datetime, ustawiając bieżący rok, ponieważ logi mogą nie zawierać informacji o roku. Wywołanie device_name = line.split()[3] dzieli linię na słowa i wyciąga czwarte słowo, które w naszym przypadku jest nazwą urządzenia. Jeśli linia zawiera interesującą nas frazę, metoda zwraca datę, godzinę i nazwę urządzenia. W przeciwnym razie zwraca None.
Śledzenie zmian w pliku
Metoda monitor_log_file() jest kluczową częścią naszego skryptu do analizy logów sysloga w czasie rzeczywistym. Jej głównym zadaniem jest ciągłe monitorowanie pliku logów, analizowanie nowych linii i wykrywanie momentów, gdy użytkownik przechodzi w tryb konfiguracji. Metoda rozpoczyna od otwarcia pliku logów, którego ścieżka została zdefiniowana jako log_file_path. Używamy tutaj funkcji open w trybie odczytu ('
r'
). Następnie przekazujemy ten plik do funkcji tailer.follow(), która zwraca iterator pozwalający na monitorowanie pliku w czasie rzeczywistym. Pętla for iteruje po każdej nowej linii dodawanej do pliku logów. Jak już wcześniej wspomniałem Funkcja tailer.follow() działa podobnie do polecenia tail -f w systemach Unix/Linux, co oznacza, że będzie czekać na nowe linie i przetwarzać je natychmiast po ich dodaniu.
Dla każdej nowej linii wywoływana jest opisana wcześniej funkcja parse_log_line(), która sprawdza, czy linia zawiera interesującą nas frazę. Jeśli linia zawiera szukaną frazę, parse_log_line() zwraca datę, godzinę i nazwę urządzenia. Jeśli linia nie zawiera frazy, zwraca None. Jeśli parse_log_line() zwróci wynik, to znaczy, że interesująca nas fraza została znaleziona. W takim przypadku result zawiera krotkę z dwoma elementami: log_datetime (data i godzina zdarzenia) oraz device_name (nazwa urządzenia).
Jeżeli fraza została znaleziona, skrypt wyświetla komunikat na konsoli, zawierający datę, godzinę i nazwę urządzenia. Formatowanie daty i godziny jest wykonywane za pomocą metody strftime, co pozwala na prezentację tych informacji w czytelny sposób.
Metoda monitor_log_file() zapewnia ciągłe monitorowanie pliku logów, analizując nowe linie w czasie rzeczywistym. Wykorzystuje funkcję tailer.follow() do śledzenia nowych wpisów w pliku bez blokowania procesu zapisu. Każda nowa linia jest analizowana za pomocą funkcji parse_log_line(), która sprawdza, czy linia zawiera interesującą nas frazę i wyciąga z niej odpowiednie informacje. Jeśli fraza zostanie znaleziona, skrypt wyświetla odpowiedni komunikat na konsoli, informując o przejściu użytkownika w tryb konfiguracji na urządzeniu sieciowym.
Zostaw komentarz
Musisz się zalogować lub zarejestrować aby dodać nowy komentarz.