Perl en Español

  1. Home
  2. Tutoriales
  3. Foro
  4. Artículos
  5. Donativos
  6. Publicidad
 
Índice general » Mundo Perl » Web » Ayuda con código Perl + script en JavaScript  RESUELTO Responder al tema
Nuevo tema


Página 1 de 1  [ 10 mensajes ] 
 
Nota Jue Jun 10, 2010 1:21 pm

Perlero Nuevo
Registrado: Jue Jun 10, 2010 1:04 pm
Mensajes: 8
Ayuda con código Perl + script en JavaScript
Hola, un saludos a todos. Soy nuevo en el foro :mrgreen: Quisiera pedirles una ayuda con un código que estoy armando en Perl. El problema es en el siguiente fragmento:

Syntax: [ Download ] [ Hide ]
Using perl Syntax Highlighting
  1. print "Content-type: text/html\n\n";
  2.  
  3. print<<EOF;
  4. <HTML>
  5. <head>
  6. <style type="text/css">
  7. <!--
  8. .Estilo1 {
  9.         color: #FF0000;
  10.         font-weight: bold;
  11. }
  12. -->
  13. </style>
  14.  
  15. <SCRIPT language=javascript>
  16. mensaje=
  17. '<p align="center">Mensaje 1</p>'+
  18. '<p align="center">Mensaje 2</p>'+
  19. '<p align="center">Mensaje 3</p>'+
  20. '<p align="center">Mensaje 4</p>'
  21.  
  22. line=0
  23. cursor='_'
  24. function teclear(){
  25. if(line==mensaje.length) cursor=''
  26. ttecleado.innerHTML=mensaje.substring(0,line)+cursor
  27. if(line++<mensaje.length) setTimeout("teclear()",0)
  28. }
  29. </SCRIPT>
  30. </head>
  31.  
  32. <body onLoad="teclear();">
  33. <p align="center"><img src="imagen.jpg" width="800" height="212"></p>
  34. <DIV class=layermensaje id=ttecleado ?></DIV>
  35. </body>
  36. </HTML>
  37. EOF
  38.  
  39. system("(sleep 3; rm /tmp/*) &");
  40. print "--- FIN - END ---";
  41.  
  42. exit(1);
  43.  


Como podrán ver, es un código con un JavaScript que muestra un texto en estilo máquina de escribir. El problema que tengo es que se ejecuta:
Syntax: [ Download ] [ Hide ]
Using perl Syntax Highlighting
  1. system("(sleep 3; rm /tmp/*) &");
  2. print "--- FIN - END ---";

sin antes haber mostrado el ultimo mensaje, que sería el
Syntax: [ Download ] [ Hide ]
Using perl Syntax Highlighting
  1. '<p align="center">Mensaje 4</p>'

Lo que quiero es que después que muestre ese "Mensaje 4" se ejecuten las líneas:
Syntax: [ Download ] [ Hide ]
Using perl Syntax Highlighting
  1. system("(sleep 3; rm /tmp/*) &");
  2. print "--- FIN - END ---";

Como está, cuando muestra el "Mensaje 1" ya está el "--- FIN - END ---"

Espero me entiendan y me puedan ayudar...

Muchas gracias.


Última edición por TooRDJ el Lun Jun 14, 2010 9:21 pm, editado 1 vez en total

Nota Jue Jun 10, 2010 1:42 pm
Avatar de Usuario
Administrador
Registrado: Dom Jul 24, 2005 6:12 pm
Ubicación: Valladolid, España
Mensajes: 9521
Re: Ayuda con código Perl + script en JavaScript
Bienvenido a los foros de Perl en Español, TooRDJ.

El problema es el siguiente: el programa Perl envíe la salida del primer print() al servidor web, que irá, poco a poco, enviando esa salida al navegador del usuario, que comenzará a presentar la pantalla cuando disponga de suficiente información. Y ejecutará el JavaScript cuando todo el código esté presente.

Pero el programa de Perl sigue funcionando, y sigue con una llamada system(), que lanza en segundo plano (&) la ejecución de dos comandos. Se supone que debe esperar 3 segundos antes de borrar los ficheros temporales. Pero el control vuelve inmediatamente a Perl (por haber sido lanzado en segundo plano), donde pinta el último print(), y termina.

Lo que puedes hacer es esperar tú los tres segundos, borrar los ficheros, y luego sacar el mensaje de final:

Syntax: [ Download ] [ Hide ]
Using perl Syntax Highlighting
    sleep 3;
    unlink </tmp/*>;
    print "--- FIN - END ---";

aunque tampoco es garantía de que se haya ejecutado completamente el JavaScript. Algunos navegadores no comienzan a ejecutar el JavaScript hasta que no ven cerrado el canal de comunicaciones con el servidor web. En ese caso, nada más enviar la última cadena de caracteres hacia el navegador del usuario, cierras el STDOUT: close STDOUT; Así, el servidor web informe al navegador de que la página se terminó de enviar. Y deja al programa Perl libre para seguir funcionando.

Lo que no puedes garantizar es que el servidor web le dé tiempo, en esos tres segundos, a mandarlo al usuario, y que la página se presente y que el JavaScript se ejecute. Hay muchos factores que pueden influir en la presentación.

_________________
JF^D Perl programming


Nota Jue Jun 10, 2010 11:56 pm

Perlero Nuevo
Registrado: Jue Jun 10, 2010 1:04 pm
Mensajes: 8
Re: Ayuda con código Perl + script en JavaScript
Hola, explorer, muchas gracias por tu respuesta.

Es decir, colocar después del EOF el sleep 3; Quedando así:
Syntax: [ Download ] [ Hide ]
Using perl Syntax Highlighting
EOF
sleep 10;
system("rm /tmp/*) &");
print "--- FIN - END ---";
exit(1);

Sin embargo, me pasa algo extraño, la ejecución de todo se tarda los 10 segundos, después muestra todo. Y sigo con el mismo problema.

Esto lo había pensado. Lo lógico es que se detenga en esa parte hasta que pasen los 10 segundos, pero no lo hace, detiene todo el proceso. ¿Por qué pasará esto? :?


Nota Vie Jun 11, 2010 2:57 am
Avatar de Usuario
Administrador
Registrado: Dom Jul 24, 2005 6:12 pm
Ubicación: Valladolid, España
Mensajes: 9521
Re: Ayuda con código Perl + script en JavaScript
Es posible que no hayas desactivado la caché de salida.

Coloca

$|++;

al principio del programa, antes del primer print().

Y el final del programa, yo lo dejaría en:

Syntax: [ Download ] [ Hide ]
Using perl Syntax Highlighting
EOF
sleep 10;
print "--- FIN - END ---";
close STDOUT;
unlink </tmp/*>;
exit(1);

Así, saldría el mensaje de fin al cabo de diez segundos, cerraría el STDOUT para indicar que no voy a imprimir nada más, y luego, tranquilamente, borraría los ficheros temporales.

Un detalle... ese mensaje de FIN no contiene ningún marcado HTML.

_________________
JF^D Perl programming


Nota Vie Jun 11, 2010 7:28 pm

Perlero Nuevo
Registrado: Jue Jun 10, 2010 1:04 pm
Mensajes: 8
Re: Ayuda con código Perl + script en JavaScript
explorer, lamentablemente no doy con la solución :? Aquí coloco el código completo con las últimas modificaciones que me recomiendas. Pero no me funciona. Pausa todo.

Syntax: [ Download ] [ Hide ]
Using perl Syntax Highlighting
  1. use strict;
  2. use CGI::Carp qw(fatalsToBrowser);
  3. use CGI;
  4. use Config::General; #modulo
  5.  
  6. my %Input;
  7.  
  8. my $query = new CGI;
  9. my @pairs = $query->param;
  10.  
  11. my $configfile = new Config::General("/etc/config.conf"); #Ruta de fichero a leer
  12. my %config = $configfile->getall;
  13.  
  14. foreach my $pair(@pairs){
  15. $Input{$pair} = $query->param($pair);
  16. }
  17.  
  18. #Directorio donde queremos estacionar los archivos
  19. my $dir = "/tmp";
  20.  
  21. #Array con extensiones de archivos que podemos recibir
  22. my @extensiones = ('gif','jpg','jpeg','bmp','png');
  23.  
  24. recepcion_de_archivo(); #Iniciar la recepcion del archivo
  25.  
  26. #TODO SALIO BIEN
  27. my $nombre_en_servidor = $Input{'archivo'};
  28. $nombre_en_servidor =~ s/ /_/gi;
  29. $nombre_en_servidor =~ s!^.*(\\|\/)!!;
  30.  
  31. my $ip_local = $config{'LOCAL_IPADDR'}; #LOCAL_IPADDR
  32. $ip_local =~ s/\'//g; #QUITO LOS ACENTOS
  33.  
  34. my $port = $config{'PORT'}; #PORT
  35. $port =~ s/\'//g; #LE QUITO LOS ACENTOS
  36.  
  37. my $languaje = $config{'LANGUAGE'}; #LANGUAGE
  38. $languaje =~ s/\'//g; #LE QUITO LOS ACENTOS
  39.  
  40. $|++;
  41. print "Content-type: text/html\n\n";
  42. print<<EOF;
  43. <HTML>
  44. <head>
  45. <style type="text/css">
  46. <!--
  47. .Estilo1 {
  48.         color: #FF0000;
  49.         font-weight: bold;
  50. }
  51. -->
  52. </style>
  53.  
  54. <SCRIPT language=javascript>
  55. mensaje=
  56. '<p align="center">Mensaje 1</p>'+
  57. '<p align="center">Mensaje 2</p>'+
  58. '<p align="center">Mensaje 3</p>'+
  59. '<p align="center">Mensaje 4</p>'
  60.  
  61. line=0
  62. cursor='_'
  63. function teclear(){
  64. if(line==mensaje.length) cursor=''
  65. ttecleado.innerHTML=mensaje.substring(0,line)+cursor
  66. if(line++<mensaje.length) setTimeout("teclear()",0)
  67. }
  68. </SCRIPT>
  69. </head>
  70.  
  71. <body onLoad="teclear();">
  72. <p align="center"><img src="logo.jpg" width="800" height="212"></p>
  73. <DIV class=layermensaje id=ttecleado ?></DIV>
  74. </body>
  75. </HTML>
  76. EOF
  77.  
  78. sleep 30;
  79. print "--- FIN - END ---";
  80. close STDOUT;
  81. unlink </tmp/*>;
  82. exit(1);
  83.  
  84. sub recepcion_de_archivo{
  85.  
  86. my $nombre_en_servidor = $Input{'archivo'};
  87. $nombre_en_servidor =~ s/ /_/gi;
  88. $nombre_en_servidor =~ s!^.*(\\|\/)!!;
  89.  
  90. my $extension_correcta = 0;
  91.  
  92. foreach (@extensiones){
  93. if($nombre_en_servidor =~ /\.$_$/i){
  94. $extension_correcta = 1;
  95. last;
  96. }
  97. }
  98.  
  99. if($extension_correcta){
  100.  
  101. #Abrimos el nuevo archivo
  102. open (OUTFILE, ">$dir/$nombre_en_servidor") || die "No se puedo crear el archivo";
  103. binmode(OUTFILE); #Para no tener problemas en Windows
  104.  
  105. #Transferimos byte por byte el archivo
  106. while (my $bytesread = read($Input{'archivo'}, my $buffer, 1024)) {
  107. print OUTFILE $buffer;
  108. }
  109.  
  110. #Cerramos el archivo creado
  111. close (OUTFILE);
  112.  
  113. }else{
  114. print "Content-type: text/html\n\n";
  115. print "<h1>Extension incorrecta</h1>";
  116. print "Sólo se reciben archivo con extension:";
  117. print join(",", @extensiones);
  118. exit(0);
  119. }
  120.  
  121. } #sub recepcion_de_archivo

¿Qué hago mal?


Nota Sab Jun 12, 2010 12:15 pm
Avatar de Usuario
Administrador
Registrado: Dom Jul 24, 2005 6:12 pm
Ubicación: Valladolid, España
Mensajes: 9521
Re: Ayuda con código Perl + script en JavaScript
Primero, tendría que quedar claro qué es lo que pretendes hacer.

Por el código, parece que el usuario va a subir una imagen, que guardarás en un directorio; luego, obtendrás una serie de datos, como la IP y el puerto; luego, mostrarás una página con el efecto de tecleo; y, finalmente, eliminar todos los ficheros del directorio temporal.

Este último paso es el que no entiendo: si estás usando el módulo CGI, es el propio módulo el que se encarga de eliminar el fichero subido del directorio temporal, en cuanto se termina el programa: tú no tienes que hacer nada para que se borre. Si quieres aumentar la seguridad, puedes agregar la opción -private_tempfiles para aumentar más las opciones de seguridad en el borrado de los ficheros temporales, pero solo es una medida de seguridad extrema: el fichero seguirá siendo borrado al final de la ejecución.

use CGI qw(:standard -private_tempfiles);

Lo que tampoco entiendo es porqué quieres enviar un print() después de los 30 segundos. Si no existiera ese print(), se podrían cerrar los canales estándar más rápido, y así dar la oportunidad de que la página se presente antes.

Esta versión sí que envía toda la página, cierra los canales, y permite seguir ejecutando el cgi.
Syntax: [ Download ] [ Hide ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use diagnostics;
  5.  
  6. use CGI       ':standard';
  7. use CGI::Carp 'fatalsToBrowser';
  8.  
  9. $|++; # no caché
  10.  
  11. my $estilo_css = <<END_CSS;
  12. <!--
  13. .Estilo1 {
  14.     color: #FF0000;
  15.     font-weight: bold;
  16. }
  17. -->
  18. END_CSS
  19.  
  20. my $javascript = <<END_JS;
  21. var mensaje =
  22.     'Mensaje 1.' +
  23.     'Mensaje 2.' +
  24.     'Mensaje 3.' +
  25.     'Mensaje 4.'
  26.     ;
  27. var largo = mensaje.length - 1;
  28. var i = 0;
  29. var cursor = '_';
  30. function teclear() {
  31.     if (i == largo) cursor = '';
  32.  
  33.     var ttecleado = document.getElementById("ttecleado");
  34.     var texto     = ttecleado.innerHTML;
  35.     var letra     = mensaje.charAt(i);
  36.  
  37.     texto = texto.substring(0,texto.length -1);
  38.  
  39.     if (letra == '.') {
  40.         ttecleado.innerHTML = texto + '<br />' + cursor;
  41.     }
  42.     else {
  43.         ttecleado.innerHTML = texto + letra    + cursor;
  44.     }
  45.  
  46.     if (i++ < largo) setTimeout("teclear()",100);
  47. }
  48. END_JS
  49.  
  50. print
  51.     header(),
  52.  
  53.     start_html(
  54.         -title  => 'Mi pagina web',
  55.         -style  => {
  56.                      -code => $estilo_css,
  57.                    },
  58.         -script => {
  59.                      -type => 'text/javascript',
  60.                      -code => $javascript,
  61.                    },
  62.         -onLoad => "setTimeout('teclear()', 0)",
  63.     ),
  64.  
  65.     p({-align=>'center'},
  66.         img({-src => 'logo.gif', -width => 800, -height => 212}), br,
  67.         'Bienvenidos',
  68.     ),
  69.  
  70.     div({-class => 'Estilo1', -align=> 'center', -id => 'ttecleado'}
  71.     ),
  72.  
  73.     end_html(),
  74.     ;
  75.  
  76. open my $oldout, ">&STDOUT";    # Duplicamos el canal de salida para que el system() funcione
  77.  
  78. close STDOUT;   # cerramos los canales para indicar fin de salida
  79. close STDERR;   # con estos dos primeros sería suficiente
  80. close STDIN;    # pero cerramos la entrada estándar para estar más seguros
  81.  
  82. system("(sleep 30; rm -f /tmp/*) &");  # ejecución en segundo plano
  83.  
  84. exit(1);

Hay muchas limitaciones en cuanto cierras los canales de comunicaciones. Quiero decir que no puedes hacer un sleep 30; desde Perl, porque requiere que algunos de esos canales estén abiertos.

Ahora ya es posible ejecutar el system() con operaciones en segundo plano, mientras la página está completamente enviada y funcionando.

Seguro que se me ha pasado algo y se podría realizar de alguna otra manera, como por ejemplo, con fork(), como se comenta aquí.

Los cambios principales con tu programa son:
* ';' en los finales de líneas en el código JavaScript
* ahora en la salida del texto en JavaScript no se ven los caracteres que forman parte del código HTML. Lo que se hace es analizar cada carácter y si es un '.' se traduce por un br.
* generación de código HTML usando las funciones importadas desde CGI. Puede parecer un poco más largo, pero evitas algunos errores de escritura, como los que tienes en el <div>, que le faltan comillas a los atributos y sobra una '?'. Y header() me saca el Content-Type.

_________________
JF^D Perl programming


Nota Sab Jun 12, 2010 3:38 pm

Perlero Nuevo
Registrado: Jue Jun 10, 2010 1:04 pm
Mensajes: 8
Re: Ayuda con código Perl + script en JavaScript
Hola, explorer. Seria sleep 3, no 30. Estaba haciendo pruebas por eso estaba el 30 :mrgreen:

Lo que quiero es que después del:

system("(sleep 3; rm -f /tmp/*) &");

se muestre un mensaje a la par con el comando, es decir, termina el Mensaje 4, después viene sleep 3... y por último

--- FIN - END ---

para decir que todo salió bien... El problema que tengo con el código que coloqué, es que me muestra todo de golpe. No termina de mostrar el Mensaje 1 y ya está el texto de --- FIN - END ---

El texto de modo máquina de escribir lo hace bien.

Este código es para subir un archivo al sistema, descomprime en /tmp, ejecuta algunos sh y borra todo lo de la carpeta /tmp.

El problema en sí es ese. Quiero enviar un mensaje para informar que todo salió bien, pero me muestra todo de golpe.


Nota Sab Jun 12, 2010 8:47 pm
Avatar de Usuario
Administrador
Registrado: Dom Jul 24, 2005 6:12 pm
Ubicación: Valladolid, España
Mensajes: 9521
Re: Ayuda con código Perl + script en JavaScript  RESUELTO
Si se trata de ir indicando un proceso que lleva mucho tiempo, pero se puede dividir en tareas, se puede ir informando al usuario de lo que va ocurriendo. Entonces, se puede simplificar mucho el problema:
Syntax: [ Download ] [ Hide ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use diagnostics;
  5.  
  6. use CGI       ':standard';
  7. use CGI::Carp 'fatalsToBrowser';
  8.  
  9. $|++; # no cache
  10.  
  11. print
  12.     header(),
  13.     start_html('Mi pagina web'),
  14.     p({-align=>'center'}, 'Bienvenidos', ),"\n",
  15.     ;
  16.  
  17. # Comienzo del proceso
  18. print p('Fichero recibido'), "\n";
  19.  
  20. sleep 4;
  21.  
  22. print p('Fichero descomprimido'), "\n";
  23.  
  24. sleep 3;
  25.  
  26. print p('Proceso realizado'), "\n";
  27.  
  28. sleep 2;
  29.  
  30. print p('Limpieza'), "\n";
  31.  
  32. sleep 1;
  33.  
  34. print p('-- FIN --'), "\n";
  35.  
  36. print end_html();
  37.  

El truco está en la variable $| y en los "\n".

Pero... la desventaja está en que esto es muy dependiente del navegador. En mi Firefox suelen salir las dos primeras líneas de golpe, y luego el resto sale bien.

En el enlace que te pasé antes, lleva a un artículo de Randal L. Schwartz donde da una solución mucho más elaborada, usando fork() y CGI::Session, pero mucho más perfecta, porque se crea un proceso aparte que realiza el trabajo largo, mientras que la página generada se va refrescando de forma automática, actualizando el estado en que se encuentra el proceso.

Es mucho más complejo de realizar, pero el resultado es mucho más completo para el usuario, porque siempre se le entrega un HTML completo, y con la información más actual.

_________________
JF^D Perl programming


Nota Lun Jun 14, 2010 9:19 pm

Perlero Nuevo
Registrado: Jue Jun 10, 2010 1:04 pm
Mensajes: 8
Re: Ayuda con código Perl + script en JavaScript
explorer, Muchas Gracias... No usaré el script de máquina de escribir. Lo haré como lo colocaste, mensaje por mensaje. Ya lo adapté al code y trabaja muy bien :mrgreen:

¡Saludos...!


Nota Vie Ago 13, 2010 3:18 am
Avatar de Usuario
Perlero Nuevo
Registrado: Mar Ago 04, 2009 1:53 pm
Ubicación: Valencia, España
Mensajes: 46
Re: Ayuda con código Perl + script en JavaScript
Hola,
¿algo parecido que se pueda hacer en PHP para ir mostrando mensajes de estado de un proceso muy largo?

Saludos

_________________
"Dios nos dió boca para pedir y el kernel de Linux para conceder/denegar servicios" (popular)


Responder al tema  [ 10 mensajes ] 

Reglas del Foro
No puedes abrir nuevos temas en este Foro
No puedes responder a temas en este Foro
No puedes editar tus mensajes en este Foro
No puedes borrar tus mensajes en este Foro
No puedes enviar adjuntos en este Foro

Publicidad

Socializa

Síguenos por Twitter

Suscríbete GRATUITAMENTE al Boletín de Perl en Español

Saltar a:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Traducción al español por Huan Manwë para phpbb-es.com
phpBB SEO