Parsowanie logów internetowych i aplikacyjnych na dużą skalę
Wyodrębniaj kody statusu, opóźnienia i pola klientów z logów dostępu za pomocą grep, cut i awk.
Parsowanie logów internetowych i aplikacyjnych na dużą skalę to bezpłatna lekcja Linux Command Line & Bash Scripting Mastery na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Linux Command Line & Bash Scripting Mastery, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Linux Command Line & Bash Scripting Mastery zawiera 4 lekcji w sumie.
Czym jest dziennik dostępu do witryny internetowej?
Każdy serwer HTTP — Apache, Nginx, Caddy — zapisuje w dzienniku dostępu jeden wiersz dla każdego żądania. Zrozumienie struktury tych wierszy jest podstawą wszelkiej analizy logów.
Typowy wiersz w Combined Log Format (CLF) wygląda tak:
- Adres IP klienta — kto wysłał żądanie
- Znacznik czasu — kiedy to nastąpiło
- Wiersz żądania — metoda, ścieżka, protokół
- Kod stanu — odpowiedź HTTP (200, 404, 500…)
- Wysłane bajty — rozmiar treści odpowiedzi
- Referer — strona źródłowa
- User-Agent — identyfikator przeglądarki lub bota
Przykładowy wiersz z pliku /var/log/nginx/access.log:
192.168.1.10 - alice [11/Jun/2026:14:32:01 +0000] "GET /api/orders HTTP/1.1" 200 1482 "-" "curl/7.88.1"
Przy dużej skali pliki te rozrastają się do milionów wierszy dziennie. Celem tej lekcji jest wydajne wyodrębnianie, filtrowanie i agregowanie zawartych w nich pól za pomocą standardowych narzędzi BASH.
Próbkowanie aktywnego logu za pomocą tail i grep
Zanim napiszesz jakikolwiek potok, przejrzyj log, aby zrozumieć jego strukturę. tail pozwala obserwować strumień na żywo, a grep od razu zawęża go do odpowiednich wierszy.
Typowe wzorce:
tail -n 1000 access.log— ostatnie 1000 wierszytail -f access.log— śledzenie w czasie rzeczywistymtail -f access.log | grep '" 5'— tylko błędy 5xx w miarę ich napływania
Najważniejszy wniosek jest taki, że grep dopasowuje wzorzec do całego wiersza, dlatego istotne jest zakotwiczenie wzorca. Dopasowanie ' 500 ' (ze spacjami) zapobiega przypadkowemu dopasowaniu ścieżki URL zawierającej ciąg 500.
#!/usr/bin/env bash
# Watch only HTTP 5xx errors arriving in real time
tail -f /var/log/nginx/access.log \
| grep --line-buffered '" 5[0-9][0-9] 'Wyodrębnianie kodu stanu za pomocą cut
cut dzieli każdy wiersz według separatora i wyświetla wybrane pola. W formacie Combined Log Format kod stanu znajduje się w polu 9 po podzieleniu według spacji, ale cudzysłowy otaczające wiersz żądania sprawiają, że bezpieczniej jest liczyć od znanego punktu odniesienia.
Niezawodny sposób polega na tym, że wiersz żądania jest zawsze ujęty w cudzysłowy, więc kod stanu jest zawsze pierwszym tokenem po zamykającym cudzysłowie pola żądania. Użycie cut -d'"' -f3 wyodrębnia wszystko po cudzysłowie żądania, a następnie drugie cut -d' ' -f2 wybiera kod stanu.
To dwuetapowe użycie cut jest klasycznym idiomem dla logów CLF — działa szybko i nie wymaga zewnętrznych zależności.
#!/usr/bin/env bash
# Print only the HTTP status code from each log line
# Input format: ... "GET /path HTTP/1.1" 200 1482 ...
cut -d'"' -f3 /var/log/nginx/access.log \
| cut -d' ' -f2 \
| sort \
| uniq -c \
| sort -rnZliczanie kodów stanu za pomocą awk
awk jest potężniejszy niż cut, ponieważ może zachowywać stan między kolejnymi wierszami. Idiomatyczny wzorzec zliczania wystąpień wykorzystuje tablicę asocjacyjną, której kluczem jest interesująca Cię wartość.
W CLF pole $9 (indeksowane od 1, rozdzielane spacjami) zawiera kod stanu. awk przetwarza każdy wiersz, zwiększa licznik, a następnie w bloku END wyświetla posortowane podsumowanie.
Dlaczego warto wybrać awk zamiast cut | sort | uniq -c? Ponieważ awk wykonuje całą operację w jednym przebiegu, bez wcześniejszego sortowania całego pliku — ma to kluczowe znaczenie, gdy log ma setki gigabajtów.
#!/usr/bin/env bash
# Count HTTP status codes in a single awk pass
awk '{ count[$9]++ }
END {
for (status in count)
printf "%6d %s\n", count[status], status
}' /var/log/nginx/access.log \
| sort -rnFiltrowanie błędów i wyodrębnianie adresów IP klientów
Jednym z najczęstszych zadań operacyjnych jest znalezienie adresów IP klientów generujących najwięcej błędów. Łączy to filtrowanie (tylko wiersze z błędami) z wyodrębnianiem pól (adres IP w polu 1).
Strategia budowy potoku:
- Użyj
awk, aby w jednym kroku filtrować zakres kodów stanu i wyodrębniać adres IP — unikaj osobnego przebiegugrep - Przekaż wynik do
sort | uniq -c | sort -rn | head, aby szybko wyświetlić pierwsze N wyników
Ten wzorzec jest wystarczająco szybki, aby przetworzyć na pojedynczym serwerze plik dziennika o rozmiarze 10 GB bez wczytywania go do pamięci.
#!/usr/bin/env bash
# Top 10 IPs generating HTTP 4xx or 5xx errors
awk '$9 ~ /^[45][0-9][0-9]$/ { print $1 }' \
/var/log/nginx/access.log \
| sort \
| uniq -c \
| sort -rn \
| head -10Analizowanie opóźnień odpowiedzi w logach aplikacji
Serwery aplikacji (Rails, Gunicorn, Express z morganem itp.) często zapisują czas trwania żądania. Nginx można skonfigurować tak, aby dopisywał $request_time jako dodatkowe pole na końcu każdego wiersza.
Przykład niestandardowego formatu logów Nginx w pliku nginx.conf:
log_format timed '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" rt=$request_time';
Gdy opóźnienie jest już zapisane w logu, możesz użyć awk do obliczenia średniej, maksimum i przybliżonych wartości percentyli dla milionów żądań bez wczytywania danych do bazy danych.
#!/usr/bin/env bash
# Compute average and max request_time from Nginx timed log
# Assumes last field is rt=<seconds> e.g. rt=0.042
awk '{
# Extract numeric value after rt=
n = split($NF, a, "=")
if (n == 2 && a[1] == "rt") {
t = a[2] + 0
sum += t
count++
if (t > max) max = t
}
}
END {
if (count > 0)
printf "Requests: %d Avg: %.4fs Max: %.4fs\n", count, sum/count, max
}' /var/log/nginx/timed_access.logTworzenie histogramu opóźnień za pomocą awk
Pojedyncza średnia ukrywa opóźnienia skrajne. Histogram pokazuje rozkład — informuje, czy większość żądań jest szybka, a tylko nieliczne bardzo wolne (długi ogon), czy też rozkład jest równomierny.
Sztuczka polega na przypisaniu każdej wartości do zaokrąglonego przedziału za pomocą arytmetyki całkowitoliczbowej wewnątrz awk. Pomnożenie przez 1000 (konwersja sekund na milisekundy), a następnie użycie dzielenia całkowitoliczbowego daje przejrzyste granice przedziałów.
Wynikiem jest tekstowy histogram, który można odczytać bezpośrednio w terminalu. Często jest to szybsze niż przesyłanie danych do Grafany podczas szybkiego badania problemu.
#!/usr/bin/env bash
# Latency histogram (50ms buckets) from Nginx timed log
awk '{
n = split($NF, a, "=")
if (n == 2 && a[1] == "rt") {
ms = int(a[2] * 1000) # convert to ms
bucket = int(ms / 50) * 50 # round down to 50ms boundary
hist[bucket]++
}
}
END {
for (b in hist)
printf "%6dms %d\n", b, hist[b]
}' /var/log/nginx/timed_access.log \
| sort -nWyodrębnianie User-Agent i wykrywanie botów
Pole User-Agent (pole 6 po podzieleniu według ") identyfikuje klientów. Roboty indeksujące, scrapery i złośliwe boty często zniekształcają metryki i zawyżają liczbę błędów. Odfiltrowanie ich daje dokładniejszy obraz ruchu generowanego przez rzeczywistych użytkowników.
Typowe sygnatury botów: bot, crawler, spider, curl, python-requests, Googlebot, Bingbot.
Użyj grep -iv (odwrócone dopasowanie bez uwzględniania wielkości liter), aby wykluczyć znane boty, albo użyj awk, aby podzielić wiersz według " i bezpośrednio dopasować pole UA.
#!/usr/bin/env bash
# Count top 15 User-Agent strings, excluding known bots
awk -F'"' '{ print $6 }' /var/log/nginx/access.log \
| grep -iv -e 'bot' -e 'crawler' -e 'spider' -e 'curl' \
-e 'python' -e 'wget' -e 'Go-http-client' \
| sort \
| uniq -c \
| sort -rn \
| head -15Agregowanie ruchu według punktu końcowego
Wiedza o tym, które punkty końcowe otrzymują najwięcej ruchu — i generują najwięcej błędów — pomaga ustalać priorytety optymalizacji i planowania wydajności. Ścieżka żądania znajduje się wewnątrz pola żądania ujętego w cudzysłowy.
Podziel wiersz według ", wybierz pole 2 (wiersz żądania), a następnie usuń metodę i protokół, aby wyodrębnić ścieżkę. W przypadku interfejsów API z parametrami ścieżki, takimi jak /users/12345, możesz również normalizować identyfikatory do postaci /users/:id, używając sed lub bardziej złożonego wzorca awk.
#!/usr/bin/env bash
# Top 20 requested endpoints (method + path, no query string)
awk -F'"' '{ print $2 }' /var/log/nginx/access.log \
| awk '{ print $1, $2 }' \
| sed 's|/[0-9][0-9]*\b|/:id|g' \
| sort \
| uniq -c \
| sort -rn \
| head -20Korelowanie błędów z punktami końcowymi za pomocą awk
Najpotężniejsza analiza wykonywana w jednym przebiegu łączy jednocześnie wiele pól: punkt końcowy, kod stanu i opcjonalnie opóźnienie. Tablice asocjacyjne awk z kluczami złożonymi z kilku wartości pozwalają zrobić to przejrzyście i szybko.
Poniższy wzorzec zlicza błędy 5xx dla poszczególnych punktów końcowych w jednym przebiegu — bez plików tymczasowych i bez sortowania pośredniego aż do samego końca. Takie podejście jest stosowane w produkcyjnych skryptach obserwowalności, gdy na dużym logu trzeba uzyskać odpowiedź w mniej niż minutę.
#!/usr/bin/env bash
# Count 5xx errors per endpoint path in a single pass
awk -F'"' '{
# $2 = request line e.g. "GET /api/orders HTTP/1.1"
# $0 in original space-split: $9 = status
split($0, fields, " ")
status = fields[9]
if (status ~ /^5/) {
split($2, req, " ")
path = req[2]
# Normalise numeric IDs
gsub(/\/[0-9]+/, "/:id", path)
errors[path]++
}
}
END {
for (p in errors)
printf "%6d %s\n", errors[p], p
}' /var/log/nginx/access.log \
| sort -rn \
| head -20Przetwarzanie rotowanych i skompresowanych logów
Na większości serwerów logi są rotowane codziennie. Starsze pliki są kompresowane za pomocą gzip i otrzymują nazwy takie jak access.log.1.gz, access.log.2.gz itd. Standardowe narzędzia nie potrafią odczytać ich bezpośrednio, ale dobrze sprawdzają się dwa podejścia:
zcat— rozpakowuje dane do standardowego wyjścia, które można przekazać do potokuzgrep— wykonuje grep bezpośrednio w plikach gzip, bez ich rozpakowywania
Aby przeanalizować pełny tydzień logów obejmujący zarówno pliki nieskompresowane, jak i skompresowane, użyj podstawiania procesu lub połącz pliki za pomocą zcat. Poniższy fragment przetwarza 7 ostatnich rotowanych plików oraz bieżący aktywny log w jednym wywołaniu awk — bez potrzeby używania plików tymczasowych.
#!/usr/bin/env bash
# Aggregate status codes across a week of rotated logs
# Handles both plain and gzip-compressed rotation files
LOG_DIR="/var/log/nginx"
{
cat "${LOG_DIR}/access.log" 2>/dev/null
zcat "${LOG_DIR}/access.log".*.gz 2>/dev/null
} | awk '
{ count[$9]++ }
END {
for (s in count)
printf "%6d %s\n", count[s], s
}' | sort -rnKtóre pole awk zawiera kod stanu HTTP w formacie Combined Log Format?
Piszesz jednolinijkowy skrypt awk, aby filtrować wyłącznie odpowiedzi HTTP 4xx ze standardowego dziennika dostępu Nginx w Combined Log Format (pola oddzielone spacjami, z ujętym w cudzysłowy wierszem żądania). Który numer pola prawidłowo identyfikuje kod statusu HTTP?
Podsumowanie lekcji: potoki analizy dzienników
W tej lekcji zbudowali Państwo kompletny zestaw narzędzi do analizowania dzienników usług internetowych i aplikacji na dużą skalę, korzystając wyłącznie ze standardowych narzędzi BASH.
Omówione techniki:
- Najpierw struktura — Combined Log Format ma przewidywalny układ pól; jego znajomość pozwala niezawodnie rozdzielać pola za pomocą
cut -d'"'lub odwołań do pól wawk. - Wyodrębnianie kodów statusu —
awk '{ count[$9]++ }'zlicza wszystkie kody w jednym przebiegu; za pomocą$9 ~ /^5/można filtrować błędy serwera. - Analiza opóźnień — za pomocą
awkmożna przetworzyć niestandardowe polert=, aby obliczyć średnie, wartości maksymalne i przedziały histogramu bez użycia zewnętrznych narzędzi. - Analiza klientów i botów — rozdzielanie po
"za pomocą-F'"'umożliwia dotarcie do pola User-Agent; następnie można użyćgrep -iv, aby wykluczyć boty przed agregacją. - Normalizacja endpointów — użycie
gsub(/\/[0-9]+/, "/:id")wewnątrzawkpozwala ujednolicić ścieżki zawierające parametry przed ich zliczaniem. - Rotowane dzienniki — połączenie
catizcatw podpowłoce pozwala przekazać wszystkie pliki rotacji do jednego przebiegu potoku.
Wzorce te można łączyć: mogą Państwo połączyć filtrowanie, wyodrębnianie, normalizację i agregację w jednym potoku, który przetwarza setki milionów wierszy na standardowym sprzęcie. Opanowanie tych podstawowych mechanizmów sprawia, że podczas doraźnego badania incydentów rzadko potrzebują Państwo dedykowanej usługi agregacji dzienników.
Często zadawane pytania
Czy lekcja „Parsowanie logów internetowych i aplikacyjnych na dużą skalę” jest bezpłatna?
Tak — pełny tekst „Parsowanie logów internetowych i aplikacyjnych na dużą skalę” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Linux Command Line & Bash Scripting Mastery, przejdź na CoddyKit PRO. Kurs Linux Command Line & Bash Scripting Mastery zawiera 4 lekcji w sumie.
Co nauczysz się w „Parsowanie logów internetowych i aplikacyjnych na dużą skalę”?
Wyodrębniaj kody statusu, opóźnienia i pola klientów z logów dostępu za pomocą grep, cut i awk. Ćwiczysz Linux Command Line & Bash Scripting Mastery z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Linux Command Line & Bash Scripting Mastery?
Nie wymagamy żadnego doświadczenia. Linux Command Line & Bash Scripting Mastery w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.
Ile czasu zajmuje lekcja „Parsowanie logów internetowych i aplikacyjnych na dużą skalę”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Linux Command Line & Bash Scripting Mastery?
Tak. Każda lekcja Linux Command Line & Bash Scripting Mastery zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Parsowanie logów internetowych i aplikacyjnych na dużą skalę
- Śledzenie logów w czasie rzeczywistym i alerty strumieniowe
- Odpytywanie journald za pomocą journalctl w skryptach
- Obliczanie metryk i histogramów ze strumieni logów