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.

Zainteresował Cię ten artykuł i chcesz dowiedzieć się więcej o automatyzacji z wykorzystaniem języka Python lub innych narzędzi? Koniecznie sprawdź portal Szkoła DevNet prowadzony przez Piotra, a także z przygotowanymi przez niego szkoleniami on-line (https://showroute.pl/edu/) między innymi z automatyzacji z wykorzystaniem Python i Ansible.