05.06.2013

Verbrauchtes LTE-Volumen protokollieren

Ich beschäftige mich weiter mit der Telekom, heute zur Abwechslung mal wieder ein technischer Beitrag, der beschreibt, wie man den Überblick über das schon verbrauchte Volumen behalten kann.

Bekanntlich ist unser Haushalt seit letztem Jahr mit LTE unterwegs im Internet. Bedauerlicherweise gibt es nur Verträge mit Pseudo-Flatrate, die nach einer bestimmten verbrauchten Datenmenge im Monat von der Nominalgeschwindigkeit ("bis zu" 16 MBit/s) auf DSL-light-Geschwindigkeit (384 KBit/s) gedrosselt werden.

Zu dieser Kontingentierung gehört übrigens auch mein Upload. Wenn ich also Bilder hochlade, um Papierabzüge zu bestellen, wird das voll gezählt.

Um das verbrauchte Volumen abzurufen, gibt es eine Info-Seite bei der Telekom, die mir berichtet, wieviel von meinem Kontingent schon verbraucht ist. Mit ein bißchen Getrickse in einem Skript kann ich daraus die zwei Zahlen extrahieren, die ich wissen will, und die protokollieren.

Mein Artikel besteht also aus zwei Teilen: dem Skript zum Abfragen, und einem (wahlweise zwei) Cron-Jobs zur regelmäßigen Aufzeichnung.

Das Skript ist sehr einfach: es verwendet eine "regular expression" in perl, um die Zahlen und die zugehörigen Maßeinheiten (KB, MB, GB) aus dem HTML-Wust herauszufischen.

Übrigens muss man kein Linux haben, um diese kleinen Hilfsmittel einzusetzen: wget, perl und die GNU Kommandozeilenwerkzeuge gibt es auch für Windows. Alternativ kann man auch die komplette CygWin-Umgebung installieren. Mit einem Cron-Job wird es etwas schwieriger, aber wenn man einen PC hat, der immer angeschaltet ist, kann man mit dem Windows-Befehl at auch so etwas zusammenbauen. Die Hilfefunktion wird mit at /? aufgerufen.

Zurück zum eigentlichen Thema: mein erster Versuch, um das HTML anzuschauen, war übrigens diese Kommandozeile:

wget -SO- http://pass.telekom.de/portal/home |\
  perl -pe 's!>!>\n!go' |\
  grep -B1 verbraucht

Diese drei Befehle fragen die Info-Seite ab (wget), und nach jedem HTML-Tag wird mit einem simplen perl-Einzeiler ein Zeilenumbruch eingefügt. Durch die nun entstandene Zeilenstruktur kann der "grep"-Befehl ein Stichwort finden ("verbraucht") und die gesamte Zeile, in der dieses Stichwort vorkommt, ausgeben. Außerdem hätte ich gern die Zeile davor ebenfalls in der Anzeige (der Switch -B anzahl zeigt soviele Zeilen vorher - "Before" - ebenfalls an - diese Option funktioniert nur beim GNU grep, nicht bei AIX, Solaris, etc.).

Mit genau demselben Prinzip, nur etwas aufgehübscht, funktioniert die eigentliche Protokollierung. Da das Werk als Cron-Job laufen soll, muss ich mich selbst um vernünftige Umgebungsvariablen wie PATH kümmern; in Cron-Jobs gibt es nur Minimaleinstellungen.

#!/bin/sh

PATH=/opt/bin:/usr/bin:/usr/local/bin:/usr/local/sbin${PATH:+:$PATH}

date=
file=

while getopts "df:" opt
do
  case "$opt" in
  d) date="%Y%m%d-%H%M%S ";;
  f) file="$OPTARG";;
  esac
done
shift $(expr $OPTIND - 1)

if [ -n "$file" ]
then
  d="${file%/*}"
  test -d "$d" || mkdir -p "$d"
fi

q=$(wget -qO- http://pass.telekom.de/portal/home |\
  perl -ne '
    print("$1 $2 $3 $4\n")
   
if (m#<span.*?>([0-9,.]+).*([KMG]B)</span> von ([0-9,.]+).*([KMG]B) mit voller Geschwindigkeit verbraucht#i)')
test "$(/bin/tty)" = "not a tty" || date +"$date$q"
test -n "$file" && date +"%Y%m%d-%H%M%S $q" >> $file

Die Ausgabe wird hier auf Wunsch noch mit dem Datum der Abfrage versehen, und wenn man mit -f einen Dateinamen angibt, wird die Ausgabe zusätzlich noch an diese Datei angehängt.

Ein paar kleine Tricks will ich ein bißchen näher erklären:

  • PATH=...${PATH:+:$PATH} - hier prüfe ich, ob in der Variablen PATH überhaupt irgendetwas enthalten ist. Falls ja, hänge ich einen Doppelpunkt und den alten Inhalt hinten dran und setze vorn neue Pfadnamen davor.
  • d="${file%/*}" - Vom Dateinamen in $file schneide ich alles nach dem letzten / ab. Als Ergebnis steht in der Variablen $d der Pfadname der Datei.
  • test -d "$d" prüft, ob dieses Verzeichnis existiert, und erzeugt es ggfs. mit mkdir -p mit allen Unterverzeichnissen dazwischen.
  • In einem Cron-Job ist eine Ausgabe auf die Konsole sinnlos, deshalb prüfe ich, ob der Befehl /bin/tty mir das Ergebnis "not a tty" liefert.
  • Der date-Befehl akzeptiert +Formatstring. Ich baue einfach das aktuelle Ergebnis in den Formatstring mit ein: date +"$date$q"

Mit einem Cron-Job wird dieses Skript nun stündlich aufgerufen:

57 * * * * /usr/local/bin/lte-quota.sh -f /var/spool/lte-quota.txt >/dev/null 2>&1

Und einmal am Tag lasse ich mir den aktuellen Stand auch noch als Mail zuschicken:

1 8 * * * (/bin/tail -1 /var/spool/lte-quota.txt | /bin/mail -s "LTE quota" ths) >/dev/null 2>&1
Das Ergebnis sieht dann bei mir etwa so aus:

20130603-225703 1,7 GB 30 GB
20130603-235702 1,9 GB 30 GB
20130604-005702 1,9 GB 30 GB
20130604-015702 1,9 GB 30 GB
20130604-025702 1,9 GB 30 GB
20130604-035702 1,9 GB 30 GB
20130604-045702 1,9 GB 30 GB
20130604-055702 2 GB 30 GB
[Update: die Telekom-Seite hat sich geändert, im Skript Regex angepasst]