GästebuchIhr Eintrag in unser Gästebuch KontaktNehmen Sie Kontakt mit den Autoren auf ArchivAlle Unixwerk- Artikel seit 2003
13. September 2005

MiniTipp: DSL Transfervolumen loggen

Inhalt

  1. Einleitung
  2. DSL Transfervolumen loggen
  3. Das Skript

Dieses Dokument beschreibt ein Verfahren, den Upstream und Downstream über ein DSL-Modem¹ zu verfolgen. Voraussetzung dafür ist die Verwendung von pppoe. Falls Sie einen DSL-Router benutzen funktioniert dieses Verfahren nicht.


¹ Dieses Verfahren sollte auch bei analogem Modem so funktionieren.

 

 

1 Einleitung

Wer über einen DSL-Anschluss mit einer Flatrate verfügt, kann sich glücklich schätzen - wieviel Volumen auch immer über die Leitung transportiert wird, es ist ziemlich egal: bezahlt ist bezahlt. Eine Aufstellung des Transfervolumens ist sicher interessant, aber nicht wirklich wichtig. Anders sieht es aus, wenn man ein bestimmtes Freivolumen hat und alles darüber hinaus richtig teuer wird - da möchte man schon gerne wissen, wieviel vom Freivolumen eigentlich schon aufgebraucht ist. Eine Möglichkeit dies zu erfassen wird im Folgenden aufgezeigt.

 

 

2 DSL Transfervolumen loggen

Es führen immer mehrere Wege nach Rom. So gibt bereits ifconfig eine Statistik über Transmit- und Receive-Bytes aus:

 linux# ifconfig ppp0

 ppp0      Link encap:Point-to-Point Protocol  
           inet addr:80.185.148.11  P-t-P:62.104.190.31  Mask:255.255.255.255
           UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1454  Metric:1
           RX packets:4423 errors:0 dropped:0 overruns:0 frame:0
           TX packets:4389 errors:0 dropped:0 overruns:0 carrier:0
           collisions:0 txqueuelen:3 
           RX bytes:3019629 (2.8 Mb)  TX bytes:734111 (716.9 Kb)

Dieser Zähler hat aber zwei Nachteile: Er kann überlaufen - und startet dann wieder bei 0. Außerdem wird nur die laufende ppp-Verbindung mitverfolgt - nach einer Verbindungstrennung steht der Zähler wieder auf 0.
Gibt's da nicht noch was anderes? Ja - der ppp-Dämon verfolgt nämlich ebenfalls die Transmit- und Receive-Bytes und schreibt diese (nach Trennung der Verbindung) nach /var/log/messages. Dort überleben die Infos auch einen System-Neustart:

 /var/log/messages (Ausschnitt)
 
 Sep 13 01:20:18 linux pppd[2260]: Hangup (SIGHUP)
 Sep 13 01:20:18 linux pppd[2260]: Modem hangup
 Sep 13 01:20:18 linux pppd[2260]: Connection terminated.
 Sep 13 01:20:18 linux pppd[2260]: Connect time 788.7 minutes.
 Sep 13 01:20:18 linux pppd[2260]: Sent 7006661 bytes, received 45366006 bytes.
 Sep 13 01:20:18 linux pppd[2260]: Exit.

Dies habe ich mir zunutze gemacht für ein kleines Skript, das mir Auskunft über das bereits verbrauchte Transfer-Volumen gibt (-> Anhang). So etwa sieht die Ausgabe (für die letzten 3 Monate) aus:

 linux# dslstat -3

  DSL Statistics for linux
 ==================================
 Log started : Oct  7 2003 01:01:03
 Current time: Sep 13 2005 18:09:44


 Jul 2005:   67 MB Upstream
            795 MB Downstream
          -------------------
            862 MB Total

 Aug 2005:  168 MB Upstream
           2336 MB Downstream
          -------------------
           2505 MB Total

 Sep 2005:   57 MB Upstream
            409 MB Downstream
          -------------------
            466 MB Total


Nachteil ist, dass die laufende Verbindung nicht mitverfolgt wird, da der pppd erst bei Trennung der Verbindung die Statistik nach /var/log/messages loggt. Für mich reicht das, da ich nicht tagelang ununterbrochen am Internet hänge. Wer's braucht könnte das erwähnte Skript aber anpassen, so dass etwa der ifconfig-Zähler auf die ppp-Statistik aufaddiert wird. Der Kreativität sind - wie immer bei Linux - keine Grenzen gesetzt.

 

 

A Das Skript

 dslstat
 #!/bin/bash
 #
 # 24-10-04: Dubletten werden rausgefischt 
 #           (Mit Kernel 2.6 schreibt der pppd 2x!)
 #
 # 25-10-04: Monate werden nach Jahren getrennt betrachtet
 #           (Dies macht der awk-Code...) 
 
 MYNAME=$(basename $0 | sed -e 's/stat$//' -e y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/)
 
 export LC_ALL=C
 
 LOGFILES="$(ls -rt /var/log/messages.* /var/log/messages)"
 
 
 # Wieviele Monate alt ist das Log?
 # ================================
 AGE=$(cat $LOGFILES | egrep 'pppd\[[0-9]*\]: Sent' | awk '{print $1}' | uniq | wc -w)
 LSM=$(cat $LOGFILES | egrep 'pppd\[[0-9]*\]: Sent' | awk '{print $1}' | uniq | head -1)
 
 # Welches Jahr haben wir?
 # =======================
 THY=$(date +%Y)
 
 # In welchem Jahr beginnt das Log?
 # ================================
 case $LSM in
   "Jan") LOGSTART=$(( THY - (AGE-1)/12 )) ;;
   "Feb") LOGSTART=$(( THY - (AGE+0)/12 )) ;;
   "Mar") LOGSTART=$(( THY - (AGE+1)/12 )) ;;
   "Apr") LOGSTART=$(( THY - (AGE+2)/12 )) ;;
   "May") LOGSTART=$(( THY - (AGE+3)/12 )) ;;
   "Jun") LOGSTART=$(( THY - (AGE+4)/12 )) ;;
   "Jul") LOGSTART=$(( THY - (AGE+5)/12 )) ;;
   "Aug") LOGSTART=$(( THY - (AGE+6)/12 )) ;;
   "Sep") LOGSTART=$(( THY - (AGE+7)/12 )) ;;
   "Oct") LOGSTART=$(( THY - (AGE+8)/12 )) ;;
   "Nov") LOGSTART=$(( THY - (AGE+9)/12 )) ;;
   "Dec") LOGSTART=$(( THY - (AGE+10)/12 )) ;;
 esac
 
 # Header ausgeben
 # ===============
 echo
 echo " $MYNAME Statistics for $(uname -n)"
 echo "=================================="
 printf "Log started : %3s %2d $LOGSTART %s\n" $(cat ${LOGFILES} | head -1 | awk '{print $1,$2,$3}')
 printf "Current time: $(date +%b" "%d" "%Y" "%X)\n\n"
 echo
 
 case "$1" in
 
   Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)
     MONTHs="$1" 
     ;;
 
   -[0-9]|-[0-9][0-9])
     CNT="$(echo $1 | cut -d- -f2)"
     $0 | tail -$((5*CNT))
     exit 
     ;;
 
   ''|"tot"*)
     MONTHs=$(cat $LOGFILES | egrep 'pppd\[[0-9]*\]: Sent' | awk '{print $1}' | uniq)
     ;;
 
   ?*)
     $0 | tail -5
     exit 
     ;;
 
 esac
 
 # Wieviele Monate wollen wir davon sehen?
 NOM=$(echo $MONTHs | wc -w)
 # => Wieviele Jahre?
 NOY=$(( (NOM-1)/12 ))
 # Startmonat?   
 STM=$(echo $MONTHs | cut -d" " -f1)
 # Welches Jahr haben wir?
 THY=$(date +%Y)
 # In welchem Jahr beginnt das Log?
 case $STM in
   "Jan") STY=$(( THY - (NOM-1)/12 )) ;;
   "Feb") STY=$(( THY - (NOM+0)/12 )) ;;
   "Mar") STY=$(( THY - (NOM+1)/12 )) ;;
   "Apr") STY=$(( THY - (NOM+2)/12 )) ;;
   "May") STY=$(( THY - (NOM+3)/12 )) ;;
   "Jun") STY=$(( THY - (NOM+4)/12 )) ;;
   "Jul") STY=$(( THY - (NOM+5)/12 )) ;;
   "Aug") STY=$(( THY - (NOM+6)/12 )) ;;
   "Sep") STY=$(( THY - (NOM+7)/12 )) ;;
   "Oct") STY=$(( THY - (NOM+8)/12 )) ;;
   "Nov") STY=$(( THY - (NOM+9)/12 )) ;;
   "Dec") STY=$(( THY - (NOM+10)/12 )) ;;
 esac
 
 
 
 NR=0
 OUY=$STY
 for monat in ${MONTHs}
 do
 
   cat $LOGFILES | egrep "^$monat" | egrep 'pppd\[[0-9]*\]: Sent' | uniq | \
                                     awk -v _nr=$NR -v _year=$OUY -v _mon=$monat '
 
     BEGIN { _day=0; _fnd=0; _rec=0; _snt=0; }
 
     {
       # Das wievielte Auftreten unseres Monats suchen wir?
       _src=int( _nr/12 );
 
       # Gefunden, dann zählen...
       if (_fnd == _src) { _rec=_rec+$10;
                           _snt=_snt+$7; };
 
       # Den "Monatsauftrittszähler" hochsetzen, wenn der gefundene
       # Tag kleiner als der letzte ist...
       if ($2 < _day) { _fnd=_fnd+1 };
 
       _day=$2;
     }
 
     END { snd_out=sprintf( "%5d", int( _snt/1024/1024 ) );
           rec_out=sprintf( "%5d", int( _rec/1024/1024 ) );
           tot_out=sprintf( "%5d", int( (_snt+_rec)/1024/1024 ) );
 
           print _mon" "_year":"snd_out" MB Upstream";
           print "         "rec_out" MB Downstream";
           print "         -------------------";
           print "         "tot_out" MB Total\n";
         }'
 
   if [ "$monat" = "Dec" ]
   then 
     OUY=$((OUY+1))
   fi
   NR=$((NR+1))
 
 done