The blocks marked Run on this page can run in your browser: the first one downloads and starts a small machine, with no network. That needs JavaScript. Without it you read the output saved with the document.
No networkText processing#
Use grep, sed and awk to answer questions about a log. The first block generates a small web-server style log, so the page needs no files of its own.
Generate a log#
sh#log
rm -f /tmp/access.log
i=0
while [ $i -lt 40 ]; do
case $((i % 7)) in
0) code=500 ;;
1|2) code=404 ;;
*) code=200 ;;
esac
path=/page/$((i % 5))
ms=$(( (i * 37) % 250 + 5 ))
printf '10.0.0.%d GET %s %d %dms\n' $((i % 4 + 1)) "$path" "$code" "$ms" >> /tmp/access.log
i=$((i + 1))
done
wc -l /tmp/access.log
head -n 5 /tmp/access.logEach line is: client address, method, path, status code and response time.
grep: pick lines#
sh#grep
echo "errors (5xx):"
grep -c ' 5[0-9][0-9] ' /tmp/access.log
echo "not found, first three:"
grep ' 404 ' /tmp/access.log | head -n 3
echo "everything except 200:"
grep -vc ' 200 ' /tmp/access.logsed: rewrite lines#
sh#sed
echo "hide the last octet of the address:"
sed -E 's/^([0-9]+\.[0-9]+\.[0-9]+)\.[0-9]+/\1.x/' /tmp/access.log | head -n 3
echo "only lines 2 to 4:"
sed -n '2,4p' /tmp/access.logawk: count and add up#
sh#awk-count
echo "requests per status code:"
awk '{ n[$4]++ } END { for (c in n) print c, n[c] }' /tmp/access.log | sortsh#awk-time
echo "slowest and average response time:"
awk '{ t = $5; sub(/ms/, "", t); t += 0; s += t; if (t > m) m = t }
END { printf "max %dms, mean %.1fms over %d requests\n", m, s / NR, NR }' /tmp/access.logPut it together#
A pipeline answers "which path has the most errors?":
sh#pipeline
awk '$4 >= 400 { print $3 }' /tmp/access.log | sort | uniq -c | sort -rnRead it from left to right: keep lines with a status of 400 or more, take the path, group equal paths, count them, put the biggest first.