Jak czytać logi systemowe, żeby szybko znaleźć przyczynę problemu

0
3
Rate this post

Nawigacja:

Po co w ogóle zaglądać do logów i czego się z nich dowiesz

Log jako czarna skrzynka systemu

Logi systemowe to czarna skrzynka każdego serwera, aplikacji i systemu operacyjnego. Rejestrują, co się wydarzyło, kiedy, przez kogo i z jakim skutkiem. Bez nich diagnoza problemu szybko zamienia się w zgadywanie.

Typowy serwer zapisuje w logach m.in.:

  • starty i zatrzymania usług (np. restart serwera www),
  • błędy aplikacji i systemu (brak pliku, błąd połączenia z bazą, wyjątki),
  • próby logowania i autoryzacji (udane i nieudane),
  • informacje o zasobach (dysk, pamięć, sieć),
  • ostrzeżenia bezpieczeństwa (nieudane logowania, próby exploitów).

Bez zrozumienia logów trudno odpowiedzieć na proste pytanie: co dokładnie się wydarzyło tuż przed awarią.

Jakie problemy da się rozwiązać wyłącznie przez analizę logów

Są sytuacje, w których system „działa”, ale coś jest wyraźnie nie tak. Interfejs www się ładuje, ale część akcji kończy się błędem. Użytkownik zgłasza, że „czasem się wylogowuje”, a ty nie możesz tego odtworzyć na zawołanie. W takich przypadkach logi często są jedynym źródłem konkretów.

Przykładowe problemy, które najczęściej rozwiązuje się patrząc w logi:

  • aplikacja nie odpowiada, ale serwer jest „up” – log serwera www wskaże błędy 5xx lub timeouty do backendu,
  • po wdrożeniu nowej wersji pojawiają się losowe błędy – log aplikacyjny pokaże stack trace z konkretną linią kodu,
  • użytkownicy nie mogą się zalogować – log autoryzacji pokaże powód odrzucenia,
  • system nagle zwolnił – logi bazy lub systemu pokażą błędy I/O, blokady, przeciążenie,
  • podejrzenie ataku – logi SSH, serwera www lub WAF pokażą adresy IP i wzorce prób.

Zamiast „działa / nie działa” dostajesz konkretny komunikat: Connection refused, permission denied, disk quota exceeded – to już są wskazówki do działania, a nie ogólne odczucia.

Intuicja kontra diagnostyka oparta na logach

Przy braku nawyku zaglądania do logów typowy przebieg wygląda tak: ktoś zgłasza problem, ktoś inny klika po interfejsie i próbuje go odtworzyć, po czym mówi „u mnie działa” albo „pewnie coś z internetem użytkownika”. To strata czasu.

Porównanie dwóch podejść:

Podejście intuicyjnePodejście oparte na logach
„Może padła baza?”Sprawdzenie błędów połączenia w logu aplikacji/bazy
„Chyba serwer jest wolny”Sprawdzenie timeoutów, błędów I/O, ostrzeżeń o zasobach
„To pewnie błąd użytkownika”Weryfikacja w logu, czy i z jakim kodem żądanie zostało obsłużone

Im szybciej nauczysz się sięgać po logi jako pierwsze źródło, tym mniej czasu zmarnujesz na zgadywanie, a więcej na realne rozwiązanie problemu.

Kiedy logi nie wystarczą

Logi nie są magicznym narzędziem, które odpowie na każde pytanie. Są sytuacje, w których okażą się zbyt ogólne albo po prostu „milczą”.

Najczęstsze przypadki, gdy trzeba sięgnąć po inne narzędzia:

  • brak błędów, a system jest wolny – potrzebne będą metryki z monitoringu (CPU, RAM, I/O, sieć),
  • brak logów z kluczowego komponentu – trzeba włączyć logowanie lub podnieść poziom szczegółowości (DEBUG),
  • wyjątki w kodzie bez stack trace – pomocne będą profilery, debugery, testy jednostkowe,
  • problemy z wydajnością na poziomie SQL – potrzebny profil SQL, EXPLAIN i monitoring bazy.

Logi dają obraz „co” i „kiedy”. „Dlaczego” czasem wymaga dodatkowych narzędzi, ale bez logów trudno w ogóle zlokalizować punkt startowy.

Dwie kobiety omawiają procesy API, notując schemat na białej tablicy
Źródło: Pexels | Autor: ThisIsEngineering

Podstawowe pojęcia: co właściwie znajduje się w logach

Struktura pojedynczego wpisu logu

Typowy wpis w logu ma stałą strukturę, którą warto rozpoznawać w locie. Przykład wpisu z logu systemowego:

2026-02-03T10:12:45Z my-hostname sshd[1234]: Failed password for user johndoe from 192.0.2.10 port 54321 ssh2

Kluczowe elementy:

  • timestamp – znacznik czasu: 2026-02-03T10:12:45Z,
  • host – nazwa maszyny: my-hostname,
  • proces / źródło – np. sshd[1234],
  • poziom – czasem jawny (INFO/ERROR), czasem zakodowany w formacie,
  • treść – opis zdarzenia: co się stało i z jakimi parametrami,
  • identyfikatory – użytkownik, IP, port, identyfikator żądania.

Na początku trzeba trenować oko: znaleźć najpierw czas, potem poziom/źródło, a dopiero na końcu czytać treść. To przyspiesza przeglądanie tysięcy linii.

Poziomy logowania w praktyce

Większość systemów i bibliotek używa podobnego zestawu poziomów logowania:

  • DEBUG – bardzo szczegółowe informacje techniczne, głównie dla programistów,
  • INFO – normalne informacje o działaniu (start, stop, udane operacje),
  • WARN (WARNING) – coś jest podejrzane, ale jeszcze nie jest to błąd,
  • ERROR – konkretna operacja się nie powiodła, ale system działa dalej,
  • FATAL lub CRITICAL – poważny błąd, po którym proces może się zatrzymać.

Proste zasady pracy z poziomami:

  • przy „nagłej awarii” zaczynaj od ERROR/FATAL,
  • przy sporadycznych problemach (czasem działa, czasem nie) – przejrzyj WARN i ERROR,
  • przy dziwnych, trudnych do odtworzenia błędach – poproś o włączenie DEBUG w krótkim oknie czasowym.

DEBUG generuje ogromną ilość logów, dlatego nie włącza się go na stałe na produkcji, ale bywa niezbędny przy głębokiej diagnozie.

Rodzaje logów: systemowe, serwerowe, aplikacyjne, bezpieczeństwa

Logi różnią się zakresem odpowiedzialności. Kilka podstawowych kategorii:

  • logi systemowe – jądro systemu, sterowniki, usługi systemowe (np. syslog, kern.log),
  • logi serwerowe – serwer www (Apache, Nginx), serwer bazy danych (PostgreSQL, MySQL), proxy,
  • logi aplikacyjne – samej aplikacji (backend, microserwisy, workerzy),
  • logi bezpieczeństwa – logowania, uprawnienia, SELinux, firewall (np. auth.log, logi SSH).

Przy konkretnym błędzie trzeba z grubsza wiedzieć, który rodzaj logu jest najbardziej prawdopodobnym źródłem odpowiedzi. Błąd HTTP 500? Najpierw log aplikacji i serwera www. Nieudane logowanie? Logi bezpieczeństwa i aplikacyjne.

Tekstowe a strukturalne logi

Starsze systemy zapisują logi w formie czystego tekstu. Nowocześniejsze rozwiązania idą w stronę logów strukturalnych, np. JSON:

{"time":"2026-02-03T10:12:45Z","level":"ERROR","service":"api","user_id":42,"path":"/login","message":"Database timeout"}

Dla początkującego logi tekstowe są prostsze w czytaniu „na oko”, ale logi strukturalne mają dużą przewagę, gdy trzeba je filtrować i analizować narzędziami (Elasticsearch, Splunk, Loki). Kluczowe plusy logów strukturalnych:

  • łatwe filtrowanie po polach (np. user_id, path, level),
  • spójny format, niezależnie od tego, jak programista napisał komunikat,
  • łatwiejsza korelacja zdarzeń z wielu usług.

Nawet jeśli dziś przeglądasz logi głównie w konsoli, z czasem warto dążyć do bardziej strukturalnego podejścia.

Gdzie szukać logów: lokalizacja i podstawowe narzędzia

Typowe ścieżki logów w systemach Linux

Na większości dystrybucji Linux logi tekstowe lądują w katalogu /var/log/. Kilka kluczowych plików:

  • /var/log/syslog lub /var/log/messages – ogólne logi systemowe,
  • /var/log/auth.log lub /var/log/secure – uwierzytelnianie, SSH, sudo,
  • /var/log/kern.log – logi jądra systemu,
  • /var/log/dmesg – komunikaty z bootowania i sterowników,
  • /var/log/nginx/, /var/log/apache2/ – logi serwerów www (access.log, error.log).

Dobrym nawykiem jest przejrzenie zawartości /var/log na każdym nowym serwerze i zorientowanie się, co jest gdzie:

ls -R /var/log

Sam przegląd nazw podpowie, z czego możesz skorzystać przy diagnozie (np. osobne logi dla konkretnej aplikacji).

systemd i journalctl – nowy sposób logowania

W systemach z systemd większość logów trafia do dziennika systemowego, dostępnego przez journalctl. To zmienia podejście: zamiast wielu plików tekstowych masz centralny dziennik z filtrami.

Podstawowe komendy:

  • journalctl -xe – końcówka logu z dodatkowymi szczegółami (przydatne tuż po błędzie),
  • journalctl -u nginx – logi konkretnej jednostki (usługi),
  • journalctl -f – podgląd logów w czasie rzeczywistym (jak tail -f),
  • journalctl --since "10 minutes ago" – logi z ostatnich 10 minut.

W środowiskach z systemd wiele błędów, które kiedyś trzeba było szukać w kilku plikach, dziś widać od razu w journalctl -xe po odtworzeniu problemu.

Gdzie znaleźć logi aplikacji

Aplikacje często mają własne logi poza /var/log. Gdy dokumentacja milczy, kilka prostych kroków zwykle wystarcza, by je znaleźć:

  • sprawdź plik konfiguracyjny (np. config.yml, application.properties, .env) – szukaj słów: log, logging, logfile,
  • przejrzyj katalog aplikacji (np. /opt/app/logs, /srv/app/log),
  • sprawdź zmienne środowiskowe (env | grep -i log),
  • zobacz konfigurację usługi w systemd: systemctl cat nazwa-uslugi – czasem komenda startowa zawiera parametry logowania.

Jeśli aplikacja jest uruchamiana z Dockera lub w Kubernetes, logi często zbiera się przez platformę (np. docker logs, narzędzia typu ELK, Loki). Zasada pozostaje ta sama: zawsze szukaj „źródła prawdy” dla danego komponentu.

Serwer vs. lokalna maszyna

Na serwerze produkcyjnym interesują cię głównie logi usług (nginx, baza, aplikacja) oraz systemu. Na lokalnym komputerze (laptop z Linuxem, macOS) dochodzą logi środowiska graficznego, sterowników, aplikacji użytkownika.

Różnice w praktyce:

  • na serwerze łatwiej powiązać błąd z konkretną usługą,
  • na desktopie często mieszają się logi wielu komponentów graficznych,
  • macOS i Windows używają własnych przeglądarek logów (Console, Event Viewer), choć część logów da się czytać z konsoli.

Jeśli zaczynasz naukę czytania logów, szybciej nauczysz się na serwerach Linux, gdzie wszystko jest spójniejsze i bardziej przewidywalne.

Zbliżenie ekranu komputera z kodem w ciemnym otoczeniu
Źródło: Pexels | Autor: luis gomes

Jak zacząć: prosty schemat analizy logów krok po kroku

Ustalenie ram czasowych problemu

Precyzyjne określenie momentu awarii

Najpierw trzeba odpowiedzieć na proste pytanie: kiedy problem się pojawił. Bez tego grozi ci przeglądanie godzin logów w ciemno.

Jeśli to możliwe, odtwórz problem i zanotuj dokładny czas (z dokładnością do minuty):

  • błąd w aplikacji webowej – zrób zrzut ekranu z widocznym zegarem systemowym lub zapisz sobie godzinę,
  • problem z cronem – sprawdź plan w crontab -l i notuj, o której godzinie wynik był zły,
  • restart usługi – spisz dokładny czas, gdy wydałeś systemctl restart lub gdy użytkownik zgłosił niedostępność.

Jeśli masz tylko informację typu „coś nie działało dziś rano”, użyj logów jako osi czasu – poszukaj charakterystycznych zdarzeń: restartów usług, deploymentów, zmian konfiguracji.

Powiązanie czasu problemu z czasem w logach

Czas w logach bywa w różnych strefach (UTC, lokalna) i formatach. Najpierw upewnij się, że patrzysz na tę samą perspektywę.

  • sprawdź strefę serwera: timedatectl lub porównanie z date,
  • zwróć uwagę, czy log używa UTC (często w formacie ISO z literą Z na końcu),
  • przy systemd journalctl domyślnie pokazuje czas lokalny, ale można przełączyć na UTC: journalctl --utc.

Jeśli czasy na ekranie użytkownika i w logach się nie zgadzają (np. różne strefy), przelicz jeden na drugi i zanotuj sobie prostą „mapę” typu: „10:05 czasu użytkownika = 09:05 UTC”. Przy długiej analizie oszczędza to sporo nerwów.

Zawężenie okna czasowego do minimum

Kiedy znasz orientacyjną godzinę problemu, ogranicz logi do możliwie wąskiego przedziału. Zamiast czytać cały dzień, wytnij kilka minut przed i po.

Przykłady dla logów tekstowych:

# logi z okolic 10:12 (5 minut przed i po) przy użyciu awk
awk '$0 >= "Feb  3 10:07" && $0 <= "Feb  3 10:17"' /var/log/syslog

Dla journalctl jest to prostsze:

journalctl --since "2026-02-03 10:07" --until "2026-02-03 10:17"

Przy braku dokładnego czasu zacznij szeroko (np. godzina), a potem sukcesywnie zawężaj okno, gdy znajdziesz pierwszy podejrzany wpis.

Identyfikacja kontekstu: użytkownik, IP, endpoint, host

Sam czas to za mało. W drugim kroku znajdź „haczyki”, które opisują konkretny przypadek:

  • login lub identyfikator użytkownika (np. user_id=42),
  • adres IP lub nazwa hosta klienta,
  • adres URL lub nazwa endpointu (/api/orders),
  • request ID / correlation ID, jeśli aplikacja go loguje.

Poproś użytkownika o dokładny URL, ewentualnie IP (np. z zakładki „szczegóły” w jego przeglądarce, jeśli potrafi), albo zajrzyj do logów access serwera www i znajdź jego żądanie po czasie i ścieżce:

grep "2026:10:12" /var/log/nginx/access.log | grep "/login"

Gdy znajdziesz jedno żądanie, wyciągnij z niego jak najwięcej parametrów (IP, user-agent, cookie z identyfikatorem sesji) i użyj ich do dalszego filtrowania.

Skanowanie logów „od końca”

Przy awarii usług dobrą taktyką jest patrzenie na log od końca, a nie od początku.

  • tail -n 200 /var/log/syslog – ostatnie 200 linii ogólnego logu,
  • tail -n 200 /var/log/nginx/error.log – ostatnie błędy serwera www,
  • journalctl -u nazwa-uslugi -n 200 – ostatnie linie dla usługi.

W wielu przypadkach objaw jest blisko przyczyny, szczególnie gdy proces po błędzie się wykrzacza. Oglądając końcówkę, szybko widzisz ostatnie ERROR-y i FATAL-e, a dopiero potem idziesz „w górę” logu, szukając pierwszego z serii.

Wyłuskanie pierwszego błędu w łańcuchu

Przy złożonych awariach często widzisz całą kaskadę błędów. Celem jest dojście do pierwszego, który je wywołał.

Przykład schematu:

  • aplikacja zgłasza „cannot connect to database”,
  • w logu bazy: „too many connections”,
  • w logu systemu: restart innego serwisu, który „pożera” połączenia.

Przy takim łańcuchu zapisuj sobie w notatkach krótką oś czasu: co, o której, na jakim komponencie. Dzięki temu nie gubisz się, przełączając się między plikami.

Jednoczesne przeglądanie kilku źródeł logów

Często potrzebujesz widoku na kilka logów naraz: np. nginx, aplikację i bazę. Najprościej zorganizować to w kilku panelach terminala lub w tmux czy screen.

Typowy układ:

  • panel 1 – tail -f /var/log/nginx/access.log,
  • panel 2 – tail -f /var/log/nginx/error.log,
  • panel 3 – journalctl -fu nazwa-aplikacji.

Odtwarzasz błąd i patrzysz, w jakiej kolejności pojawiają się wpisy. Nawet bez dokładnej analizy treści widać, kto reaguje jako pierwszy, a kto tylko raportuje skutek.

Odróżnianie szumu od sygnału

W każdym większym systemie znajdziesz logi, które „krzyczą” non stop, mimo że nic złego się nie dzieje. Przykład: ostrzeżenia o braku tłumaczeń, drobne timeouty retryowane automatycznie.

Podczas analizy konkretnego problemu:

  • ignoruj znane, stałe ostrzeżenia, które występują cały dzień z podobną częstotliwością,
  • skup się na nowych wpisach, które zaczęły się pojawiać tuż przed awarią,
  • zwróć uwagę na zmianę tempa – np. nagły wysyp tych samych ERROR-ów co sekundę.

Po kilku sesjach z logami zaczniesz rozpoznawać „codzienny szum”. Nowe wpisy będą się same wyróżniały.

Rośliny w probówkach podczas eksperymentu biotechnologicznego
Źródło: Pexels | Autor: Mikhail Nilov

Praca z narzędziami w konsoli: grep, less, tail, journalctl

Podstawowy arsenał: tail, less, grep

Te trzy narzędzia wystarczą, żeby wygodnie poruszać się po większości logów tekstowych.

  • tail – podgląd końcówki pliku i „śledzenie” nowych wpisów,
  • less – wygodne przeglądanie plików (scrollowanie, wyszukiwanie),
  • grep – filtrowanie linii zawierających szukany fragment.

Typowe wywołania:

# ostatnie 100 linii
tail -n 100 /var/log/syslog

# śledzenie na żywo
tail -f /var/log/syslog

# przeglądanie z możliwością przewijania
less /var/log/nginx/error.log

# wyszukiwanie hasła w pliku
grep "ERROR" /var/log/nginx/error.log

Efektywne korzystanie z less

less to nie tylko przewijanie w dół i w górę.

  • /tekst – wyszukiwanie w dół,
  • ?tekst – wyszukiwanie w górę,
  • n/N – następne/poprzednie wystąpienie,
  • G – skok na koniec pliku, g – skok na początek.

Przy dużych plikach lepiej połączyć grepa z less niż otwierać całość:

# pokaż tylko linie z ERROR i przeglądaj je w less
grep "ERROR" /var/log/app.log | less

Grep – szybkie filtrowanie po treści

grep to podstawowe narzędzie do zawężania logów po słowach kluczowych. W praktyce najczęściej używa się kilka przełączników:

  • -i – ignoruj wielkość liter,
  • -n – pokazuj numery linii,
  • -C N – pokaż kontekst, N linii przed i po dopasowaniu,
  • -v – negacja: pokaż linie nie pasujące do wzorca.

Przykłady z życia:

# znajdź wszystkie błędy krytyczne z kontekstem 3 linii
grep -iC 3 "fatal" /var/log/app.log

# pokaż logi użytkownika johndoe z auth.log
grep "johndoe" /var/log/auth.log

# wszystko poza wpisami health-check (szum)
grep -v "healthcheck" /var/log/nginx/access.log

Kombinowanie narzędzi: potoki

Narzędzia Unix najlepiej działają w łańcuchach. Zamiast pisać jedno skomplikowane polecenie, połącz kilka prostych.

# access.log: tylko błędy HTTP (kod 5xx) dla konkretnego endpointu
grep "/api/orders" /var/log/nginx/access.log | grep " 5[0-9][0-9] "

# logi z ostatniej godziny, tylko ERROR, wygodnie przeglądane
journalctl --since "1 hour ago" | grep "ERROR" | less

# śledzenie na żywo tylko wybranych wpisów
tail -f /var/log/app.log | grep "order_id=123"

Jeśli nie jesteś pewien efektu, uruchom najpierw pierwszy element potoku, zobacz wynik, potem dokładaj kolejne filtry.

Zaawansowane użycie grep i narzędzi pokrewnych

Gdy prosty grep nie wystarcza, wchodzą do gry wyrażenia regularne i dodatkowe narzędzia.

  • grep -E – włącza rozszerzone regexy:
# ERROR lub WARN (duże litery)
grep -E "ERROR|WARN" app.log

# błędy HTTP 500–504
grep -E " 50[0-4] " access.log
  • egrep – alias do grep -E (w nowszych systemach bywa oznaczany jako przestarzały),
  • fgrep lub grep -F – wyszukiwanie dosłowne, bez regexów (szybsze przy prostych ciągach).

Do bardziej złożonych transformacji przydaje się awk i sed, np. wycinanie konkretnych kolumn z logów access:

# z access.log nginx: wypisz tylko IP i kod odpowiedzi
awk '{print $1, $9}' /var/log/nginx/access.log | head

journalctl – filtrowanie dziennika systemd

journalctl to odpowiednik „kombajnu” do logów, ale jego podstawowe opcje da się zapamiętać w kilka minut.

  • -u nazwa-uslugi – logi konkretnej jednostki systemd,
  • -f – śledzenie w czasie rzeczywistym,
  • -n N – ostatnie N linii,
  • --since / --until – zawężenie czasowe.

Typowe scenariusze:

# logi usługi nginx z ostatnich 15 minut
journalctl -u nginx --since "15 minutes ago"

# śledzenie logów aplikacji
journalctl -fu my-app.service

# logi z konkretnego bootu systemu
journalctl -b

Filtry po polach w journalctl

Dziennik systemd przechowuje metadane, z których można korzystać w filtrach. Najprzydatniejsze:

  • SYSLOG_IDENTIFIER – nazwa procesu, który loguje,
  • _PID – identyfikator procesu,
  • _HOSTNAME – host, jeśli zbierasz logi z wielu maszyn.

Przykłady:

# logi konkretnego identyfikatora syslog
journalctl SYSLOG_IDENTIFIER=sshd

# logi danego procesu
journalctl _PID=1234

# logi sshd z ostatniej godziny, tylko błędy
journalctl SYSLOG_IDENTIFIER=sshd --since "1 hour ago" | grep -i "fail"

Łączenie journalctl z innymi narzędziami

journalctl można spokojnie łączyć z grep, less czy awk, tak jak zwykłe pliki.

# wygodne przeglądanie błędów nginx
journalctl -u nginx | grep -i "error" | less

# policz ile razy pojawił się dany komunikat
journalctl -u my-app.service | grep "connection refused" | wc -l

Jeśli chcesz później wrócić do analizy lub wysłać logi komuś innemu, zrzut z journalctl możesz przekierować do pliku:

Zapisywanie wycinków logów do dalszej analizy

Całego logu zwykle nie ma sensu kopiować. Wystarczy fragment, który pokazuje problem w kontekście.

Typowy schemat:

  • zawężasz logi w czasie (--since, --until albo sed -n 'A,Bp'),
  • filtrujesz po słowach kluczowych (grep, awk),
  • wynik przekierowujesz do pliku.
# wycinek dziennika z ostatnich 30 minut
journalctl --since "30 minutes ago" > /tmp/log-wycinek.txt

# tylko ERROR/WARN z app.log z kontekstem, do analizy
grep -iE -C3 "error|warn" /var/log/app.log > /tmp/app-error-context.log

Dobrze od razu w nazwie pliku zapisać system, usługę i przybliżony czas, np. web1-nginx-502-2024-02-03.log. Przy większej liczbie przypadków oszczędza to sporo czasu.

Kolorowanie i formatowanie logów dla czytelności

Przy długiej sesji z logami pomaga kolor.

Przykład z grep --color:

# podświetl słowo ERROR
grep --color=always -i "error" /var/log/app.log | less -R

Można też użyć narzędzi typu ccze czy lnav, które rozpoznają typ logu i kolorują poziomy logowania, daty, IP. Przy debugowaniu nginx czy apache różnica jest wyraźna.

Agregacja wielu plików logów naraz

Gdy masz rotowane logi (app.log, app.log.1, app.log.2.gz), szybciej jest potraktować je jako jeden strumień.

# przeglądanie bieżącego i poprzedniego pliku
zcat -f /var/log/app.log* | grep -i "fatal" | less

zcat -f sam zrozumie pliki .gz i zwykłe. Dzięki temu widzisz całą historię błędu, który zaczął się np. wczoraj przed rotacją.

Jak filtrować i zawężać logi, żeby nie utonąć w danych

Filtrowanie po czasie jako pierwszy krok

Najsilniejszy filtr to czas. Bez niego łatwo obejrzeć tysiące nieistotnych linii.

Jeśli znasz przybliżony moment problemu, wytnij godzinę przed i po:

# wpisy od 10:00 do 11:00
journalctl --since "2024-02-03 10:00" --until "2024-02-03 11:00"

# z pliku tekstowego (przy formacie z datą na początku linii)
sed -n '10000,12000p' /var/log/app.log | grep -i "error"

Przy logach tekstowych czasem prościej skorzystać z awk, jeśli data jest w pierwszej kolumnie:

# przykładowy format: 2024-02-03 10:15:23 ...
awk '$1=="2024-02-03" && $2>="10:00:00" && $2<="11:00:00"' app.log

Filtrowanie po poziomach i słowach kluczowych

Większość loggerów ma poziomy: DEBUG, INFO, WARN, ERROR, FATAL.

Przy incydencie zwykle wystarczą WARN/ERROR/FATAL:

# tylko ważniejsze poziomy
grep -E "WARN|ERROR|FATAL" app.log

# w journalctl - często poziomy są w treści lub w polu PRIORITY
journalctl -u my-app.service | grep -E "ERROR|CRITICAL"

Jeśli logi są hałaśliwe, dokładniej określ kontekst błędu:

# problem z bazą
grep -i "database" app.log | grep -i "timeout"

# błędy HTTP 500 przy konkretnym endpointcie
grep "/api/login" access.log | grep " 500 "

Wycinanie szumu za pomocą negacji

Silny wzorzec to „wszystko poza…”. Pozwala szybko pozbyć się znanych, niegroźnych komunikatów.

# wszystko poza healthcheckami
grep -v "healthcheck" access.log

# usuń DEBUG i INFO, zostaw resztę
grep -vE "DEBUG|INFO" app.log

Negację można łączyć w kilka etapów. Najpierw wyrzucasz healthchecki, potem metryki, na końcu np. znane, nieistotne WARN-y.

Grupowanie po polach i szukanie powtarzających się wzorców

Przy dużej liczbie podobnych wpisów liczy się coś innego: ile razy i dla czego to się dzieje.

# najczęstsze IP w access.log
awk '{print $1}' access.log | sort | uniq -c | sort -nr | head

# najczęstsze komunikaty błędów
grep -i "error" app.log | cut -d '|' -f3 | sort | uniq -c | sort -nr | head

Tak szybko widzisz np. jednego klienta, który generuje większość 500-ek, albo jeden typ wyjątku, który zalewa log.

Łączenie filtrów: czas + komponent + treść

Filtry działają najlepiej w zestawie. Na przykład:

# logi usługi z konkretnego okna czasowego, tylko błędy logowania
journalctl -u my-app.service 
  --since "2024-02-03 09:00" --until "2024-02-03 10:00" 
  | grep -i "login" | grep -iE "error|fail"

Lub w plikach tekstowych:

# nginx: 5xx dla /api/payments w danym dniu
grep "2024-02-03" access.log 
  | grep "/api/payments" 
  | grep " 5[0-9][0-9] "

Trzy–cztery proste filtry zwykle dają lepszy efekt niż jedno bardzo skomplikowane wyrażenie regularne.

Ograniczanie rozmiaru danych przy śledzeniu na żywo

Przy tail -f łatwo patrzeć na tysiące wpisów, z których większość jest nieistotna.

Rozwiązanie: filtruj już na wejściu:

# śledź tylko ERROR-y
tail -f /var/log/app.log | grep -i "error"

# journalctl + filtr treści
journalctl -fu my-app.service | grep -i "timeout"

Jeśli filtr jest zbyt agresywny, chwilowo go wyłącz (np. usuń grep) i złap kilka sekund „pełnego” strumienia dla porównania.

Wykrywanie anomalii po tempie logowania

Niektóre problemy widać nie po treści, tylko po tempie wpisów.

Prosty sposób: policz linie w krótkich oknach czasowych.

# ile wpisów na minutę
awk '{print substr($0,1,16)}' app.log | sort | uniq -c | sort -nr | head

Przy sporych skokach (np. z kilku wpisów na minutę do setek) często widać początek lawiny błędów albo niekończące się retry.

Budowanie prostych „presetów” filtrów

Jeżeli wracasz do tych samych wzorców filtracji, nie wpisuj wszystkiego ręcznie co każde zdarzenie.

Przykład prostego aliasu w ~/.bashrc:

# logi app: ostatnie 30 minut, tylko ERROR/WARN
alias app-logs='journalctl -u my-app.service --since "30 minutes ago" | grep -E "ERROR|WARN"'

Takie aliasy szybko zamieniają się w twoją mini-bibliotekę „presetów” do analizy logów, którą da się przenosić między serwerami.

Najczęściej zadawane pytania (FAQ)

Jak zacząć czytać logi systemowe, żeby szybko coś z nich wyciągnąć?

Na początek w każdym wpisie szukaj trzech elementów w tej kolejności: czasu (timestamp), źródła (proces/usługa) i poziomu (INFO/WARN/ERROR). Dopiero potem czytaj treść komunikatu.

Przykład: w linijce z błędem logowania najpierw sprawdzasz godzinę, potem czy to sshd, nginx czy aplikacja, a na końcu widzisz „Failed password” lub „Permission denied”. Taki schemat mocno przyspiesza przeglądanie dużych plików.

Gdzie w Linuksie znaleźć podstawowe logi systemowe i bezpieczeństwa?

Na większości serwerów logi tekstowe są w katalogu /var/log/. Najczęściej używane pliki to m.in. /var/log/syslog lub /var/log/messages (ogólne logi systemowe) oraz /var/log/auth.log lub /var/log/secure (logowania, SSH, sudo).

Dodatkowo zwykle znajdziesz tam katalogi z logami serwera www, np. /var/log/nginx/ lub /var/log/apache2/ (pliki access.log i error.log). Na nowej maszynie dobrze jest po prostu zrobić ls -R /var/log i zobaczyć, co jest dostępne.

Jakie problemy da się rozwiązać tylko na podstawie logów?

Logi są kluczowe, gdy problem jest „losowy” albo trudny do odtworzenia na żądanie. Przykład: użytkownik twierdzi, że „czasem go wylogowuje”, a u ciebie wszystko działa poprawnie.

Typowe przypadki to m.in. losowe błędy 5xx po wdrożeniu nowej wersji, problemy z logowaniem użytkowników, nagłe spowolnienie systemu bez oczywistej awarii czy podejrzenie ataku (np. masowe próby logowania po SSH). W takich sytuacjach tylko logi pokazują konkretny komunikat i dokładny moment zdarzenia.

Jak odróżnić ważne wpisy w logach od „szumu”?

Najprościej filtrować po poziomie logowania. Przy awarii zacznij od ERROR i FATAL/CRITICAL, przy dziwnych, sporadycznych problemach dorzuć WARN. INFO i DEBUG czytaj dopiero wtedy, gdy potrzebujesz kontekstu.

Jeśli używasz narzędzi typu grep lub systemów logowania (np. Elasticsearch), filtruj po polach level, service, user, path. To pozwala szybko odsiać normalne komunikaty start/stop od faktycznych błędów.

Co zrobić, gdy logi nic nie pokazują, a system nadal ma problem?

Jeśli nie ma błędów, a system jest wolny, przyda się monitoring zasobów: CPU, RAM, dysk, sieć. To już rola Prometheusa, Grafany lub choćby top, iotop, vmstat. Logi mówią „co i kiedy”, ale nie zawsze wyjaśniają przyczynę.

Gdy brakuje wpisów z kluczowej usługi, sprawdź konfigurację logowania i poziom szczegółowości (czasem trzeba włączyć DEBUG na krótki czas). Przy problemach z SQL pomogą profilery zapytań, EXPLAIN i monitoring bazy, bo same logi aplikacyjne mogą być zbyt ogólne.

Po czym poznać, czy patrzeć w logi systemowe, serwera czy aplikacji?

Dobierz log do objawu. Błąd HTTP 500 lub 504? Najpierw logi serwera www (error.log) i log aplikacyjny. Nieudane logowanie użytkownika? Sprawdź logi bezpieczeństwa (auth.log, SSH) oraz log aplikacji, jeśli logika logowania jest po jej stronie.

Problemy z wydajnością lub nagłym „muleniem” to często domena logów bazy danych (błędy I/O, blokady, długie zapytania) oraz logów systemowych (ostrzeżenia o dysku, pamięci, sieci). Z czasem wyrobisz sobie skojarzenia: „HTTP 5xx → www + aplikacja”, „podejrzenie ataku → SSH/WAF/auth.log”.

Czym różnią się logi tekstowe od strukturalnych (np. JSON) i które są lepsze dla początkującego?

Logi tekstowe to zwykłe linie tekstu, często łatwiejsze do szybkiego przeczytania w terminalu. Logi strukturalne (np. JSON) mają pola typu time, level, service, user_id, message, dzięki czemu świetnie nadają się do filtrowania i analizy narzędziami.

Dla osoby początkującej czytanie „na oko” zwykle jest prostsze w formacie tekstowym. W większych systemach logi strukturalne wygrywają, bo pozwalają w kilka sekund przefiltrować miliony wpisów po użytkowniku, endpointzie czy poziomie błędu.

Poprzedni artykułKamerka internetowa do pracy zdalnej: jak wybrać, by wyglądać i brzmieć lepiej
Zbigniew Kowalski
Zbigniew Kowalski przygotowuje testy i recenzje sprzętu: od routerów i dysków po laptopy i akcesoria. Opiera się na powtarzalnych procedurach, mierzalnych wynikach i porównaniach w podobnych warunkach, a nie na wrażeniach z pierwszego dnia. Zwraca uwagę na kulturę pracy, stabilność, aktualizacje firmware’u, serwis oraz opłacalność w dłuższym okresie. W recenzjach jasno oddziela fakty od opinii i opisuje, dla kogo dany sprzęt ma sens. Jego celem jest pomóc czytelnikowi kupić świadomie, bez przepłacania i bez rozczarowań.