• Publicidad

Ejecución de comandos shell en Perl

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Re: Ejecución de comandos shell en Perl

Notapor explorer » 2010-01-14 07:42 @363

Antes de nada, puedes quitar los '\' dentro de los qq(). Así,

qq($asterisk_bin $asterisk_option \"$asterisk_command"\ );

que, además, fíjate que has "escapado" las primeras dobles comillas, pero no las segundas :)

Mejor, lo escribes así:

qq($asterisk_bin $asterisk_option "$asterisk_command");

En cuanto al problema, es fácil de entender...

Estás ejecutando un comando. El bucle for() recoge todas las líneas de la ejecución. Pero lo que hay dentro del bucle es un if(), que, ocurra lo que ocurra, terminará (un exit()). Pues bien... el bucle comienza con la PRIMERA línea del comando, que, si lo miras, son las cabeceras de los comandos. Y ahí no está el texto que estás esperando. Por eso falla, y sale por el else{}.

Soluciones...
1.- Ejecutar los comandos pero con alguna opción, si es posible, para que no saquen esos encabezados. Solo el resultado del comando

2.- Leer la salida como un arreglo o vector y deshacernos del primer elemento (la línea de cabeceras)

3.- Si sabemos que la línea de resultados contiene solo un conjunto de palabras, podemos colocar un next if o meterlo todo dentro de un if() como primera línea del bucle, para descarte cualquier línea que no cumpla con lo que esperamos. Un ejemplo. Si a la hora de pedir un 'sip show registry' sabemos que la columna 'State' solo puede contener los valores de 'Registered' o 'Unregistered', entonces podemos modificar el bucle así (no probado):
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. for ( qx($cmd) ) {
  2.     if (/Registered/ or /Unregistered/) {
  3.         if (/Registered/) {
  4.             print(" El proveedor Gizmo 5 esta registrado. \n");
  5.             exit(0);
  6.         }
  7.         else {
  8.             print(" El proveedor Gizmo 5 no esta registrado en este momento. \n");
  9.             exit(1);
  10.         }
  11.     }
  12. }
  13. warn "ERROR en la ejecución del comando\n";
  14. exit(-1);
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

o quizás también, así (no probado)
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. for ( qx($cmd) ) {
  2.     next if not /egistered/;  # "egistered" es común a las dos palabras
  3.     if (/Registered/) {
  4.         print(" El proveedor Gizmo 5 esta registrado. \n");
  5.         exit(0);
  6.     }
  7.     else {
  8.         print(" El proveedor Gizmo 5 no esta registrado en este momento. \n");
  9.         exit(1);
  10.     }
  11. }
  12. warn "ERROR en la ejecución del comando\n";
  13. exit(-1);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Aunque también podemos modificar el else{} y cambiarlo por un if(), si sabemos la segunda palabra que buscamos (no probado):
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my $return;
  2. for ( qx($cmd) ) {
  3.     if (/Registered/) {
  4.         print(" El proveedor Gizmo 5 esta registrado. \n");
  5.         exit(0);
  6.     }
  7.     if (/Unregistered/) {
  8.         print(" El proveedor Gizmo 5 no esta registrado en este momento. \n");
  9.         exit(1);
  10.     }
  11. }
  12. warn "ERROR en la ejecución del comando\n";
  13. exit(-1);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Publicidad

Re: Ejecución de comandos shell en Perl

Notapor davidin073 » 2010-01-14 07:56 @372

Voy a probar lo que me dices pero creo que sé dónde está el error:

He puesto un print(" $_ \n"); antes del if(); resulta que si el resultado debía ser este:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
Description                              Alarms     IRQ        bpviol     CRC4
Wildcard TDM400P REV E/F Board 5         OK         0          0          0
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


solo muestra esto:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
Description                              Alarms     IRQ        bpviol     CRC4
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Por tanto, es imposible que funcione.
He probado tanto con tu forma:

foreach (qx($cmd)){}

Como con la mía:

foreach (`($cmd)`) {}

y el resultado es el mismo.

No sé por qué sucede eso, no obstante voy a probar lo que me dices.

...

No había leído entero tu comentario. Es cierto lo que dices, encontraré la solución a base de pruebas.

Antes tenía el exit() al final del programa, y había definido la variable al inicio, y esa variable cambiaba o no y se retornaba.

El problema que encontré fue que a pesar de que la variable cambiaba de valor retornaba siempre el valor con el que se inicio, por eso definí la variable y retorné a continuación en cada if() o elsif().

Eejmplo:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my $return=3;
my $d=0;
if($d eq 0){
$return=0;
}
print(" $return \n");
exit($return);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


El ejemplo que me fallaba era otro pero similar, me mostraba la variable return=0 y retornaba 3 o eso es lo que veía; también hay que tener en cuenta que este script lo utilizo para monitorizar Asterisk con Nagios, y éste, a veces si no ejecutas desde el usuario nagios el script no funciona bien. Quizás sea por esto último.

Gracias por tu atención.
davidin073
Perlero nuevo
Perlero nuevo
 
Mensajes: 17
Registrado: 2010-01-13 10:33 @481

Re: Ejecución de comandos shell en Perl

Notapor explorer » 2010-01-14 09:02 @418

El por qué falla ya te lo he explicado en el mensaje anterior: estás procesando solo la primera línea del comando: al entrar en el if(), se sale por un exit() y no le das oportunidad al for() a que procese el resto de líneas.

Por eso te he dado tres soluciones distintas y de la tercera, tres variantes...

Otra cosa es si no las quieres probar, claro. :(
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Ejecución de comandos shell en Perl

Notapor davidin073 » 2010-01-14 10:44 @489

Sí lo he probado, tienes razón, ya te dije.
davidin073
Perlero nuevo
Perlero nuevo
 
Mensajes: 17
Registrado: 2010-01-13 10:33 @481

Re: Ejecución de comandos shell en Perl

Notapor davidin073 » 2010-01-14 14:55 @663

Buenas de nuevo,

el script ya me funciona; al final ha quedado así:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl -w
  2.  
  3. use Getopt::Std;
  4. use strict;
  5.  
  6. my $asterisk_bin="/usr/bin/sudo /usr/sbin/asterisk";
  7. my $asterisk_option="-rx";
  8. my $asterisk_command_version="show version";
  9. my $return;
  10. my $out="";
  11.  
  12. my $cmd = qq($asterisk_bin $asterisk_option "$asterisk_command_version" );
  13. foreach (`($cmd)`) {
  14.   if (/Asterisk/) {
  15.      $out=$_;
  16.      $return=0;
  17.     }
  18. }
  19. if($return==0){
  20.      print(" $out \n");
  21.      exit($return);
  22. }
  23. else{
  24.      print(" Asterisk no esta arrancado \n");
  25.      exit(2);
  26. }
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Aun tengo una duda sobre el funcionamiento de este script; cuando entra por el if() no hay ningún problema; cuando no entra por el if(), al no estar inicializada la variable return no se ejecuta; el caso es que si inicializo esa variable Nagios toma como retorno el valor de retorno.

Mi pregunta es la siguiente: ¿cómo podría mejorar el código para que se ejecute el script cuando no entra por dicho if() sin inicializar la variable return?
davidin073
Perlero nuevo
Perlero nuevo
 
Mensajes: 17
Registrado: 2010-01-13 10:33 @481

Re: Ejecución de comandos shell en Perl

Notapor explorer » 2010-01-14 16:43 @738

No entiendo la pregunta... está un poco lioso lo que dices...

«¿Cómo podría mejorar el código para que se ejecute el script cuando no entra por dicho if() sin inicializar la variable return

El "código", supongo que te refieres al que acabas de publicar, entonces, ¿a cuál te refieres con la palabra script?
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Ejecución de comandos shell en Perl

Notapor davidin073 » 2010-01-14 17:52 @786

Sí, sí, código, script, me refiero a lo mismo. Cuando no entra por el if() no llega a retornar nada porque al no estar inicializada la variable return da error en la condición del if().

Mi problema es que si inicializo me retorna el valor inicializado, no el valor final de la variable. Es extraño pero cierto.

Lo único que se me ha ocurrido hasta ahora es quitar el else{}. Creo que aunque dé error en el if(), seguirá ejecutando el código y retornara el valor 2. ¿No?

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
       if($return==0){
            print(" $out \n");
            exit($return);
       }
       print(" Asterisk no esta arrancado \n");
       exit(2);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Última edición por explorer el 2010-01-14 19:48 @867, editado 1 vez en total
Razón: Ortografía, anglicismos, sintaxis, bloques de código, abreviaturas telefónicas
davidin073
Perlero nuevo
Perlero nuevo
 
Mensajes: 17
Registrado: 2010-01-13 10:33 @481

Re: Ejecución de comandos shell en Perl

Notapor explorer » 2010-01-14 20:01 @875

Sí, si quitas el else{}, siempre se ejecutará la última parte. Si quieres asegurarte de que $return tenga algún valor, pues se lo pones al principio... pongamos... "2".

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. use Getopt::Std;
  6.  
  7. my $asterisk_bin     = '/usr/bin/sudo /usr/sbin/asterisk';
  8. my $asterisk_option  = '-rx';
  9. my $asterisk_command_version = 'show version';
  10. my $return = 2;      # Un valor distinto del habitual
  11. my $out;
  12.  
  13. my $cmd = qq($asterisk_bin $asterisk_option "$asterisk_command_version");
  14.  
  15. for (qx($cmd)) {
  16.     if (/Asterisk/) {
  17.         $out = $_;   # la línea que encontramos
  18.         $return = 0; # el valor de retorno
  19.         last;        # salimos inmediatamente del bucle
  20.     }
  21. }
  22.  
  23. if ( $return == 0) {
  24.      print " $out \n";
  25.      exit(0);
  26. }
  27. else {
  28.      print(" Asterisk no esta arrancado \n");
  29.      exit(2);
  30. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Aunque, se puede hacer más breve:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. use Getopt::Std;
  6.  
  7. my $asterisk_bin             = '/usr/bin/sudo /usr/sbin/asterisk';
  8. my $asterisk_option          = '-rx';
  9. my $asterisk_command_version = 'show version';
  10.  
  11. my $cmd = qq($asterisk_bin $asterisk_option "$asterisk_command_version");
  12.  
  13. for (qx($cmd)) {
  14.     if (/Asterisk/) {
  15.         print;       # la línea que encontramos
  16.         exit(0);     # salimos inmediatamente del bucle, informando
  17.     }
  18. }
  19.  
  20. print(" Asterisk no esta arrancado \n");
  21. exit(2);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Es decir: si puedo salir del programa porque he encontrado lo que quiero, pues salgo inmediatamente. Si todo falla, salgo con otro mensaje de error.

No sé si era esto lo que buscabas.

Para colorear el código Perl, usa el botón Perl que aparece justo encima de la caja de edición de texto, mientras escribes un mensaje. Primero seleccionas el código y luego pulsas el botón.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Ejecución de comandos shell en Perl

Notapor davidin073 » 2010-01-15 05:41 @279

Ok, sí, creo que es eso lo que quiero. Es que, como te dije, si inicializo a 2 no funciona bien, es ilógico pero es así: Nagios, si devuelves un 0 pone el estado a Ok, si devuelves un 1 a Warning, si devuelves un 2 a Critical.

Espero que funcione correctamente de una vez.
Muchas gracias.
davidin073
Perlero nuevo
Perlero nuevo
 
Mensajes: 17
Registrado: 2010-01-13 10:33 @481

Re: Ejecución de comandos shell en Perl

Notapor explorer » 2010-01-15 06:17 @304

Esos valores corresponden muy bien con casi todos los programas que funcionan en los sistemas UNIX, así que me parecen correctos.

Si ves el último ejemplo, es justo lo que hago: no hay variable de retorno, sino que hago un exit() justo cuando sé que debo terminar. Y lo hago con el valor que corresponde a cada situación: o 0 o 2.

En el primer ejemplo del mensaje mío anterior, sí que hay una variable de retorno, que inicializo al peor caso. De esa manera, si el for() falla porque se ejecutó mal el comando o no estaba el asterisk funcionando o no se encontró Registered, siempre entrará en el else{} y devolverá el exit(2). En cambio, si todo fue bien, devolverá un 0.

Los dos ejemplos deben comportarse exactamente igual.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

AnteriorSiguiente

Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 31 invitados