105 votes

Comment puis-je résoudre mon script Perl CGI?

J'ai un script Perl qui ne fonctionne pas et je ne sais pas comment commencer à cerner le problème. Que puis-je faire?


Note: J'ajoute la question parce que je veux vraiment ajouter ma très longue réponse à Stackoverflow. Je continue à y renvoyer des liens externes dans d'autres réponses et il mérite d'être ici. Ne soyez pas timide pour éditer ma réponse si vous avez quelque chose à ajouter.

10voto

Mikael S Points 2973

Je pense que CGI :: Debug mérite également d'être mentionné.

7voto

mob Points 61524

Êtes-vous à l'aide d'un gestionnaire d'erreur lorsque vous déboguez?

die des déclarations et autres fatal au moment de l'exécution et des erreurs de compilation obtenir imprimé STDERR, ce qui peut être difficile à trouver et peut être confondue avec les messages provenant d'autres pages web de votre site. Alors que vous êtes le débogage de votre script, c'est une bonne idée d'obtenir l'erreur fatale de messages à afficher dans votre navigateur en quelque sorte.

Une façon de le faire est d'appeler

   use CGI::Carp qw(fatalsToBrowser);

en haut de votre script. Cet appel permettra d'installer un $SIG{__DIE__} gestionnaire (voir perlvar)affichage des erreurs fatales dans votre navigateur, ajoutant avec un en-tête valide si nécessaire. Un autre débogage des scripts CGI truc que j'ai utilisé avant que j'ai jamais entendu parler d' CGI::Carp a été à utiliser eval avec l' DATA et __END__ des installations sur le script de capture des erreurs de compilation:

   #!/usr/bin/perl
   eval join'', <DATA>;
   if ($@) { print "Content-type: text/plain:\n\nError in the script:\n$@\n; }
   __DATA__
   # ... actual CGI script starts here

Cette plus détaillée de la technique a un léger avantage sur CGI::Carp qu'il va attraper plus d'erreurs de compilation.

Mise à jour: je n'ai jamais utilisé, mais il ressemble CGI::Debug, comme Mikael S suggéré, est également très utile et configurable outil à cette fin.

7voto

sdaau Points 6262

Je me demande comment personne n'a mentionné l' PERLDB_OPTS option appelée" RemotePort; bien que, certes, il n'y a pas beaucoup d'exemples sur le web (RemotePort n'est même pas mentionné dans perldebug) - et c'était un peu problématique pour moi de venir avec ce point, mais ici, il va (étant un Linux par exemple).

Pour faire un bon exemple, j'ai d'abord besoin de quelque chose qui peut faire un très simple simulation d'un serveur web CGI, de préférence au moyen d'une seule ligne de commande. Après constatation Simple ligne de commande du serveur web pour l'exécution de scripts cgi. (perlmonks.org), j'ai trouvé le IO::Tous - Un petit Serveur Web pour être applicable pour ce test.

Ici, je vais travailler dans l' /tmp répertoire; le script CGI sera /tmp/test.pl (inclus ci-dessous). Notez que l' IO::All serveur servira uniquement les fichiers exécutables dans le même répertoire que le CGI, de sorte chmod +x test.pl est requis ici. Donc, faire l'habitude CGI essai, je change le répertoire /tmp dans le terminal et exécutez la ligne de commande du serveur web:

$ cd /tmp
$ perl -MIO::All -e 'io(":8080")->fork->accept->(sub { $_[0] < io(-x $1 ? "./$1 |" : $1) if /^GET \/(.*) / })'

Le serveur de commande va bloquer dans le terminal, et sinon, démarrez le serveur web en local (127.0.0.1 ou localhost) - par la suite, je peux aller à un navigateur web, et demande à cette adresse:

http://127.0.0.1:8080/test.pl

... et je dois observer l' prints par test.pl chargé et affiché dans le navigateur web.


Maintenant, pour déboguer ce script avec RemotePort, nous avons d'abord besoin d'un port d'écoute sur le réseau, qui nous permettra d'interagir avec le débogueur Perl; on peut utiliser l'outil de ligne de commande netcat (nc, vu que ici: Perl如何remote debug?). Donc, tout d'abord exécuter l' netcat auditeur dans un terminal où il permet de bloquer et d'attente pour les connexions sur le port 7234 (qui sera notre port de débogage):

$ nc -l 7234

Ensuite, nous souhaitons perl pour démarrer en mode debug avec RemotePort, lorsque l' test.pl a été appelé (même en mode CGI, par le biais du serveur). Ce, dans Linux, qui peut être fait à l'aide de la suite de "shebang wrapper" script - qui, ici, doit aussi être prise en /tmp, et doit être rendu exécutable:

cd /tmp

cat > perldbgcall.sh <<'EOF'
#!/bin/bash
PERLDB_OPTS="RemotePort=localhost:7234" perl -d -e "do '$@'"
EOF

chmod +x perldbgcall.sh

C'est le genre de chose la plus délicate - voir le script shell - Comment puis-je utiliser des variables d'environnement dans mon arborescence? - Unix & Linux Stack Exchange. Mais, le truc, ici, semble être pas la fourche à l' perl interprète qui gère test.pl - donc, une fois que nous avons atteint, nous n'avons pas l' exec, mais au lieu de cela, nous appelons perl "clairement", et en gros, "source" notre test.pl script à l'aide de do (voir Comment puis-je exécuter un script Perl à partir de l'intérieur d'un script Perl?).

Maintenant que nous avons perldbgcall.sh en /tmp - on peut changer l' test.pl le fichier, de sorte qu'il se réfère à ce fichier exécutable sur sa ligne shebang (au lieu de l'habituel interpréteur Perl) - /tmp/test.pl modifié ainsi:

#!./perldbgcall.sh

# this is test.pl

use 5.10.1;
use warnings;
use strict;

my $b = '1';
my $a = sub { "hello $b there" };
$b = '2';
print "YEAH " . $a->() . " CMON\n";
$b = '3';
print "CMON " . &$a . " YEAH\n";

$DB::single=1;  # BREAKPOINT

$b = '4';
print "STEP " . &$a . " NOW\n";
$b = '5';
print "STEP " . &$a . " AGAIN\n";

Maintenant, les deux test.pl et sa nouvelle arborescence du gestionnaire, perldbgcall.sh, sont en /tmp; et nous avons nc écoute pour déboguer les connexions sur le port 7234 - alors, nous pouvons enfin ouvrir une autre fenêtre de terminal, modifiez le répertoire /tmp, et d'exécuter la ligne de commande du serveur web (qui sera à l'écoute pour les connexions web sur le port 8080) il y a:

cd /tmp
perl -MIO::All -e 'io(":8080")->fork->accept->(sub { $_[0] < io(-x $1 ? "./$1 |" : $1) if /^GET \/(.*) / })'

Après ceci est fait, nous pouvons aller à notre navigateur web, et demande à la même adresse, http://127.0.0.1:8080/test.pl. Cependant, maintenant, quand le serveur tente d'exécuter le script, il le fera par le biais perldbgcall.sh inclus - qui débutera perl dans le débogueur distant mode. Ainsi, l'exécution du script en pause - et donc le navigateur web de verrouillage, l'attente de données. Nous pouvons maintenant passer à l' netcat terminal, et nous devrions voir les familiers débogueur Perl texte - cependant, la sortie par le biais nc:

$ nc -l 7234

Loading DB routines from perl5db.pl version 1.32
Editor support available.

Enter h or `h h' for help, or `man perldebug' for more help.

main::(-e:1):   do './test.pl'
  DB<1> r
main::(./test.pl:29):   $b = '4';
  DB<1>

Comme le montre l'extrait de code, nous allons maintenant utiliser nc comme un "terminal" - afin que nous puissions type r (et Enter) pour "exécuter" - et le script sera exécuté jusqu'faire le point d'arrêt de déclaration (voir aussi En perl, quelle est la différence entre $DB::simple = 1 et 2?), avant de s'arrêter à nouveau (note à ce point, le navigateur sera toujours verrouiller).

Donc, maintenant, nous pouvons, dire, étape à travers le reste de l' test.pl, grâce à l' nc terminal:

....
main::(./test.pl:29):   $b = '4';
  DB<1> n
main::(./test.pl:30):   print "STEP " . &$a . " NOW\n";
  DB<1> n
main::(./test.pl:31):   $b = '5';
  DB<1> n
main::(./test.pl:32):   print "STEP " . &$a . " AGAIN\n";
  DB<1> n
Debugged program terminated.  Use q to quit or R to restart,
  use o inhibit_exit to avoid stopping after program termination,
  h q, h R or h o to get additional info.
  DB<1>

... cependant, à ce niveau, le navigateur de serrures et attend les données. C'est seulement après la sortie du débogueur avec q:

  DB<1> q
$

... le navigateur arrêt verrouillage - et enfin affiche l' (complète) de sortie de l' test.pl:

YEAH hello 2 there CMON
CMON hello 3 there YEAH
STEP hello 4 there NOW
STEP hello 5 there AGAIN

Bien sûr, ce genre de débogage peut être fait même sans courir le serveur web - toutefois, le point intéressant ici, c'est que nous ne touchons pas le serveur web; nous déclencher l'exécution "nativement" (CGI) à partir d'un navigateur web et le seul changement nécessaire dans le script CGI lui-même, est le changement de shebang (et bien sûr, la présence de l'arborescence script, en tant que fichier exécutable dans le même répertoire).

Eh bien, espérons que cela aide quelqu'un - bien sûr, j'aurais aimé avoir tombé sur ce, au lieu de l'écrire moi-même :)
Cheers!

5voto

zawhtut Points 3423

Pour moi, j'utilise log4perl . C'est très utile et facile.

 use Log::Log4perl qw(:easy);

Log::Log4perl->easy_init( { level   => $DEBUG, file    => ">>d:\\tokyo.log" } );

my $logger = Log::Log4perl::get_logger();

$logger->debug("your log message");
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X