Command Line Adventues: AWK
Wenn ich mich recht erinnere haben wir in den vorangegangenen CLI-Adventures awk
bisher immer nur verwendet um eine bestimmte Stelle (nennen wir es Spalte) einer Zeile herauszulösen. awk kann jedoch deutlich mehr, zum Beispiel Rechnen und Systembefehle ausführen.
cat speedtest.txt | grep Download | awk ‘{SUM += $2} END {system(“cat speedtest.txt | grep Download | wc -l” | getline LINES);print SUM/LINES}’ 2> /dev/null
Was passiert da? Nun, ich denke, ich sollte das ein wenig ausführlicher Erläutern. Mein Internet zuhause schwächelt. Schon länger, aber es waren gefühlt immer mind. 50 MBit (von 100), damit habe ich mich zufrieden gegeben. Mittlerweile fühlt es sich aber eher wie 25 MBit an. Bevor ich mich beim Provider (netcologne) beschwere wollte ich das aber genau wissen. netcologne blockt in der Regel alle Speedtests ab, die nicht mit netcologne-Servern durchgeführt wurden. Für http://speedtest.net stellt netcologne einen Testserver bereit. Unter https://github.com/sivel/speedtest-cli gibt es ein Kommandozeilentool für speedtest.net, es steht außerdem als Debian-Paket zur Verfügung:
apt-get install speedtest-cli
speedtest-cli –server 6601
6601
ist die Server-ID des netcologne-Speedtest-Servers (siehe http://www.speedtest.net/speedtest-servers.php). Natürlich sollte man einen Speedtest über einen längeren Zeitraum durchführen. Und natürlich habe ich keine Lust dies jede Stunde selbst zu tun. Also ein kleines Script:
#!/bin/bash
cd /home/gpkvt
date >> speedtest.txt
/usr/local/bin/speedtest-cli –server 6601 | grep ‘Download\|Upload\|Hosted\|Testing from’ >> speedtest.txt
echo “———————————–” >> speedtest.txt
Per Cron läuft das jetzt jede Stunde und erzeugt pro Lauf folgenden Eintrag:
Sun Jan 3 12:00:01 CET 2016
Testing from NetCologne GmbH (xx.xx.xx.xx)…
Hosted by NetCologne (Cologne) [5.04 km]: 20.8 ms
Download: 24.14 Mbit/s
Upload: 4.59 Mbit/s
———————————–
Natürlich will ich netcologne jetzt nicht mit einer Datei mit hunderten von Zeilen bewerfen, sondern einen Durchschnittswert melden. Die awk
-Zeile von oben ermöglicht genau das:
cat speedtest.txt | grep Download
gibt die Downloadgeschwindigkeiten aus.
awk ‘{SUM += $2}
zählt die MBit/s-Werte zusammen.
END
sorgt dafür, dass eine Aktion ausgeführt wird, wenn keine weiteren Zeilen von speedtest.txt an awk übergeben werden.
{system(“cat speedtest.txt | grep Download | wc -l” | getline LINES)
zählt die Anzahl der Download-Zeilen in speedtest.txt zusammen und speichert den Wert als LINES.
;print SUM/LINES}’
teilt SUM durch LINES und gibt das Ergebnis aus.
2> /dev/null
unterdrückt eine Shell-Fehlermeldung.
Das Ergebnis, meine durchschnittliche Downloadrate (in MBit/sek.) in den letzten 3 Tagen:
24.9871
Update: Auf [[https://twitter.com/jselzer/status/683648459837173760|Twitter]] wurde ich gefragt, ob der system
-Part nicht auch eleganter zu lösen wäre. Ja:
cat speedtest.txt | grep Download | awk ‘{LINES++;SUM += $2} END {print SUM/LINES}’
Hier zählt awk
gleich die Anzahl der Zeilen (LINES++) mit und nutzt diesen Wert dann. Der system
-Aufruf kann dann komplett entfallen. Neben der handlicheren Zeilenlänge hat dieses Vorgehen natürlich auch noch den Vorteil, dass sich zwischen der Summenbildung (SUM) und dem system
-Aufruf die Anzahl der gefundenen Zeilen in der speedtest.txt
nicht ändern können.
Noch handlicher ginge es dann noch, wenn man auf cat
und grep
verzichtet:
awk ‘/Download/ {LINES++;SUM += $2} END {print SUM/LINES}’ speedtest.txt
Hier sucht awk
selbst nach Download
.