Contar impresiones con Perl

Necesito contar el nº de impresiones que realiza una impresora conectada por USB a un pc con CUPS. Si la impresora estuviera en red podría simplemente conectarme a ella via http y acceder al contador. Si la impresora fuera multifuncional o algo mas decente seguramente tendría una combinación de teclas para imprimir el contador o su configuracion. Pues no, no tiene red y solo tiene 2 botones: el de power y el de reset-job. Para contar las impresiones al final me he decidido por PERL

Cups genera un fichero llamado page_log donde informa de las páginas y copias que genera al imprimir. Por ejemplo una impresión de 3 hojas genera algo parecido a:

RICOH_Aficio_SP_3410DN cliente 341 [17/Apr/2012:15:48:41 +0200] 1 1 - localhost Microsoft PowerPoint - Produzione liquidi.ppt A4 one-sided
RICOH_Aficio_SP_3410DN cliente 341 [17/Apr/2012:15:48:55 +0200] 2 1 - localhost Microsoft PowerPoint - Produzione liquidi.ppt A4 one-sided
RICOH_Aficio_SP_3410DN cliente 341 [17/Apr/2012:15:49:01 +0200] 3 1 - localhost Microsoft PowerPoint - Produzione liquidi.ppt A4 one-sided

Lo que nos interesa es que vemos el "1 1", "2 1", "3 1" que significa que imprime respectivamente: 1 copia de la pagina 1, una copia de la página 2 y una copia de la página 3. ¿Que hay que hacer? pues simplemente sumar la columna de copias del page_log para cada impresora.

En perl, (mi segundo script yuhuuu) lo he conseguido de la siguiente manera:

#!/usr/bin/env perl
use strict;
use warnings;

# resultado
my %printings;

# queremos un parametro y que exista el fichero
#my $input = shift or die "Need input file";
#open(PAGELOG, "<", $input) or die "Cannot open $input: $! \n";

# analizamos archivo
#while (<PAGELOG>)
while (<STDIN>)
{
  chomp;
  (my $printer, my $user, undef, my $data, undef,undef, my $copies, undef) = split(/\ /,$_,8);

  if (exists $printings{"$printer"})
  {
    $printings{"$printer"} += $copies;
  }
  else
  {
    $printings{"$printer"} = $copies;
  }
}
#close(PAGELOG);

#imprimir el resultado
foreach my $elem (keys %printings)
{
   print "$elem: $printings{$elem} \n"

}

1ero había puesto que se tenia que pasar el archivo page_log como parámetro por lo que hacia un shift y un open del archivo, pero después pensé que mejor hacer que el programa pille la info de la entrada estándar, o sea:
cat page_log | script.pl
ya que de esta manera si quiero limitar la cuenta de un més puedo hacer un:
cat page_log | grep Apr/2012 | script.pl
VERSION 2

Cambio para que el ordenador me envíe por email los contadores de la impresora de cada més.

1. Modificación del logrotate.d/cups para que guarde los registros el tiempo suficiente, por ejemplo, haga la rotación semanalmente y guarde 8 registros.

2. Unificamos los diferentes registros de page_log en uno
find /var/log/cups -name "page_log*.gz" -mtime -30 -exec zcat '{}' >> /tmp/pages \;
3. Modificamos el script en perl para que acepte como parámetro que mes debe contabilizar.

#!/usr/bin/env perl
use strict;
use warnings;

# resultado
my %printings;

# mapa de meses
my %months = (
   1 => "Jan",
   2 => "Feb",
   3 => "Mar",
   4 => "Apr",
   5 => "May",
   6 => "Jun",
   7 => "Jul",
   8 => "Ago",
   9 => "Sep",
   10 => "Oct",
   11 => "Nov",
   12 => "Dec"
);

my $month = shift or die "Need month number";

# analizamos archivo
while (<STDIN>)
{
  chomp;
  (my $printer, my $user, undef, my $data, undef,undef, my $copies, undef) = split(/\ /,$_,8);

  if ($data =~ /$months{"$month"}/)
  {
     if (exists $printings{"$printer"})
     {
        $printings{"$printer"} += $copies;
     }
     else
     {
        $printings{"$printer"} = $copies;
     }
  }
}

#imprimir el resultado
print "-------------------\n";
print $months{"$month"}." PRINTINGS\n";
print "-------------------\n";
foreach my $elem (keys %printings)
{
   print "   $elem: $printings{$elem} \n";
}
print "-------------------\n";

4. Montamos el script que lance la contabilización del mes anterior y la pase por mail:
#!/bin/bash

month=$(date +%m)
(( month -= 1 ))

rm -f /tmp/pages
find /var/log/cups -name "page_log*.gz" -mtime -30 -exec zcat '{}' >> /tmp/pages \;
cat /tmp/pages | script.pl $month | mail -s PRINTINGS admin@example.org

5. Programar que se ejecute el punto 4 cada día 1 de cada mes con un crontab.

Comentarios

Antonio ha dicho que…
Muy interesante, pero ¿Cómo se cambia logrotate?
Beavies ha dicho que…
normalmente en /etc/logrotate.d/ hay una serie de archivos que especifica como se hacen copias, con que periodicidad, cuantas se guardan, etc.

Se trata pues de crear o modificar un archivo alli dentro