• Publicidad

Ejecutar comandos en distintos hilos

¿Ya sabes lo que es una referencia? Has progresado, el nível básico es cosa del pasado y ahora estás listo para el siguiente nivel.

Ejecutar comandos en distintos hilos

Notapor estudiante » 2014-06-05 05:53 @286

Hola a todos y gracias por atenderme.

Estoy intentando hacer un programa en Perl que me permita realizar ping a un rango determinado de IP. Estaba pensando, en vez de ir haciendo ping de una a una, dividir el nº de IP en 5 listas y pasarle dichas listas a 5 hilos para que cada uno se encarge de realizar el ping a todos los componentes de su lista. El problema que tengo es que me sale el siguiente error:

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
No ha hecho ping 192.168.1.1
No ha hecho ping 192.168.1.6
Comienza la ejecuci├│n del hilo
Thread 1 terminated abnormally: Undefined subroutine &main::0 called at pingh.pl line 73, <STDIN> line 2.
No ha hecho ping 192.168.1.2
No ha hecho ping 192.168.1.7
Can't locate object method "create" via package "trheads" (perhaps you forgot to load "trheads"?) at pingh.pl line 74, <STDIN>
Perl exited with active threads:
        0 running and unjoined
        1 finished and unjoined
        0 running and detached
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

El código que uso es el siguiente y lo uso en Windows XP:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!c:\perl\bin\perl.exe
  2. use Net::Ping::External qw(ping);
  3. use threads;
  4. use Config;  
  5.  
  6. $Config{useithreads} or die('Recompile Perl with threads to run this program.');
  7.  
  8. print "Introduce IP de la red desde donde empezar: ";
  9. my $primera_ip = <STDIN>;
  10. chop($primera_ip);
  11. print "Introduce IP donde terminar: ";
  12. my $ultima_ip;
  13. $ultima_ip=<STDIN>;
  14. chop($ultima_ip);
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

Para simplificar el código no pongo cómo se incluyen en cada una de las listas @lista1, @lista2, ..., @lista5
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my ($hilo1) = threads->create(&realizarping(@lista1));
  2. my ($hilo2) = trheads->create(&realizarping(@lista2));
  3. my ($hilo3) = trheads->create(&realizarping(@lista3));
  4. my ($hilo4) = threads->create(&realizarping(@lista4));
  5. my ($hilo5) = threads->create(&realizarping(@lista5));
  6.  
  7. my @resultado1 = $hilo1->join();
  8. my @resultado2 = $hilo2->join();
  9. my @resultado3 = $hilo3->join();
  10. my @resultado4 = $hilo4->join();
  11. my @resultado5 = $hilo5->join();
  12.  
  13. sub realizarping{
  14.     print("Comienza la ejecución del hilo\n");
  15.  
  16.     foreach $direccion_ip (@_){
  17.          my $alive = ping(host =>$direccion_ip, count => 3,timeout => 1 );
  18.         if ($alive){
  19.             print "Ping conseguido en $direccion_ip\n";
  20.         } else {
  21.             print "No ha hecho ping $direccion_ip\n";
  22.         };
  23.     }
  24.     return ( 0 , 'Finalización correcta');
  25. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
estudiante
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2013-02-06 07:36 @358

Publicidad

Re: Ejecutar comandos en distintos hilos

Notapor explorer » 2014-06-05 06:29 @312

Bienvenido a los foros de Perl en Español, estudiante.

Prueba a colocar un '\' delante de los '&', dentro de los create().

El método create() espera una referencia a una subrutina. Si pones solamente '&' lo que estás haciendo es llamar a la subrutina, en ese momento.

Y los argumentos deben ir aparte. Quedaría algo así:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my($hilo1) = threads->create(\&realizarping, @lista1);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Más información, en threads.

P.D.: Los paréntesis alrededor de $hilo1 son importantes, para que threads sepa que realizarping() devuelve una lista, no un escalar.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Ejecutar comandos en distintos hilos

Notapor estudiante » 2014-06-05 07:22 @348

Hola, explorer, aún colocando la barra invertida dentro del create() me sigue dando el mismo fallo.

Me he dado cuenta que el primer fallo empieza en la línea 73, creo que la numeración del primer código que te envié está mal. Esta segunda está correcta.

También tengo la siguiente duda: cuando se ejecuta la línea 73, no pasa a ejecutar la línea 74 hasta que termina de ejecutar el procedimiento realizarping(), o pasa a ejecutar la línea 74 aunque no haya acabado el procedimiento realizarping.

Un saludo.

73 my ($hilo1) = threads->create(\&realizarping(@lista1));
74 my ($hilo2) = trheads->create(\&realizarping(@lista2));
75 my ($hilo3) = trheads->create(\&realizarping(@lista3));
76 my ($hilo4) = threads->create(\&realizarping(@lista4));
77 my ($hilo5) = threads->create(\&realizarping(@lista5));

79 my @resultado1 = $hilo1->join();
80 my @resultado2 = $hilo2->join();
81 my @resultado3 = $hilo3->join();
82 my @resultado4 = $hilo4->join();
83 my @resultado5 = $hilo5->join();

87 sub realizarping{
88 print("Comienza la ejecución del hilo\n");
89
90 foreach $direccion_ip (@_){
91 my $alive = ping(host =>$direccion_ip, count => 1,timeout => 1 );
92 if ($alive){print "Ping conseguido en $direccion_ip\n";
93 }else{print "No ha hecho ping $direccion_ip\n";
94 };
95 }
96 return ( 0 , 'Finalización correcta');
97 }

salida que da con el error:

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
Introduce IP de la red desde donde empezar: 192.168.1.1
Introduce IP donde terminar: 192.168.1.5
Comienza la ejecuci├│n del hilo
No ha hecho ping 192.168.1.1
Comienza la ejecuci├│n del hilo
Thread 1 terminated abnormally: Not a CODE reference at pingh.pl line 73, <STDIN> line 2.
No ha hecho ping 192.168.1.2
Can't locate object method "create" via package "trheads" (perhaps you forgot to load "trheads"?) at pingh.pl line 74, <STDIN>
Perl exited with active threads:
        0 running and unjoined
        1 finished and unjoined
        0 running and detached
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4
estudiante
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2013-02-06 07:36 @358

Re: Ejecutar comandos en distintos hilos

Notapor explorer » 2014-06-05 08:43 @405

Por favor, vuelve a repasar mi contestación anterior: no has escrito bien las líneas 73 a 77.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Ejecutar comandos en distintos hilos

Notapor explorer » 2014-06-05 13:59 @624

A propósito... hay al menos un módulo en CPAN que hace lo que quieres: Net::Ping::Network.

Puedes mirar su código fuente, para que te sirva de inspiración.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Ejecutar comandos en distintos hilos

Notapor estudiante » 2014-06-06 03:29 @187

Hola, explorer, gracias por la ayuda. Efectivamente estaba colocando mal las instrucciones 73 a 77. Me concentraba solo en los paréntesis de $hilo1, $hilo2... y lo que estaba mal realmente era el paso de los parámetros y que la palabra threads estaba mal escrita :oops: . Ahora funciona correctamente. Miraré de todas forma el módulo que me indicas.

Un saludo y gracias de nuevo.
estudiante
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2013-02-06 07:36 @358

Re: Ejecutar comandos en distintos hilos

Notapor explorer » 2014-06-06 04:59 @249

estudiante escribiste:y que la palabra threads estaba mal escrita
¡Ahí va! Ni me di cuenta :)
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Ejecutar comandos en distintos hilos

Notapor estudiante » 2014-06-06 06:21 @306

Hola de nuevo, explorer.

Tengo otro problema con el código: no me escribe por pantalla todas las IP por las que pasa el bucle. No sé si es por el Windows o por que hay algo mal, es muy raro :shock:

Si te fijas hay IP que no salen. Ejemplo: 192.168.1.13. Y debería de haber pasado por ella. Te adjunto el código de nuevo y su correspondiente salida por pantalla.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.   @lista1=("192.168.1.1","192.168.1.2","192.168.1.3","192.168.1.4");
  2.   @lista2=("192.168.1.5","192.168.1.6","192.168.1.7","192.168.1.8");
  3.  
  4.   @lista3=("192.168.1.9","192.168.1.10","192.168.1.11","192.168.1.12");
  5.   @lista4=("192.168.1.13","192.168.1.14","192.168.1.15","192.168.1.16");
  6.  
  7.   @lista5=("192.168.1.17","192.168.1.18","192.168.1.19","192.168.1.20");
  8.  
  9.   print "@lista1\n";
  10.   print "@lista2\n";
  11.   print "@lista3\n";
  12.   print "@lista4\n";
  13.   print "@lista5\n";
  14.  
  15.   my ($hilo1) = threads->create(\&realizarping,@lista1);
  16.   my ($hilo2) = threads->create(\&realizarping,@lista2);
  17.   my ($hilo3) = threads->create(\&realizarping,@lista3);
  18.   my ($hilo4) = threads->create(\&realizarping,@lista4);
  19.   my ($hilo5) = threads->create(\&realizarping,@lista5);
  20.  
  21.  
  22.   my @resultado1 = $hilo1->join();
  23.   my @resultado2 = $hilo2->join();
  24.   my @resultado3 = $hilo3->join();
  25.   my @resultado4 = $hilo4->join();
  26.   my @resultado5 = $hilo5->join();
  27.  
  28.  
  29.  
  30.   sub realizarping{
  31.     print("Comienza la ejecución del hilo\n");
  32.        
  33.         foreach $direccion_ip (@_){
  34.             print ".............................................$direccion_ip\n";
  35.             my $alive = ping(host =>$direccion_ip, count => 4,timeout => 3 );
  36.                 if ($alive){
  37.                    print "Ping conseguido en $direccion_ip\n";
  38.             }else{
  39.                     print "No ha hecho ping $direccion_ip\n";
  40.              };
  41.         }      
  42.     return ( 0 , 'Finalización correcta');
  43. }
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

La salida que me da:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
192.168.1.1 192.168.1.2 192.168.1.3 192.168.1.4
192.168.1.5 192.168.1.6 192.168.1.7 192.168.1.8
192.168.1.9 192.168.1.10 192.168.1.11 192.168.1.12
192.168.1.13 192.168.1.14 192.168.1.15 192.168.1.16
192.168.1.17 192.168.1.18 192.168.1.19 192.168.1.20
Comienza la ejecuci├│n del hilo
.............................................192.168.1.1
Comienza la ejecuci├│n del hilo
.............................................192.168.1.5
Comienza la ejecuci├│n del hilo
.............................................192.168.1.9
Comienza la ejecuci├│n del hilo
.............................................192.168.1.17
No ha hecho ping 192.168.1.9
.............................................192.168.1.10
No ha hecho ping 192.168.1.18
No ha hecho ping 192.168.1.14
.............................................192.168.1.15
.............................................192.168.1.19
No ha hecho ping 192.168.1.19
No ha hecho ping 192.168.1.11
.............................................192.168.1.20
No ha hecho ping 192.168.1.7
.............................................192.168.1.12
.............................................192.168.1.8
No ha hecho ping 192.168.1.8
No ha hecho ping 192.168.1.4
No ha hecho ping 192.168.1.20
No ha hecho ping 192.168.1.16
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4
estudiante
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2013-02-06 07:36 @358

Re: Ejecutar comandos en distintos hilos

Notapor explorer » 2014-06-06 09:43 @446

Pues... no lo sé...

En mi Linux, sí que me funciona.

Esta es mi versión:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use v5.14;
  3. use Net::Ping::External qw(ping);
  4. use threads;
  5.  
  6. my $IP_BASE    = '91.121.132';
  7. my $IP_PRIMERO = 1;
  8. my $IP_LARGO   = 20;
  9.  
  10. my @hilos;
  11.  
  12. ### Generación de listas de IP, en bloques de 5
  13. for (my $j = $IP_PRIMERO; $j < $IP_PRIMERO + $IP_LARGO; $j += 4) {
  14.  
  15.     my @lista_IP = map { "$IP_BASE.$_" } $j .. $j + 3;
  16.  
  17.     my $hilo = threads->create(\&realizarping,@lista_IP);
  18.    
  19.     push @hilos, $hilo;
  20. }
  21.  
  22. for my $hilo (@hilos) {
  23.     $hilo->join();
  24. }
  25.  
  26. sub realizarping{
  27.  
  28.     say "Inicio de hilo (@_)";
  29.     for my $IP (@_) {
  30.         my $alive = ping(host =>$IP, count => 4,timeout => 3 );
  31.  
  32.         printf "%-16s %s responde\n", $IP, $alive ? 'sí' : 'no';
  33.     }
  34.     say "Fin de hilo"
  35. }
  36.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Ejemplo de salida:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
$ perl ping_threads.pl
Inicio de hilo (91.121.132.1 91.121.132.2 91.121.132.3 91.121.132.4)
Inicio de hilo (91.121.132.5 91.121.132.6 91.121.132.7 91.121.132.8)
Inicio de hilo (91.121.132.9 91.121.132.10 91.121.132.11 91.121.132.12)
Inicio de hilo (91.121.132.17 91.121.132.18 91.121.132.19 91.121.132.20)
Inicio de hilo (91.121.132.13 91.121.132.14 91.121.132.15 91.121.132.16)
91.121.132.5     sí responde
91.121.132.9     sí responde
91.121.132.17    sí responde
91.121.132.18    sí responde
91.121.132.10    sí responde
91.121.132.11    sí responde
91.121.132.12    sí responde
Fin de hilo
91.121.132.1     no responde
91.121.132.13    no responde
91.121.132.14    sí responde
91.121.132.6     no responde
91.121.132.19    no responde
91.121.132.15    sí responde
91.121.132.7     sí responde
91.121.132.20    sí responde
Fin de hilo
91.121.132.16    sí responde
Fin de hilo
91.121.132.8     sí responde
Fin de hilo
91.121.132.2     no responde
91.121.132.3     sí responde
91.121.132.4     no responde
Fin de hilo
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

De todas maneras, el uso de threads es siempre problemático: en muchas ocasiones te encuentras que el perl que tienes instalado en tu máquina no está compilado con soporte de Threads:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
$ perl ping_threads.pl
This Perl not built to support threads
Compilation failed in require at ping_threads.pl line 2.
BEGIN failed--compilation aborted at ping_threads.pl line 2.
$ perl -V|fgrep -i threads
    useithreads=undef, usemultiplicity=undef
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4
(sacado de uno de mis servidores con Debian)

A veces se puede instalar de forma sencilla:
$ apt-get install libthreads-perl

pero otras veces no. Y luego está el tema del sistema operativo. Linux no es lo mismo que Windows. Y no es lo mismo los hilos de Perl que el del sistema operativo.

En el documento perldoc perlthrtut tienes una explicación de esto:
Es muy importante recordar cuando estemos gestionando hilos Perl, que los hilos Perl no son hilos X, para todos los valores de X. No son hilos POSIX, o hilos Dec o hilos Green de Java, o hilos Windows. Hay similitudes, y los conceptos generales son los mismos, pero si empieza a mirar los detalles de la implementación, se encontrará decepcionado o confundido. Posiblemente las dos cosas a la vez.

Hay otras soluciones. La más completa es usar AnyEvent, pero también se puede usar cualquiera de los módulos de los que depende: EV, Event, Glib, Event::Lib, Irssi, rxvt-unicode, IO::Async, Qt, FLTK y POE. También existe Coro (hilos cooperativos). En Windows, además, hay una serie de distribuciones específicas para la gestión de procesos.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Ejecutar comandos en distintos hilos

Notapor estudiante » 2014-06-09 02:13 @134

Hola, explorer, gracias por contestar. He probado en un linux y funciona correctamente. Las cosas del Windows...

Un saludo.
estudiante
Perlero nuevo
Perlero nuevo
 
Mensajes: 9
Registrado: 2013-02-06 07:36 @358


Volver a Intermedio

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado

cron