Contador de sesiones GPRS para Linux

¿Qué es?

Es un script que cuenta las sesiones (según tiempo y datos transferidos) consumidas al utilizar un teléfono móvil como módem (GSM, GPRS o UMTS) conectado al ordenador para acceder a Internet. Mas información en el propio script.

Captura de pantalla

Ejemplo de funcionamiento:


[libnet@localhost ~]$ ./conta_ses.pl
[11:26:55]       Contador iniciado:  Wed Aug 16 21:04:19 2006
[11:26:55]       Sesiones consumidas:
[11:26:55]       = 150
[12:14:19]       +1 = 151        Iniciada conexion
[12:24:19]       +1 = 152        Tiempo
[12:32:35]       +1 = 153        Datos
[12:35:52]       = 153           Terminada conexion
[12:50:59]       +1 = 154        Iniciada conexion
[12:57:04]       +1 = 155        Datos
[13:07:04]       +1 = 156        Tiempo
                 [04:39   32 KB   46%]

Script

Para obtener el script, copiar el siguiente texto coloreado y pegarlo en un fichero nuevo, con nombre "conta_ses.pl":


#!/usr/bin/perl

# 
# conta_ses.pl
# 
# Contador de "sesiones" de Internet.
# Version 0.9 (12-ago-2006)
# 
# 
# 
# POR QUE este script:
# 
# - En Vodafone (y posiblemente en otros operadores), el consumo de internet se
#   tarifica por "sesiones". Una "sesión" se define como 256KB de transferencia
#   o 10 minutos de tiempo (lo que ocurra primero).
# 
# - Por tanto, para saber el numero de "sesiones" consumidas, no basta con saber
#   el total de datos transferidos o el tiempo total de conexión. Es preciso ir
#   contando las sesiones conforme se van consumiendo.
# 
# - Las sesiones se cobran por adelantado, es decir, antes de consumirlas. Nada 
#   mas conectar, ya has gastado una sesion. Por ejemplo, si conectas y 
#   desconectas rápidamente 3 veces (sin apenas consumir tiempo ni datos), te
#   cobran 3 "sesiones".
# 
# - Otro ejemplo. La Promoción Verano de este año anuncia "250MB gratis", pero
#   en realidad son "1000 sesiones gratis". Si te conectaras a internet el 
#   primer día de facturación, y te desconectaras el último dia de facturación,
#   sin haber transferido datos en todo el tiempo, tendrías que pagar 
#   aproximadamente (teniendo en cuenta que 1000 sesiones dan para 
#   1000*10 minutos =~ 7 dias): 
#
#   (30-7)*24*(60/10) sesiones * 0.5 euros/sesion = 1656 euros  
#    
#   Es decir, tendrías que pagar 1656 euros, a pesar de no haber consumido ni 
#   1KB de los "250MB gratis".
# 
# 
# QUE HACE este script:
# 
# - Cuenta el numero de "sesiones" conforme se van consumiendo.
# 
# - Para ello, tiene en cuenta conexiones y desconexiones, tiempo de conexión,
#   y datos transferidos (subida y bajada).
# 
# - Va acumulando en un fichero (contador.txt) las sesiones contabilizadas. 
#   Para poner a cero el contador, sólo hay que borrar (o renombrar) el fichero.
# 
# - Va generando un fichero de bitácora (conta_ses.log) con el historial de 
#   sesiones consumidas.
# 
# - Es fácilmente adaptable a cualquier operador, a cualquier interfaz, y 
#   a cualesquiera cantidades que definan una "sesión".
# 
# 
# CUAN FIABLE es este script:
# 
# - Este script funciona por muestreo. Es decir, cada cierto tiempo (periodo de
#   muestreo) recoge muestras del estado de la interfaz (conectada o 
#   desconectada) y de los datos transferidos hasta el momento (bajada+subida).
# 
# - Por tanto, no conoce el momento exacto en el que la interfaz cambia de 
#   estado o en el que se alcanza el máximo de datos de una sesión, ya eso que 
#   puede ocurrir en cualquier momento entre dos muestras.
# 
# - Sin embargo, al ser el periodo de muestreo muy bajo (por defecto, de una 
#   décima de segundo), el error cometido también es muy bajo, lo suficiente
#   como para afirmar que la contabilización de sesiones es muy fiable. No es 
#   exacta, pero sí muy aproximada.
# 
# - Esto significa que no debe usarse este script, por ejemplo, para apurar "al
#   máximo" un bono de acceso a internet (para consumir hasta la última sesión
#   pero sin pasarse). Es decir, si tenemos un bono de 400 sesiones, y el script
#   lleva contabilizadas 380, no podemos pretender llegar justo hasta 400, 
#   porque puede ser que se hayan contado algunas de menos o de mas. Aunque nos 
#   indique que hemos consumido 380, puede que en realidad hayamos consumido
#   377 o 383 (por poner un ejemplo).
# 
# - Sí puede usarse para saber, con una fiabilidad bastante alta, cuánto hemos 
#   consumido.
# 
# - Si se desea, puede aumentarse la exactitud modificando el periodo de 
#   muestreo. Cuanto mas pequeño sea este, mas pequeño será el error, y
#   por tanto mas exacta será la contabilización de sesiones. Por ejemplo, en 
#   vez del periodo por defecto de una décima de segundo (0'1 seg.), puede 
#   utilizarse una centésima (0'01 seg.) o incluso con una milésima 
#   (0'001 seg.). La contrapartida es que, cuanto mas rápido se muestree, mayor
#   será el uso del procesador por parte del script.
#
# 
# CUANDO debe ejecutarse este script:
# 
# - El script debe estar ejecutandose siempre que se realice una conexión, y 
#   no debe detenerse (control+c) hasta que finalice la conexión.
# 
# - Si se lanza cuando ya está establecida una conexion, hará una estimación
#   del número de sesiones consumidas durante la conexión, calculando el número
#   de sesiones equivalentes a los datos transferidos.
# 
# - El script sólo contabiliza sesiones mientras se está ejecutando, no 
#   contabiliza sesiones correspondientes a conexiones antiguas en las que no 
#   se estaba ejecutando. Por ejemplo: si, sin estar ejecutándose el script, se
#   realiza una conexión, se transfieren datos, y se termina la conexión, las
#   sesiones consumidas durante la conexión habrán quedado sin contabilizar. 
# 
# - Por tanto, se recomienda lanzar el script nada mas encender el ordenador,
#   antes de realizar cualquier conexión, y dejarlo funcionando continuamente.
# 
# 
# COMO ejecutar este script:
# 
# - Hay 2 comandos posibles:
# 
#   - perl conta_ses.pl
#   
#   - ./conta_ses.pl  (darle antes permiso de ejecución (chmod +x conta_ses.pl))
# 
# - Puede llamarse desde cualquier directorio (y desde cualquier script).
# 
# 
# REQUISITOS:
# 
# - Ordenador gnulinux con interfaz lógica de red. Normalmente será la interfaz
#   que utilices para la conexión punto-a-punto con el móvil (por ejemplo ppp0),
#   pero puede servir cualquier interfaz (puedes probar con: lo, eth0, ...).
# - Perl.
# - Módulo Time::HiRes (viene de serie desde Perl 5.8) (disponible en cpan.org).
# - Kernel linux 2.6 (o superior).  (proporciona el arbol /sys)
# 
# 
# Restricciones de LIBERTAD:
# 
# - Este programa es Software Libre.
# - Eso significa que eres libre de usarlo, copiarlo, compartirlo y modificarlo
#   (entre otras cosas).
# - Licencia GNU GPL 2.0 (disponible en http://www.gnu.org/licenses/gpl.html).
# - Y por supuesto, puedes contribuir a mejorarlo. Por ejemplo, detectando 
#   errores, añadiendo funcionalidad, traduciendo a otros idiomas, etc.
# 
# 
# AUTOR:
# 
# - Libnet (libnet_ algarroba myway.com).
# 


## Bibliotecas
use Time::HiRes qw( time sleep );   ## si no está instalada, descargar de CPAN.
use FindBin qw( $RealBin );         ## directorio del script


## Configuracion
$int = "ppp0";                  ## interfaz [ppp0]
$ses_t = 10 * 60;               ## tiempo de sesión (segundos) [10 minutos]
$ses_d = 256 * 1024;            ## datos de sesión (bytes) [256 KB]
$p_mues = 0.1;                  ## periodo de muestreo (segundos) [1 décima]

$f_cont = "${RealBin}/contador.txt";  ## fich con el contador (núm. de sesiones)
$f_log = "${RealBin}/conta_ses.log";  ## fichero de bitácora


## Info interfaz
$int_d = "/sys/class/net/$int";         ## directorio de la interfaz
$int_d_es = "${int_d}/statistics";      ## direc de estadisticas de la interfaz
$int_f_su = "${int_d_es}/tx_bytes";     ## fichero contador de subida
$int_f_ba = "${int_d_es}/rx_bytes";     ## fichero contador de bajada


## Inicio bitácora
impri_log ("------ \t Iniciado programa");


## Contador acumulado
if (-e $f_cont)                 ## existe fichero contador -> leemos
{
  open FCONT, "< $f_cont";
  chomp ($f_ini_cont = <FCONT>);        ## fecha inicio del contador (1a linea)
  chomp ($n_ses = <FCONT>);             ## numero de sesiones consumidas (2a)
  close FCONT;
}
else                            ## no existe fichero contador -> creamos
{
  $f_ini_cont = localtime;
  $n_ses = 0;
  guar_cont();                          ## guardamos contador en fichero
}
impri ("Contador iniciado:  $f_ini_cont");
impri ("Sesiones consumidas:");
impri ("= $n_ses");


## Bucle principal
$conectado = 0;             ## conectado en este momento? (= hay sesion ahora?)
$ini_ses_t = 0;             ## instante de inicio de la sesion actual
$ini_ses_d = 0;             ## datos transferidos al iniciarse la sesion actual
$t_dorm = 0;                ## tiempo a dormir
$mues_t = time;             ## muestra de tiempo actual
$mues_t_sig = $mues_t;      ## muestra de tiempo siguiente (muestreamos ya)
$mues_t_ant = $mues_t;      ## muestra de tiempo anterior
$t_imp = 0;                 ## instante de ultima impresion por pantalla
$| = 1;                     ## escritura en pantalla sin buffer
while (1)
{
  ## Dormimos hasta siguiente muestra
  $t_dorm = $mues_t_sig - time;         ## rectifica desviaciones de tiempo
  if ($t_dorm > 0)
  {
    sleep $t_dorm;                      ## dormimos el tiempo calculado
  }
  else
  {
    $t_dorm = 0;
  }


  ## Datos de la muestra actual
  $mues_t_ant = $mues_t;                ## muestra de tiempo anterior
  $mues_t = $mues_t_sig;                ## muestra de tiempo actual
  $nue_ses = 0;                         ## es nueva sesion?


  ## Casos posibles
  if (-e $int_d)        ## existe la interfaz (= conectado)
  {

    if ($conectado)     ## estaba conectado -> sigue conectado
    {
      $mues_d = dat_act();              ## muestra de datos
      $dif_t = $mues_t - $ini_ses_t;    ## diferencia de tiempo entre muestras
      $dif_d = $mues_d - $ini_ses_d;    ## diferencia de datos entre muestras


      if ($dif_t >= $ses_t)             ## superado el tiempo de sesion
      {
        $n_ses++;                   ## una sesion mas
        guar_cont();                ## guardamos contador en fichero
        $nue_ses = 1;               ## es nueva sesion

        $ini_ses_t += $ses_t;       ## instante de inicio de la nueva session
        $ini_ses_d = $mues_d;       ## datos transferidos al iniciarse la sesion

        impri ("+1 = $n_ses \t Tiempo");

        $mues_t_sig = $ini_ses_t + $p_mues;     ## muestra de tiempo siguiente
      }
      elsif ($dif_d >= $ses_d)          ## superados los datos de sesion
      {
        $inc_n_ses = int ($dif_d / $ses_d); ## sesiones equivalentes
        $n_ses += $inc_n_ses;               ## anadimos incremento de sesiones
        guar_cont();                        ## guardamos contador en fichero
        $nue_ses = 1;                       ## es nueva sesion

        $ini_ses_t = ($mues_t + $mues_t_ant) / 2; ## estimamos que los datos se
                                              ## superaron a mitad del intervalo

        $dec_d = $dif_d % $ses_d;           ## decremento de datos
        $ini_ses_d = $mues_d - $dec_d;      ## datos al iniciarse la sesion

        impri ("+$inc_n_ses = $n_ses \t Datos");

        $mues_t_sig = $ini_ses_t + $p_mues;     ## muestra de tiempo siguiente
      }
      else                              ## no superados tiempo ni datos
      {
        $mues_t_sig = $mues_t + $p_mues;        ## muestra de tiempo siguiente
      }

    }
    else                ## no estaba conectado -> acaba de conectarse
    {
      $n_ses++;                     ## una sesion mas
      guar_cont();                  ## guardamos contador en fichero
      $nue_ses = 1;                 ## es nueva sesion

      $ini_ses_t = ($mues_t + $mues_t_ant) / 2; ## estimamos a mitad del interv.
      $ini_ses_d = 0;               ## datos transferidos al iniciarse la sesion

      impri ("+1 = $n_ses \t Iniciada conexion");

      $mues_t_sig = $mues_t + $p_mues;          ## muestra de tiempo siguiente
    }


    ## Informacion en pantalla
    if (
         (($mues_t - $t_imp) >= 0.9)    ## refrescamos pantalla cada 0'9 seg.
         or
         $nue_ses                       ## o cuando hay nueva sesion
       )
    {
      ## Tiempo
      $minus = int ($dif_t / 60);     ## minutos
      $segs = $dif_t % 60;            ## segundos

      ## Datos
      $dats = ($dif_d >= 10 * 1024**2)  ? sprintf ("%d MB",    $dif_d / 1024**2)
              : ($dif_d >= 1000 * 1024) ? sprintf ("%.01f MB", $dif_d / 1024**2)
              : ($dif_d >= 10 * 1024) ? sprintf ("%d KB",    $dif_d / 1024)
              : ($dif_d >=  1000 * 1) ? sprintf ("%.01f KB", $dif_d / 1024)
              : sprintf ("%d B", $dif_d);

      ## Porcentage
      $porc_t = int (100 * $dif_t / $ses_t);            ## porcentage de tiempo
      $porc_d = int (100 * $dif_d / $ses_d);            ## porcentage de datos
      $porc = ($porc_t > $porc_d) ? $porc_t : $porc_d;  ## el mayor

      ## Linea a imprimir
      $tex = sprintf ("[%02d:%02d %7s %4s\%]", $minus, $segs, $dats, $porc);
      print "\b"x79, " "x79, "\b"x79,
            "           \t ", $tex;

      ## Tiempo de impresion
      $t_imp = $mues_t;
    }


    ## Cerca de tiempo máximo?
    ($mues_t_sig > ($ini_ses_t + $ses_t))       ## muestrear fuera de sesión
      and $mues_t_sig = $ini_ses_t + $ses_t;    ## muestrear justo al terminar

    $conectado = 1;
  }
  else                  ## no existe la interfaz (= desconectado)
  {
    if ($conectado)     ## estaba conectado -> acaba de desconectar
    {
      impri ("= $n_ses    \t Terminada conexion");
    }
    else                ## no estaba conectado -> sigue desconectado
    {
    }

    $mues_t_sig = $mues_t + $p_mues;        ## muestra de tiempo siguiente

    $conectado = 0;
  }

}



#######################
sub impri               ## imprime en pantalla y en bitácora
{
  my ($tex) = @_;

  my ($s, $m, $h) = localtime;
  print "\b"x79, " "x79, "\b"x79,
        sprintf("[%02d:%02d:%02d]", $h, $m, $s),
        " \t ", $tex, "\n";

  impri_log($tex);
}
#######################
sub impri_log           ## imprime sólo en bitácora
{
  my ($tex) = @_;

  open FLOG, ">> $f_log"
    or die "No puedo abrir fichero de bitacora";
  print FLOG "[", scalar(localtime), "] \t $tex\n";
  close FLOG;
}
#######################
sub dat_act             ## obtiene datos transferidos actuales
{
  my ($dat_sub, $dat_baj);

  open FSUB, "< $int_f_su"
    or die "No puedo abrir fichero de subida";
  chomp ($dat_sub = <FSUB>);
  close FSUB;

  open FBAJ, "< $int_f_ba"
    or die "No puedo abrir fichero de bajada";
  chomp ($dat_baj = <FBAJ>);
  close FBAJ;


  return $dat_sub + $dat_baj;
}
#######################
sub guar_cont           ## guarda contador
{
  $f_cont_tmp = $f_cont . ".tmp";

  open FCONTTMP, "> $f_cont_tmp"
    or die "No puedo abrir fichero temporal de bitacora";
  print FCONTTMP $f_ini_cont, "\n",
                 $n_ses, "\n";
  close FCONTTMP;

  rename $f_cont_tmp, $f_cont
    or die "No puedo renombrar fichero temporal de bitacora";

}
#######################




This website is hosted for free by Freewebs.com - free website. Get your own Free Website now!