Cílem je vyzkoušet si textové filtry a regulární výrazy
při zpracování logů.
Jednoduché textové filtry
Pokud máte naklonovaný repozitář
https://gitlab.fit.cvut.cz/barinkl/uos-workbench.git, aktualizujte jej, jinak si jej naklonujte.
~( cd ~/uos-workbench && git pull ) \
|| git clone https://gitlab.fit.cvut.cz/barinkl/uos-workbench.git
(Na Solarisu - fray1): Nastavte proměnnou PATH
tak, aby se primárně spouštěly GNU verze příkazů z adresáře /usr/gnu/bin
.
~PATH=/usr/gnu/bin:$PATH
Vytvořte symbolický link logs
, který vede do adresáře logs
, který vznikl v prvním úkolu a vstupte do něj.
~ln -s uos-workbench/logs
~cd logs
Zjistěte adresářovou strukturu v adresáři logs
příkazem find
. Spočítejte počty řádků všech souborů s příponou log
v podadresářích.
~/logsfind
~/logswc -l */*/*.log
Vypište jméno log souboru s největším počtem řádků (pozor na celkový počet řádků výpisu příkazu wc
).
~/logswc -l */*/*.log | head -n -1 | sort -n | \
tail -n 1 | cut -c 11-
~/logswc -l */*/*.log | head -n -1 | sort -n | \
tail -n 1 | grep -o '..../../..\.log'
Jméno souboru z předchozího příkladu uložte do proměnné FILE
.
~/logsFILE=$( !! )
~/logsFILE=$( wc -l */*/*.log | head -n -1 | sort -n \
| tail -n 1 | cut -c 11- )
V soboru podle proměnné FILE
spočítejte počet řádků.
~/logswc -l <"$FILE"
Odstraňte z něj začátek každé řádky tak, aby začínal položkou Timestamp
. Výsledek uložte do proměnné LOG
.
Log soubor má strukturu: Měsíc Den Čas Server Služba: Timestamp IP Data1 Data2 "Požadavek"
Pozor na dvouznakové číslo dne. Uvnitř uvozovek jsou vždy právě tři slova.
~/logsLOG=$( tr -s ' ' <"$FILE"| cut -d' ' -f6- )
Z proměnné LOG
vypiště IP adresy seřazené podle počtu požadavků z dané IP adresy (počtu řádků, na které je daná IP adresa).
~/logscut -d' ' -f2 <<<"$LOG" | sort | uniq -c | \
sort -n | tr -s ' ' | cut -d' ' -f3
Nejčastější adresu z předchozího příkladu uložte do proměnné IP
. Pomocí příkazu fgrep
spočítejte, kolik řádek v proměnné LOG
obsahuje tuto IP adresu.
~/logsIP=$(cut -d' ' -f2 <<<"$LOG" | sort | uniq -c | \
sort -n | tr -s ' ' | cut -d' ' -f3 | tail -n 1)
~/logsfgrep -c " $IP " <<<"$LOG"
Vypište přípony souborů o které a kolikrát se žádalo z této IP adresy, seřazené podle počtu požadavků. Přípony vypište za sebou oddělené čárkami.
Předpokládejte, že v cestě k souboru je maximálně 1 tečka.
~/logsfgrep " $IP " <<<"$LOG" | cut -d\" -f2 | \
cut -d' ' -f2 | cut -d. -f2 | sort | uniq -c | sort -rn | \
cut -c9- | paste -d, -s
Vypište jména všech log souborů, ve kterých se vyskytuje IP adresa z proměnné IP
.
~/logsfgrep -l " $IP " */*/*.log
Pro každý soubor, který tuto IP adresu obsahuje (pouze pro ně) vypište počet řádků s touto IP adresou.
~/logsfgrep -c " $IP " $( fgrep -l " $IP " */*/*.log )
Ze všech log souborů vypište pouze řádky, které obsahují řetězec [access_per_ip]
.
~/logsfgrep '[access_per_ip]' */*/*.log
Z řádků podle předchozího příkladu vypište pouze první slovo z řetězce v uvozovkách. Každé slovo nechť je ve výstupu maximálně jednou. Pomocí příkazu grep .
odstraňte prázdné řádky.
~/logsfgrep '[access_per_ip]' */*/*.log | cut -d\" -f2 -s | \
cut -d' ' -f1 | grep . | sort -u
Do výstupu předchozího příkladu přidejte na začátek každé řádky uvozovky a uložte jej do souboru re
.
Nápověda: Použijte příkaz paste
. Jako prázdný soubor můžete použít /dev/null
a standardní vstup se označuje jako -
.
~/logsfgrep '[access_per_ip]' */*/*.log | cut -d\" -f2 -s | \
cut -d' ' -f1 | grep . | sort -u | paste -d\" /dev/null - >re
Ze souboru re
odstraňte řádky obsahující řetězce "GET
nebo "POST
.
~/logsgrep -v -e '"GET' -e '"POST' re >re2
~/logsmv re2 re
Vypište řádky všech log souborů, které odpovídají vzorům v souboru re
. Odpovídající řetězec, nechť je ve výstupu obarvený.
~/logsgrep --color -f re */*/*.log
Z předcházejícího příkladu vypište časový rozsah, kdy k takovým požadavkům docházelo ve formátu YYYY.MM.DD-YYYY.MM.DD
.
~/logsFILES=$( grep -l -f re */*/*.log | cut -c1-10 )
~/logsSINCE=$( head -n 1 <<<"$FILES" )
~/logsTO=$( tail -n 1 <<<"$FILES" )
~/logsprintf '%s-%s\n' "$SINCE" "$TO" | tr / .
Regulární výrazy
Zkontrolujte, že příkazem grep
voláte GNU verzi příkazu, která podporuje přepínač -o
.
Na Solarisu (fray1): Nastavte proměnnou PATH
tak, aby se primárně spouštěly GNU verze příkazů z adresáře /usr/gnu/bin
.
# Linux
~grep --version
~grep -o '' /dev/null ; echo $?
# Solaris
~PATH=/usr/gnu/bin:$PATH
~grep --version
~grep -o '' /dev/null ; echo $?
Stáhněte/aktualizujte si lokální kopii repozitáře https://gitlab.fit.cvut.cz/barinkl/uos-workbench.git
a přejděte do jeho podadresáře logs
.
~( cd ~/uos-workbench && git pull ) \
|| git clone https://gitlab.fit.cvut.cz/barinkl/uos-workbench.git
~cd logs || cd uos-workbench/logs
Spočítejte, kolik požadavků (záznamů v logu apache.log
) neodesílalo data (poslední položka je -
).
Poslední položkou v souboru apache.log
je velikost odeslaných dat nebo znak -
, pokud data nebyla odeslána.
~/logsgrep -c -- '-$' apache.log
~/logsgrep -c -e '-$' apache.log
~/logsgrep -c ' -$' apache.log
Vypište stavové kódy (předposlední položku), při kterých došlo k neodeslání dat (poslední položka je -
).
Předposlední položkou v souboru apache.log
je trojciferný stavový kód.
~/logsgrep -o '... -$' apache.log | cut -c1-3 | sort -u
Z předchozího příkladu vypište, který stavovoý kód byl nejčastější. Tento stavový kód uložte do proměnné CODE
.
~/logsgrep -o '... -$' apache.log \
| cut -c1-3 \
| sort \
| uniq -c \
| sort -n \
| tail -n 1 \
| grep -o '...$'
~/logsCODE=$( !! )
Vypište, jaké různé metody byly u požadavků, které končily stavovým kódem v proměnné CODE
a neodeslaly žádná data.
První řádka HTTP požadavku je v logu zapsána do uvozovek a obsahuje"metoda URL HTTPverze"
~/logsgrep " $CODE -$" apache.log \
| egrep -o '"[^ ]+' \
| sort -u \
| cut -c2-
Vypište, která URL byla nejčastější u požadavků, které končily stavovým kódem v proměnné CODE
a neodeslaly žádná data.
~/logsgrep " $CODE -$" apache.log \
| egrep -o '"[^"]+"' \
| cut -d' ' -f2 \
| sort \
| uniq -c \
| sort -n \
| tail -n 1 \
| grep -o '[^ ]*$'
Spočítejte, kolik požadavků skončilo stavovým kódem 200. Vypište, kolik jich bylo a kolik to bylo procent ze všech požadavků.
~/logsc=$( egrep -c ' 200 [^ ]+$' apache.log )
~/logsn=$( egrep -c '' apache.log )
~/logsprintf '%d %d%%\n' "$c" $(( 100*c/n ))
Při použití jednoduššího RE " 200 "
v předchozím příkladu by byl výsledech chybný o jeden řádek. Vypište, který by to byl.
~/logsegrep ' 200 ' apache.log | egrep -v ' 200 [^ ]+$'
~/logsegrep ' 200 [^ ]+$' apache.log >~/spravne
~/logsegrep ' 200 ' apache.log >~/spatne
~/logsdiff ~/spravne ~/spatne
~/logsrm ~/spravne ~/spatne
U požadavků se stavovým kódem 200
vypište, které různé přípony požadovaných souborů obsahují query string.
Součástí URL může být tzv. query string, který začíná znakem ?
.
~/logsegrep ' 200 [^ ]+$' apache.log \
| egrep -o '\.[^. ]+\?' \
| grep -o '[^?]*' \
| sort -u
Sečtěte všechny velikosti odeslaných dat při stavovém kódu 200
.
(Nápověda: použijte příkaz paste
a aritmetický výraz v shellu.)
~/logsegrep -o ' 200 [^ ]+$' apache.log \
| egrep -o '[0-9]+$' \
| paste -d+ -s
~/logsecho $(( $( !! ) + 0 ))
# Půjde to i snadněji
~/logsawk '
$(NF-1)==200 { sum+=$NF }
END { printf "%0.f\n", sum }
' apache.log
Vypiště řádky, které požadavky mají nejdelší cestu (počet adresářů) - t.j. řádky obsahují nejvíce lomítek.
~/logsC=$(
cut -d\" -f2 -s apache.log \
| cut -d' ' -f2 \
| tr -dc '/\n' \
| wc -L
)
~/logsegrep "(/[^ ]+){$C}" apache.log
~/logsC=$( tr -dc '/\n' <apache.log | wc -L )
~/logsegrep "(/.*){$C}" apache.log
Vypište počet požadavků na soubory s příponami jpg
nebo png
.
~/logsegrep -c '\.(jpg|png)[ ?]' apache.log
Vypiště, které požadavky by chyběly nebo byly navíc, kdyby se v předchozím řešení použily nesprávné RE '.(jpg|png)'
a nebo '\.(jpg|png) '
~/logsegrep '\.(jpg|png)[ ?]' apache.log \
| egrep -v '\.(jpg|png) '
~/logsegrep '.(jpg|png)' apache.log \
| egrep -v '\.(jpg|png)[ ?]'