2010-08-23 6 views
5

Tengo un script CGI que tarda aproximadamente 1 minuto en ejecutarse. En este momento Apache solo devuelve los resultados al navegador una vez que el proceso ha finalizado.Mostrando un proceso de shell de larga ejecución con Apache

¿Cómo puedo hacer que muestre la salida como si se hubiera ejecutado en un terminal?

Aquí hay un example que demuestra el problema.

Quiero ver aparecer los números del 1 al 5 a medida que se imprimen.

+1

Es posible que desee buscar en Google "encabezados no analizados" –

+0

@glenn: también lo hice, pero [esta antigua pregunta frecuente] (http://httpd.apache.org/docs/1.3/misc/FAQ- F.html # nph-scripts) establece que "[a] s de Apache 1.3, los scripts CGI esencialmente no están almacenados en búfer. Cada vez que la secuencia de comandos realiza un "lavado" de los datos de salida, los datos se transmiten al cliente. Algunos lenguajes de scripting, por ejemplo Perl, tienen su propio buffer para la salida, esto se puede deshabilitar estableciendo la variable especial '$ |' en '1'." –

+0

me han señalado http://mywiki.wooledge.org/BashFAQ/009 WRT shell buffering. todavía no lo he descubierto. – hendry

Respuesta

6

tuve que desactivar el modo mod_deflate tener trozo trabajar con Apache

No he encontrado otra manera para que mi cgi desactivar automática de codificación de gzip.

+1

Oh wow, deshabilité 'sudo a2dismod deflate' y ahora funciona !!! !! !!! ! – hendry

+0

También puede desactivar gzip para ciertos tipos de archivos. Mis scripts CGI tienen a.extensión sh, por lo que desactivo gzip solo para scripts bash: [ver también] (http://stackoverflow.com/questions/1922934/how-to-disable-mod-deflate-in-apache2) – jtv4k

3

Aquí hay varios factores en juego. Para eliminar algunos problemas, Apache y bash no almacenan en búfer ninguno de los resultados. Puede comprobar con este script:

#!/bin/sh 

cat <<END 
Content-Type: text/plain 

END 

for i in $(seq 1 10) 
do 
    echo $i 
    sleep 1 
done 

Pegue esto en alguna parte que Apache está configurado para ejecutar scripts CGI, y probar con netcat:

$ nc localhost 80 
GET /cgi-bin/chunkit.cgi HTTP/1.1 
Host: localhost 

HTTP/1.1 200 OK 
Date: Tue, 24 Aug 2010 23:26:24 GMT 
Server: Apache/2.2.14 (Unix) mod_ssl/2.2.14 OpenSSL/0.9.7l DAV/2 
Transfer-Encoding: chunked 
Content-Type: text/plain 

2 
1 

2 
2 

2 
3 

2 
4 

2 
5 

2 
6 

2 
7 

2 
8 

2 
9 

3 
10 

0 

Cuando hago esto, veo en netcat cada número que aparece una vez por segundo, según lo previsto.

Tenga en cuenta que mi versión de Apache, al menos, aplica la codificación de transferencia fragmentada automáticamente, presumiblemente porque no incluí un Content-Length; si devuelve el encabezado Transfer-Encoding: chunked usted mismo, entonces necesita codificar el resultado de su secuencia de comandos en la codificación de transferencia fragmentada. Eso es bastante fácil, incluso en un script de shell:

chunk() { 
    printf '%x\r\n' "${#1}" # Length of the chunk in hex, CRLF 
    printf '%s\r\n' "$1"  # Chunk itself, CRLF 
} 

chunk $'1\n' # This is a Bash-ism, since it's pretty hard to get a newline 
chunk $'2\n' # character portably. 

Sin embargo, sirven a un navegador, y obtendrá resultados variables dependiendo del navegador. En mi sistema, Mac OS X 10.5.8, veo diferentes comportamientos entre mis navegadores. En Safari, Chrome y Firefox 4 beta, no empiezo a ver la salida hasta que he enviado alrededor de 1000 caracteres (supongo que 1024 incluye los encabezados, o algo así, pero no lo he reducido al comportamiento exacto). En Firefox 3.6, comienza a mostrarse de inmediato.

Supongo que este retraso se debe a content type sniffing, o character encoding sniffing, que están en proceso de estandarización. Intenté ver si podía superar el retraso especificando los tipos de contenido y las codificaciones de caracteres adecuados, pero sin suerte. Puede que tenga que enviar algunos datos de relleno (lo que sería bastante fácil de hacer de forma invisible si utiliza HTML en lugar de texto sin formato), para ir más allá de ese búfer inicial.

Una vez que comience a transmitir HTML en lugar de texto sin formato, también importa la estructura de su HTML. Algunos contenidos pueden mostrarse progresivamente, mientras que otros no. Por ejemplo, la transmisión hacia abajo <div> s en el cuerpo, sin ningún estilo, funciona bien, y puede mostrarse progresivamente a medida que llega. Si intentas abrir una etiqueta <pre> y simplemente transmitir contenido a eso, los navegadores basados ​​en Webkit esperarán hasta que vean la etiqueta de cierre para tratar de establecer eso, mientras que Firefox se complace en mostrarla progresivamente. No conozco todos los casos de esquina; Tendrás que experimentar para ver qué funciona para ti.

De todos modos, espero que esto lo ayude a comenzar. ¡Avíseme si tiene más preguntas!

+0

. Solo puedo hacer funcionar 'curl -vv http: // test.dabase.com/foo.cgi'. Firefox 3.6.8, w3m, Chrome no muestran nada. :( ¿Puede decirme cómo ejecuta netcat en un solo paso? Tengo problemas para ejecutarlo con mi configuración de Apache2 VHOST Solo puedo ejecutar ese curl desde el propio host. Cuando estoy remoto, deja de funcionar. :(Supongo que un proxy lo está arruinando? – hendry

+0

@hendry Para ejecutar netcat, lo invocas como 'nc localhost 80', y luego escribes la solicitud HTTP y los encabezados manualmente (' GET/cgi- bin/... 'a través de la línea en blanco). En ese punto, debería ver la respuesta del servidor. Es una forma bastante baja de depurar HTTP, pero puede ser útil ver exactamente qué está pasando. Si las cosas funcionan localmente pero no remotamente, entonces esperaría que un proxy o algún aspecto de tu configuración de Apache te esté molestando. No estoy seguro de cómo ayudar allí, sin saber más sobre tu configuración. –

+0

Pensé que podrías echo y pipe to nc para depurar más rápido. – hendry

Cuestiones relacionadas