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 intuicyjne | Podejś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.

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/sysloglub/var/log/messages– ogólne logi systemowe,/var/log/auth.loglub/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 (jaktail -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.

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 -li notuj, o której godzinie wynik był zły, - restart usługi – spisz dokładny czas, gdy wydałeś
systemctl restartlub 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:
timedatectllub porównanie zdate, - zwróć uwagę, czy log używa UTC (często w formacie ISO z literą
Zna końcu), - przy systemd
journalctldomyś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.

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 dogrep -E(w nowszych systemach bywa oznaczany jako przestarzały),fgreplubgrep -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 | headjournalctl – 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,--untilalbosed -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 | headTak 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 | headPrzy 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.






