En el siguiente artículo se describen
las posibles causas por errores en programas CGI, particularmente aquellos que
causan un “Error 500 en el Servidor”
y un mensaje nada útil aconsejando contactar al administrador del
servidor. Además contiene algunas sugerencias para escribir aplicaciones en
Perl de una forma que facilite modificaciones posteriores. Estas notas mayormente
están enfocadas a código para Perl y plataformas UNIX, aunque algunas sugerencias
pueden aplicar a programas CGI escritos en otros lenguajes o corriendo en otras
diferentes plataformas. Pueden utilizar esta nota como una lista de revisión
– Así al encontrar un error, leerla mientras se compara en busca de cualquier
error común.

Esta información fue traducida y adaptada del artículo de Angus McIntyre.

Para mayor información sobre el CGI, puede consultar el artículo
introductorio al CGI
.

Los errores explicados son los siguientes:

Error
en el Servidor (Error 500)

Objeto
no encontrado (Error 404)

El
documento no contiene ninguna información (Document contains no data)

Otros
problemas comunes

Error en el
Servidor (Error 500)

Mensajes reportando un “Error
500”
o “Error Interno en el Servidor” (Internal Server Error) puden ser
causados por varios posibles problemas, como por ejemplo:

Cargar el archivo en Forma binaria en lugar de en caracteres
ASCII:

A la hora de cargar o subir un programa CGI a el servidor donde va a ejecutarse,
hay que prestar especial atención a la forma de envío de los archivos. Por ser
el código de un programa CGI en forma de caracteres de texto, es necesario enviarlo
en forma ASCII. Enviarlo en forma BINARIA causará un “Error
500”
pues el interprete encontrará errores de sintaxis.

Permisos de ejecución Incorrectos:

Para que un programa corra, los permisos deben de estar de acuerdo para que
sea ejecutado.Recuerde que los permisos se dan por números, siendo los primeros del administrador,
los segundos de los usuarios y los terceros globales.

Así para asignar que un archivo tenga permisos de ejecución para los usuarios
y globales, teniendo todos los privilegios para el administrador se utiliza
desde la línea de comando, la instrucción:

chmod 755
nombre_del_archivo.cgi

En caso de que el programa CGI necesite algún archivo para guardar información,
debe asignársele los permisos de lectura y escritura para el administrador,
el usuario y globales con la instrucción:

chmod 666 nombre_del_archivo.cgi

Línea incorrecta del Interprete:

Un programa escrito en Perl, debe iniciar con una línea que identifique
al interprete en el sistema:

#!/usr/bin/perl

Si la línea no da la locación correcta del interprete de Perl, se causará
un error. Para averiguar la locación del interprete se utiliza el comando:

wich perl

La línea del interprete debe ir en la primera línea del código del programa
y debe iniciar con “#!”. El mismo principio se
aplica al escribir programas utilizando sh, csh, etc.

Error de Sintaxis en el código del programa:

Cualquier error de sintaxis en el código del programa causará un error 500.
Perl permite que revises la sintaxis del código en la línea de comando con la
instrucción:

perl -c nombre_del_archivo.cgi

Otra opción útil es:

perl -w nombre_del_archivo.cgi

lo que le indica al compilador que muestre advertencias de posibles errores
lógicos en el código.

Archivo requerido Desaparecido:

Si alguna librería ha sido especificada con los comandos “requiere” o “use” no puede ser encontrada, también
se producirá un “Error 500”. Comúnmente se
puede detectar este error con una revisión de sintaxis, aunque en algunos casos
el ambiente en el que los programas son ejecutados por el servidor, son diferentes
a el ambiente especificado cuando el código corre en la línea de comando. Perl
puede encontrar el archivo necesario en algunos casos, pero no en todos.

Error lógico en el programa:

Si el código tiene algún error lógico, como por ejemplo, un archivo no encontrado,
una división por cero, etc, se producirá un “Error 500”. Errores lógicos, particularmente
los del tipo “file not found”, pueden ser causados
usualmente por diferencias entre ambientes de Perl al ser ejecutados bajo el
servidor y bajo la línea de comando. Para encontrar el error, se recomienda
imprimir la locación completa del archivo que el programa necesita puede ser
de gran utilidad. Más abajo se muestra una técnica que también sirve para corregir estos errores.

Header HTTP invalido:

La primera línea que un programa debe enviar como Header HTTP debe ser valida, usualmente
es:

Content-type: text/html

Esta línea que se utiliza para el Header HTTP debe
ser seguido de dos líneas de espacio y para lo cual se utiliza el agregado ” ” antes que el contenido empieze. Precaución
al compilar comentarios escritos a un error estándar: algunos servidores toman
los datos de un STDOUT o STDERR, y porque STDERR es una línea de estado (Texto escrito
hacia STDERR es enviada tan pronto como la línea
es completada), mientras que STDOUT es un bloque de estado (Texto es
enviado al ser completado el bloque), STDERR podría considerarse: “Llegar de
inmediato”. El siguiente código de prueba podría causar algunos errores en algunos
sistemas:

#!/usr/local/bin/perl
print "Content-type: text/plain ";
print STDERR "Listo hasta aquí ";
print "Exitosamente.";

Debido a que el servidor vería “Listo hasta
aquí” primero, y no le encontraría sentido al mensaje. Se puede forzar un bloque
de estado en STDOUT con:

$|=1;

incluyéndolo en el inició del código del programa, lo cual es probablemente
algo bueno para hacer de cualquier forma.

Versión incorrecta de Perl:

Hay que asegurarse de no tratar de correr un programa escrito para Perl5 en
un interprete Perl4 (o anterior!) Para confirmar esto, escribir:

perl -e `print $]`

en la línea de comando, lo cual mostrará la versión de Perl que está instalada.
Si resulta ser Perl 4, podría existir un interprete para Perl 5 instalado en
el mismo directorio, pero con el nombre perl5. También
hay que tomar en cuenta que algunos programas escritos para Perl 4 pueden dar
problemas en Perl 5, en particular, variables que contengan “@”
pueden causar errores; ésto debido a que para utilizar la arroba es necesario
incluir la diagonal invertida “” antes.

Errores de configuración
en el servidor:

El último caso que puede llevar a un “Error 500”,
es que el servidor esté mal configurado. Netscape Commerce
Server, por ejemplo, enviará un error del servidor si se utiliza POST
para llamar a un programa localizado en un directorio en el que el directorio
no ejecuta programas. Si el utilizar POST causa un error, al utilizar GET (en el mismo programa) se enviará el
código en forma de texto como resultado. Es en resumen que el directorio donde
se ejecutan los programas no está habilitado para corre programas CGI. Para corregir
esto, hay que ir al archivo obj.conf (en servidores Netscape) y hacer
los cambios respectivos. Hay que estar seguros y ser capaces de modificar ese
archivo, o pedirle ayuda a un profesional para evitar cualquier conflicto en
el servidor.

La mejor técnica para simplificar la corrección de Errores de lógica es por
medio del comando Eval. Un modelo general del código para
esta función sería:

{ ... código de inicialización
... }
eval("main");
if ($@) {
print "Content-type: text/plain ",
"El programa fallo porque el error $@ ocurrio.";
}
sub main { ... }

En caso de que esto cause un “Error
500”
, se sabe que es causado por algo fuera de la sub-rutina principal,
siendo probablemente uno de los errores que se discutieron anteriormente.

Objeto
no encontrado (Error 404)

El famoso “Error 404” es el de “Objeto no encontrado”. Así como fácilmente
nos topamos con un error similar de “Archivo no encontrado” en documentos HTML,
así mismo se pueden encontrar dentro de programas CGIs por la misma razón. La
solución a este problema es de revisar el URL, y
la locación del archivo para asegurarse que el URL realmente apunta hacia el lugar que
se cree. La relación entre la locación en el servidor y el URL
correcto para referenciarlo puede ser a veces no muy obvia, particularmente
si programas del servidor corren en un ambiente cerrado (donde, por razones
de seguridad, los programas corren únicamente en una parte del sistema de archivos),
o cuando la configuración de los archivos en el servidor especifica una locación
compleja de un URL a la locación en el sistema de
archivos. Hay que recordar también que algunos servidores no permiten subdirectorios
en un directorios cgi-bin designados, por lo que:

http://www.maestrosdelweb.com/cgi-bin/mi_programa.cgi

podria ser valido, mientras que:

http://www.maestrosdelweb.com/cgi-bin/otros/mi_programa.cgi

fallaría por la misma razón.

El documento
no contiene ninguna información (Document contains no data)

El error en inglés “Document
contains no data”
es un error que se da en los navegadores. Este
error da a entender que el programa no envió el content-header adecuado. En otras palabras,
que envió una información que no está descrita y por lo tanto que no puede ser
manejada.

Las posibles explicaciones para este error son:

Error en el código:

Si el programa falla luego de haber enviado los content-header validos, no se encontrara
ningún reporte de error del servidor. Alguno de los errores lógicos usuales
podría causar esto (como por ejemplo que algún archivo no pudo ser abierto,
declaraciones “die()”, divisiones por cero, etc). Utilizando la técnica
de eval()
se puede arreglar cualquiera de estos errores.

Tiempo fuera en el servidor:

Si el programa toma un largo tiempo para correr, la conexión puede perderse
antes de que termine de enviar la información. Tanto el servidor como el navegador
pueden desistir si al parecer el programa no se apresura en terminar. Para arreglar
esto, se puede ajustar el tiempo de tiempo fuera (Server
timeout) del servidor, aunque en general la atención del usuario es más
corta que el tiempo fuera del servidor, así que si el programa no termina rápido,
probablemente se perderá de cualquier forma. Si el programa realmente toma un
largo tiempo para correr, la mejor solución es hacer que los resultados estén
disponibles, según se den, en lugar de esperar a que se cargue todo el paquete,
hay que tratar de que el usuario reciba información y por lo tanto no se aburra.
Si esto no puede ser aplicado (el programa tiene que hacer varios cálculos antes
de enviar información, y por lo tanto no hay resultados intermedios que puedan
ser enviados) entonces hay que adoptar otra estrategia. Una es simplemente enviar
por correo los resultados hacia el usuario cuando estén listos.

La otra técnica
es usar métodos de “Server push” para alimentar el progreso de los reportes
al usuario intermitentemente. Una recomendación es crear un indicador visual
del progreso que indique el tiempo faltante y que los persuadirá a esperar en
lugar de irse.

Falta de producción:

Esto sucede, cuando por alguna razón, el programa no envía más información.
Se ejecuta exitosamente, pero esto no incluye el escribir algo hacia el STDOUT.
Para contrarrestar esto, hay que revisar la lógica del código para asegurarse
de que todas las declaraciones de producción están siendo ejecutadas, y revisar
la configuración para asegurarse que se esté escribiendo hacia el STDOOUT. Correr el programa desde la línea
de comando puede ayudar a corregir este problema.

Errores de conexión en la red o fallas del servidor:

Es raro, aunque el error puede ocasionarse también por fallas en el servidor
(por ejemplo que se quede sin memoria). Es extraño que esto suceda, pero si
el programa corre intermitentemente o corre un día y al otro no, este podría
ser el problema. El error en inglés “Document contains
no data”
es un error que se da en los navegadores. Este error da
a entender que el programa no envió el content-header adecuado. En otras palabras,
que envió una información que no está descrita y por lo tanto que no puede ser
manejada.

Las posibles explicaciones para este error son:

Error en el código:

Si el programa falla luego de haber enviado los content-header validos, no se encontrara
ningún reporte de error del servidor. Alguno de los errores lógicos usuales
podría causar esto (como por ejemplo que algún archivo no pudo ser abierto,
declaraciones “die()”, divisiones por cero, etc). Utilizando la técnica
de eval()
se puede arreglar cualquiera de estos errores.

Tiempo fuera en el servidor:

Si el programa toma un largo tiempo para correr, la conexión puede perderse
antes de que termine de enviar la información. Tanto el servidor como el navegador
pueden desistir si al parecer el programa no se apresura en terminar. Para arreglar
esto, se puede ajustar el tiempo de tiempo fuera (Server
timeout) del servidor, aunque en general la atención del usuario es más
corta que el tiempo fuera del servidor, así que si el programa no termina rápido,
probablemente se perderá de cualquier forma. Si el programa realmente toma un
largo tiempo para correr, la mejor solución es hacer que los resultados estén
disponibles, según se den, en lugar de esperar a que se cargue todo el paquete,
hay que tratar de que el usuario reciba información y por lo tanto no se aburra.
Si esto no puede ser aplicado (el programa tiene que hacer varios cálculos antes
de enviar información, y por lo tanto no hay resultados intermedios que puedan
ser enviados) entonces hay que adoptar otra estrategia. Una es simplemente enviar
por correo los resultados hacia el usuario cuando estén listos.

La otra técnica
es usar métodos de “Server push” para alimentar el progreso de los reportes
al usuario intermitentemente. Una recomendación es crear un indicador visual
del progreso que indique el tiempo faltante y que los persuadirá a esperar en
lugar de irse.

Falta de producción:

Esto sucede, cuando por alguna razón, el programa no envía más información.
Se ejecuta exitosamente, pero esto no incluye el escribir algo hacia el STDOUT.
Para contrarrestar esto, hay que revisar la lógica del código para asegurarse
de que todas las declaraciones de producción están siendo ejecutadas, y revisar
la configuración para asegurarse que se esté escribiendo hacia el STDOOUT. Correr el programa desde la línea
de comando puede ayudar a corregir este problema.

Errores de conexión en la red o fallas del servidor:

Es raro, aunque el error puede ocasionarse también por fallas en el servidor
(por ejemplo que se quede sin memoria). Es extraño que esto suceda, pero si
el programa corre intermitentemente o corre un día y al otro no, este podría
ser el problema.

Otros
problemas comunes

Algunos otros posibles problemas podrían
ser:

Código del programa mostrado como texto en lugar de ejecutarse:

En el caso de que al tratar de correr el programa, el código no se ejecuta,
sino que el navegador muestra el código en texto, lo más probable es que se
haya instalado el programa en el lugar incorrecto o con el nombre equivocado.
Algunos servidores están configurados para ejecutar los programas CGI en directorios
específicos e incluso con terminaciones específicas: “.cgi”, “.pl”. Al poner un programa CGI en el directorio
equivocado, no será ejecutado, sino se mostrará el código como un archivo ordinario
de texto.

El navegador muestra la venta de “Guardar Archivo” al tratar
de correr un programa:

Cuando en lugar de mostrarse la página de respuesta, el navegador invoca una
ventana para “Guardar Archivo como” y trata de guardar
el archivo como tipo “desconocido” (o ‘application/x-url-encoded’, etc.), es
causado probablemente por las Headers de contenido incorrectas. Para arreglar
este problema, vea la sección de Headers
HTTP incorrectas
.

Problemas al usar técnicas “Here-documents”:

Uno de los errores de sintaxis más comunes son los asociados con las técnicas
de “here-documents” en Perl. Estas expresiones son:

print << "FinDelTexto";
Aquí hay algo de texto y HTML
FinDelTexto;

La señal entre comillas “FinDelTexto” que termina el texto para ser impreso debe ser exactamente igual, o se producirá un
error como el siguiente:

‘FinDel Texto’ no encontrado en ningún lugar antes del fin
del archivo

Espacios en blanco antes o después de la terminación de la señal pueden causar
que esta exactitud falle, así que la señal “FinDelTexto” (o cualquiera que se utilice
debe estar pegada al margen izquierdo y no debe contener un espacio después;
una particularidad que ocurre al mover archivos de texto desde DOS/Windows hacia
UNIX. Todo esto debido a que DOS/Windows utiliza dos caracteres: <CR>
y <LF>, para delimitar líneas, mientras que UNIX utiliza una: <LF>,
lo cual puede producir que caracteres <CR> sean visibles entre la señal
y la delimitación de la línea. Esto no puede ser visto por el usuario, pero
Perl lo detecta, por lo que para Perl “FinDelTexto<CR>” no es lo mismo
que “FinDelTexto”. La compilación fallará misteriosamente.

Esta lista de razones por las que algo
salió mal no es probablemente exhaustiva pero trata de cubrir la mayor cantidad
de errores.