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.
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.
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 The address rows are a count and an address, and the busiest hour is a count and a bare two-digit hour.
- the top addresses are ranked with their request counts
- the busiest hour is reported as a count and an hour
- the report has a heading and several result rows
- the commands actually ran
Three headed sections. Under the addresses you get one row per address, each a count then the address, with the largest count first because sort -nr ranks them. Under the errors you get a single number, the count of lines whose status code is in the 500 range. Under the busiest hour you get a count then a two-digit hour, the hour with the most requests. If a section is empty, one of the pipelines lost its input along the way.