Perl en Español

  1. Home
  2. Tutoriales
  3. Foro
  4. Artículos
  5. Donativos
  6. Publicidad
 

Parseo de archivo

 
Publicar nuevo tema   Responder al tema    Foros de discusión -> Básico
Mensaje Mie Oct 15, 2008 7:21 am
natxo
Perlero Nuevo
Perlero Nuevo
Registrado: 09 Ago 2007
Mensajes: 26
Ubicación: Países Bajos
Parseo de archivo Responder citando

Tengo que verificar que ciertas tareas programadas (scheduled tasks) de un servidor win2k3 se ejecuten correctamente y si no, recibir un aviso. Usamos Nagios, así que me he puesto a escribir un plugin (no he visto nada en nagiosexchange).

Hay dos maneras de ver si se han ejecutado bien las tareas: interactivamente (no es lo que quiero) o con el comando schtasks.

He visto que puedo sacar la información a un archivo con este comando:
bash:
schtasks /query /fo list /v > dump.txt


El archivo es así:

Código:
HostName:                             SERVER
TaskName:                             jobname
Next Run Time:                        09:00:00, 16-10-2008
Status:                               
Logon Mode:                           Interactive only
Last Run Time:                        09:00:00, 07-10-2008
Last Result:                          0
Creator:                              user
Schedule:                             At 09:00 every day, starting 18-01-2008
Task To Run:                          C:\Program Files\program\exe.exe "jobname.xml" -l"C:\Documents and Settings\user\Application Data\program\log.log" -s"C:\Documents and Settings\user\Application Data\pgrogram\program.xml"
Start In:                             N/A
Comment:                              N/A
Scheduled Task State:                 Enabled
Scheduled Type:                       Daily
Start Time:                           09:00:00
Start Date:                           18-01-2008
End Date:                             N/A
Days:                                 Everyday
Months:                               N/A
Run As User:                          domain\administrator
Delete Task If Not Rescheduled:       Disabled
Stop Task If Runs X Hours and X Mins: Disabled
Repeat: Every:                        Disabled
Repeat: Until: Time:                  Disabled
Repeat: Until: Duration:              Disabled
Repeat: Stop If Still Running:        Disabled
Idle Time:                            Disabled
Power Management:                     Disabled


A continuación sigue otra tarea con el mismo formato, y otra ...

Necesito sacar la información de TaskName, Status y Last Result. Si sólo tuviera una tarea, sería muy simple, pero no sé me ocurre cómo guardar los resultados para luego utilizarlos. Cómo puedo leer trozos de un archivo (desde la línea Hostname hasta Power Management), y luego otra vez y otra y otra, tantas veces como sea necesario.

No me hace falta que me hagan la tarea Smile , sólo necesito un empujón en la dirección adecuada porque la verdad, no se me ocurre cómo hacerlo.
Mensaje Mie Oct 15, 2008 7:46 am
kidd
Creador de Perl en Español
Creador de Perl en Español
Registrado: 15 Oct 2003
Mensajes: 1390
Ubicación: México
Responder citando

Hola,

En CPAN podrás encontrar varios módulos relacionados con Nagios, alguno de ellos te podría ayudar en lo que necesitas:
http://search.cpan.org/search?query=nagios&mode=all

Saludos
Mensaje Mie Oct 15, 2008 9:44 am
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4239
Ubicación: Valladolid, España
Responder citando

Como es un fichero de texto, puedes probar a sacar las líneas con patrones de búsqueda:

Perl:
if ( $linea =~ /TaskName:\s+(.*)/ ) {
    print "Tarea $1\n";
}
Mensaje Mie Oct 15, 2008 10:23 am
natxo
Perlero Nuevo
Perlero Nuevo
Registrado: 09 Ago 2007
Mensajes: 26
Ubicación: Países Bajos
Responder citando

Sí, claro Smile

El problema es la repetición de jobs/tareas. O sea, cada tarea es un párrafo del archivo de texto cuya primera línea es Hostname y la última 'Power Management' y así tantos párrafos como jobs haya definidos en el servidor. Si śolo hubiera un párrafo, sería trivial hacer algo así como indicas. Mi problema es que no sé todavía cómo parsear un párrafo, ver si hay algún error, pasar al siguiente párrafo, etc. Creo que voy a crear un hash por cada tarea programada y luego sacaré los resultados con los códigos de error que espera Nagios (0, 1, 2, ó 3).

Se nota que no soy un programador, soy el sysadmin de la empresa Smile
Mensaje Mie Oct 15, 2008 11:08 am
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4239
Ubicación: Valladolid, España
Responder citando

Con
Perl:
#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;

open MYLOG, '<kk.log' or die "No pude abrir el fichero de log: $!\n";

while (<MYLOG>) {
    if (/^(HostName|TaskName|Status|Last Result):\s+(.*)/) {
        printf "%-12s: %s\n", $1, $2;
        print "\n" if $1 eq 'Last Result';
    }
}

close MYLOG;
y el fichero de entrada

Código:
HostName:                             SERVER
TaskName:                             jobname
Next Run Time:                        09:00:00, 16-10-2008
Status:
Logon Mode:                           Interactive only
Last Run Time:                        09:00:00, 07-10-2008
Last Result:                          0
Creator:                              user
Schedule:                             At 09:00 every day, starting 18-01-2008
Task To Run:                          C:\Program Files\program\exe.exe "jobname.xml" -l"C:\Documents and Settings\user\Application Data\program\log.log" -s"C:\Documents and Settings\user\Appl
Start In:                             N/A
Comment:                              N/A
Scheduled Task State:                 Enabled
Scheduled Type:                       Daily
Start Time:                           09:00:00
Start Date:                           18-01-2008
End Date:                             N/A
Days:                                 Everyday
Months:                               N/A
Run As User:                          domain\administrator
Delete Task If Not Rescheduled:       Disabled
Stop Task If Runs X Hours and X Mins: Disabled
Repeat: Every:                        Disabled
Repeat: Until: Time:                  Disabled
Repeat: Until: Duration:              Disabled
Repeat: Stop If Still Running:        Disabled
Idle Time:                            Disabled
Power Management:                     Disabled
HostName:                             SERVER2
TaskName:                             jobname2
Next Run Time:                        09:00:00, 16-10-2008
Status:                               Ok
Logon Mode:                           Interactive only
Last Run Time:                        09:00:00, 07-10-2008
Last Result:                          1
Creator:                              user
Schedule:                             At 09:00 every day, starting 18-01-2008
Task To Run:                          C:\Program Files\program\exe.exe "jobname.xml" -l"C:\Documents and Settings\user\Application Data\program\log.log" -s"C:\Documents and Settings\user\Appl
Start In:                             N/A
Comment:                              N/A
Scheduled Task State:                 Enabled
Scheduled Type:                       Daily
Start Time:                           09:00:00
Start Date:                           18-01-2008
End Date:                             N/A
Days:                                 Everyday
Months:                               N/A
Run As User:                          domain\administrator
Delete Task If Not Rescheduled:       Disabled
Stop Task If Runs X Hours and X Mins: Disabled
Repeat: Every:                        Disabled
Repeat: Until: Time:                  Disabled
Repeat: Until: Duration:              Disabled
Repeat: Stop If Still Running:        Disabled
Idle Time:                            Disabled
Power Management:                     Disabled
HostName:                             SERVER3
TaskName:                             jobname3
Next Run Time:                        09:00:00, 16-10-2008
Status:                               No Ok
Logon Mode:                           Interactive only
Last Run Time:                        09:00:00, 07-10-2008
Last Result:                          12
Creator:                              user
Schedule:                             At 09:00 every day, starting 18-01-2008
Task To Run:                          C:\Program Files\program\exe.exe "jobname.xml" -l"C:\Documents and Settings\user\Application Data\program\log.log" -s"C:\Documents and Settings\user\Appl
Start In:                             N/A
Comment:                              N/A
Scheduled Task State:                 Enabled
Scheduled Type:                       Daily
Start Time:                           09:00:00
Start Date:                           18-01-2008
End Date:                             N/A
Days:                                 Everyday
Months:                               N/A
Run As User:                          domain\administrator
Delete Task If Not Rescheduled:       Disabled
Stop Task If Runs X Hours and X Mins: Disabled
Repeat: Every:                        Disabled
Repeat: Until: Time:                  Disabled
Repeat: Until: Duration:              Disabled
Repeat: Stop If Still Running:        Disabled
Idle Time:                            Disabled
Power Management:                     Disabled
HostName:                             SERVER4
TaskName:                             jobname41
Next Run Time:                        09:00:00, 16-10-2008
Status:                               -1
Logon Mode:                           Interactive only
Last Run Time:                        09:00:00, 07-10-2008
Last Result:                          023
Creator:                              user
Schedule:                             At 09:00 every day, starting 18-01-2008
Task To Run:                          C:\Program Files\program\exe.exe "jobname.xml" -l"C:\Documents and Settings\user\Application Data\program\log.log" -s"C:\Documents and Settings\user\Appl
Start In:                             N/A
Comment:                              N/A
Scheduled Task State:                 Enabled
Scheduled Type:                       Daily
Start Time:                           09:00:00
Start Date:                           18-01-2008
End Date:                             N/A
Days:                                 Everyday
Months:                               N/A
Run As User:                          domain\administrator
Delete Task If Not Rescheduled:       Disabled
Stop Task If Runs X Hours and X Mins: Disabled
Repeat: Every:                        Disabled
Repeat: Until: Time:                  Disabled
Repeat: Until: Duration:              Disabled
Repeat: Stop If Still Running:        Disabled
Idle Time:                            Disabled
Power Management:                     Disabled
sale
Código:
HostName    : SERVER
TaskName    : jobname
Status      :
Last Result : 0

HostName    : SERVER2
TaskName    : jobname2
Status      : Ok
Last Result : 1

HostName    : SERVER3
TaskName    : jobname3
Status      : No Ok
Last Result : 12

HostName    : SERVER4
TaskName    : jobname41
Status      : -1
Last Result : 023
Por eso Perl es perfecto para los administradores de sistemas...

Incluso si quieres ejecutarlo desde la línea de comandos, así:
bash:
filtra.pl kk.log

puedes dejarlo en
Perl:
#!/usr/bin/perl -n
if (/^(HostName|TaskName|Status|Last Result):\s+(.*)/) {
    printf "%-12s: %s\n", $1, $2;
    print "\n" if $1 eq 'Last Result';
}


Incluso, si quieres, sin hacer ningún programa:
bash:
perl -nle '/^(HostName|TaskName|Status|Last Result):\s+(.*)/ and printf "%-12s: %s\n", $1, $2' kk.log
Mensaje Lun Oct 20, 2008 8:56 am
natxo
Perlero Nuevo
Perlero Nuevo
Registrado: 09 Ago 2007
Mensajes: 26
Ubicación: Países Bajos
Responder citando

explorer:

A veces uno se enciega con una solución que no tiene sentido. Al final lo he hecho así:

Perl:
#!perl

# define the file where we'll dump the logfile of schtasks
my $jobfile = "c:/tmp/dump.txt" ;
unlink ($jobfile) or die "cannot remove $jobfile: $!\n" ;

# first run schtasks /query /fo /list /v and dump everything to a file
my $schtasks_dump = `schtasks /query /fo list /v > $jobfile`;

# open file RO, or croak
open (JOBS, $jobfile) or die "couldn't open $jobfile: $!\n";

my $count = 0;
my $ok = 0;
# parse file, if string Last Result is not 0 (success), croak
while (<JOBS>) {
    if (/^(Last Result:)\s+(.*)$/) {
        # count how many jobs there are, we'll use this later
        $count++;
        # if an error level is not 0, croak
        if ($2 != 0) {
            print "WARNING: problem with a scheduled job\n";
            exit 1;
        }
        # now we count how many jobs have run fine
        else {
            $ok++;
        }
    }
}

if ($count = $ok) {
    print "OK: all scheduled tasks have run fine\n";
    exit 0;
}
else {
    # if there is something wrong, give unkonw and errolevel 3
    print "UNKONWN: something else went wrong\n";
    exit 3;
}


Nagios espera ciertos resultados: 0 => OK; 1 => WARNING; 2 => CRITICAL; 3 => UNKNOWN.

Me estaba empecinando en meter cada párrafo del log en un hash para luego sacarlo y hacer no sé qué. Con esta solución (ya lo tengo en producción) si falla algún job, Nagios me avisa (me da igual cuál, tengo que darme de alta en el servidor de todos modos para activarlo).

Gracias por darme un empujón en la dirección correcta Wink
Mensaje Lun Oct 20, 2008 10:41 am
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4239
Ubicación: Valladolid, España
Responder citando

Hay un error (creo) en el código:
Perl:
if ($count = $ok) {

Estás haciendo una asignación, no una comparación.

Salvo que quieras saber cuándo $ok es distinto de cero, lo normal es que una asignación dentro de una condición sea un error. Debería ser
Perl:
if ($count == $ok) {
Mensaje Lun Oct 20, 2008 10:48 am
natxo
Perlero Nuevo
Perlero Nuevo
Registrado: 09 Ago 2007
Mensajes: 26
Ubicación: Países Bajos
Responder citando

explorer escribió:
Hay un error (creo) en el código:
Perl:
if ($count = $ok) {

Estás haciendo una asignación, no una comparación.

Salvo que quieras saber cuándo $ok es distinto de cero, lo normal es que una asignación dentro de una condición sea un error. Debería ser
Perl:
if ($count == $ok) {


curioso, en mi código está como lo pones tú. No sé qué ha podido pasar durante el copiar/pegar.
Mensaje Lun Oct 20, 2008 11:02 am
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4239
Ubicación: Valladolid, España
Responder citando

Perl:
#!perl
use strict;
use warnings;
use diagnostics;

# first run schtasks /query /fo /list /v and dump everything to a file
open (JOBS, "schtasks /query /fo list /v |") or die "couldn't exec schtasks: $!\n";

# Counters
my $count = 0;
my @count = ();

# parse file, if string Last Result is not 0 (success), croak
while (<JOBS>) {
    if (/^Last Result:\s+(.*)$/) {
        # count how many jobs there are, we'll use this later
        $count++;

        # By type
        $count[$1]++;
    }
}

close JOBS;

if ($count[1]) {
    warn "WARNING: problem with $count[1] scheduled jobs\n";
    exit 1;
}

if ($count[0] == $count) {
    warn "OK: all scheduled tasks have run fine\n";
    exit 0;
}
else {
    # if there is something wrong, give unkonw and errolevel 3
    warn "UNKONWN: something else went wrong\n";
    exit 3;
}

__END__

Actualización: Ahora no recuerdo si en Windows funcionan los pipes de la misma manera que en Unix/Linux.

Ultima edición por explorer el Lun Oct 20, 2008 1:08 pm, editado 1 vez
Mensaje Lun Oct 20, 2008 12:00 pm
RockoX
Perlero Nuevo
Perlero Nuevo
Registrado: 20 Ago 2008
Mensajes: 10
Responder citando

explorer escribió:

Actualización: Ahora no recuerdo si en Windows funcionan los pipes de la misma manera que en Unix/Linux.


Si, funcionan igual :
Código:
tasklist | find /i "explorer.exe"
Publicar nuevo tema   Responder al tema    Foros de discusión -> Básico Todas las horas son GMT - 6 Horas
Página 1 de 1



Powered by phpBB © 2001, 2005 phpBB Group