Project: a log analyser

The log analyser is built from small pipelines. This set covers the field syntax of awk, why sort has to come before uniq -c, and how a timestamp is sliced down to its hour.

4 questions 1 task Read the lesson

Questions

Each one is marked as you go, and the explanation arrives straight after, which is the part worth reading.

4 questions, marked as you go.

1 Why must sort come before uniq -c in the count-and-rank pipeline?
2 What does the awk program that prints the first field output for each line of sample.log?
3 Why does the error count use a grep pattern of a space, 5[0-9][0-9], then a space?
4 The timestamp is 10/Oct/2026:11:03:22 inside square brackets. How does the script get the hour?

Tasks

These need your own device. Run the command in Termux, then paste what it printed. The marking looks at what the output means, so spacing, version numbers and ordering do not matter. If you have not installed anything yet, the lesson covers the setup.

Run the report on a sample log

This writes the sample log the project uses and then runs the three parts of the report: the ranked source addresses, the count of server errors, and the busiest hour. Read the shape of each section rather than the exact numbers.

Run this in Termux On your own device. Nothing on this page executes it. The command runs in your terminal, and this box only reads what you paste back.

printf '203.0.113.7 - - [10/Oct/2026:09:12:01 +0000] "GET /index.html HTTP/1.1" 200 1043 198.51.100.4 - - [10/Oct/2026:09:12:05 +0000] "GET /style.css HTTP/1.1" 200 512 203.0.113.7 - - [10/Oct/2026:09:15:44 +0000] "GET /about.html HTTP/1.1" 200 2210 192.0.2.55 - - [10/Oct/2026:10:01:10 +0000] "POST /login HTTP/1.1" 302 0 198.51.100.4 - - [10/Oct/2026:10:02:33 +0000] "GET /index.html HTTP/1.1" 200 1043 203.0.113.7 - - [10/Oct/2026:10:30:00 +0000] "GET /missing.html HTTP/1.1" 404 153 192.0.2.55 - - [10/Oct/2026:10:41:59 +0000] "GET /index.html HTTP/1.1" 200 1043 203.0.113.7 - - [10/Oct/2026:10:55:12 +0000] "GET /boom HTTP/1.1" 500 21 198.51.100.4 - - [10/Oct/2026:10:55:40 +0000] "GET /boom HTTP/1.1" 500 21 192.0.2.55 - - [10/Oct/2026:11:03:22 +0000] "GET /index.html HTTP/1.1" 200 1043 203.0.113.7 - - [10/Oct/2026:11:07:07 +0000] "GET /about.html HTTP/1.1" 200 2210 198.51.100.4 - - [10/Oct/2026:11:22:18 +0000] "GET /style.css HTTP/1.1" 200 512 192.0.2.55 - - [10/Oct/2026:11:44:59 +0000] "GET /index.html HTTP/1.1" 200 1043 203.0.113.7 - - [10/Oct/2026:11:50:31 +0000] "GET /index.html HTTP/1.1" 200 1043 198.51.100.4 - - [10/Oct/2026:11:58:02 +0000] "GET /boom HTTP/1.1" 500 21 192.0.2.55 - - [10/Oct/2026:12:00:01 +0000] "GET /index.html HTTP/1.1" 200 1043 203.0.113.7 - - [10/Oct/2026:12:14:14 +0000] "GET /index.html HTTP/1.1" 200 1043 198.51.100.4 - - [10/Oct/2026:12:19:19 +0000] "GET /style.css HTTP/1.1" 200 512 192.0.2.55 - - [10/Oct/2026:12:25:25 +0000] "GET /index.html HTTP/1.1" 200 1043 203.0.113.7 - - [10/Oct/2026:12:30:30 +0000] "GET /index.html HTTP/1.1" 200 1043 ' > "$HOME/sample.log"; echo "-- Top 10 source addresses --"; awk '{print $1}' "$HOME/sample.log" | sort | uniq -c | sort -nr | head -n 10; echo "-- Errors (5xx) --"; grep -c ' 5[0-9][0-9] ' "$HOME/sample.log"; echo "-- Busiest hour --"; awk -F'[][]' '{print $2}' "$HOME/sample.log" | cut -d: -f2 | sort | uniq -c | sort -nr | head -n 1
Marking your own work Both halves of this are checked in your browser, with no server involved, so nothing stops you from pasting output you did not run. The tasks are written so that the easiest way to pass one is to actually do it and read the result, which is the whole intention.

All sets Read the lesson