Shell Prakticky
Zpracování logů

Lukáš Bařinka

Cíl

Cílem je vyzkoušet si textové filtry a regulární výrazy
při zpracování logů.

Obsah

  • Jednoduché textové filtry
  • Regulární výrazy

Část 1

Jednoduché textové filtry

Úloha 01

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
						

Úloha 02

(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
						

Úloha 03

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
						

Úloha 04

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
						

Úloha 05

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'
						

Úloha 06

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- )
						

Úloha 07

V soboru podle proměnné FILE spočítejte počet řádků.


							~/logswc -l <"$FILE"
						

Úloha 08

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- )
						

Úloha 09

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
						

Úloha 10

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"
						

Úloha 11

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
						

Úloha 12

Vypište jména všech log souborů, ve kterých se vyskytuje IP adresa z proměnné IP .


							~/logsfgrep -l " $IP " */*/*.log
						

Úloha 13

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 )
						

Úloha 14

Ze všech log souborů vypište pouze řádky, které obsahují řetězec [access_per_ip] .


							~/logsfgrep '[access_per_ip]' */*/*.log
						

Úloha 15

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
						

Úloha 16

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
						

Úloha 17

Ze souboru re odstraňte řádky obsahující řetězce "GET nebo "POST .


							~/logsgrep -v -e '"GET' -e '"POST' re >re2
							~/logsmv re2 re
						

Úloha 18

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
						

Úloha 19

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 / .
						

Část 2

Regulární výrazy

Úloha 01

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 $?
						

Úloha 02

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
						

Úloha 03

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
						

Úloha 04

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
						

Úloha 05

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=$( !! )
						

Úloha 06

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-
						

Úloha 07

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 '[^ ]*$'
						

Úloha 08

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 ))
						

Úloha 09

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
						

Úloha 10

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
						

Úloha 11

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
						

Úloha 12

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
						

Úloha 13

Vypište počet požadavků na soubory s příponami jpg nebo png .


							~/logsegrep -c '\.(jpg|png)[ ?]' apache.log
						

Úloha 14

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)[ ?]'