OVH Cloud OVH Cloud

un pipe fait planter mon CGI perl

18 réponses
Avatar
Christophe Baegert
Bonjour,

Ca fait plusieurs ANNEES (!!!) que j'ai ce problème. J'ai toujours essayé de
le contourner jusqu'à présent, mais ça commence à me gonfler... J'avais
déjà posté ça sur comp.lang.perl.misc, mais ils m'ont envoyé sur la FAQ
"mon script marche avec perl mais pas avec apache" comme s'il s'agissait
d'un problème de permission.... Evidemment je connais le contenu de cette
FAQ que j'ai parcouru de fond en comble au siècle dernier, et ça n'a rien à
voir avec ça. Voici mon problème donc :

Le script :

#!/usr/bin/perl
print "Content-type: text/html\n\nOK1\n<br>";
open(LEPIPE,"|cat > /tmp/test");
print LEPIPE "test";
close LEPIPE;
print "OK2";


- Ce script fonctionne très bien en ligne de commande, j'ai OK1 et OK2
- Il fonctionne également très bien en CGI si je commente les 3 lignes
concernant "LEPIPE", j'ai OK1 et OK2.
- Mais tel quel en CGI... il part en exécution infinie, sans faire quoi que
ce soit, ni afficher OK1, ni OK2, ni même remplir /tmp/test !!! (dans les
logs Apache, tout va bien excepté le contenu vide)
- Sur d'autres machines ça marche très bien
- Sur la même machine sur d'autres scripts ça marche très bien ! Sur ce
script jamais !


J'utilise Perl 5.8.1 et Apache 1.3.29, mais j'avais déjà le problème avec
Perl 5.0 et Apache 1.3.27

Ai-je été marabouté ?

Cordialement,

Christohe

8 réponses

1 2
Avatar
Paul GABORIT
À (at) Fri, 18 Jun 2004 10:37:04 +0200,
Christophe Baegert écrivait (wrote):
Paul GABORIT wrote:

Rien puisque pour apache tout va bien, j'ai un code 200 et 8 octets
envoyés dans l'access_log.


8 octets ? On peut les voir ?


Non. Rien à l'écran sur Mozilla. Ah si, en telnet on les voit :
OK1n<br>


Ok. Si vous aviez mis text/plain à la place de text/html, vous les auriez eu
dans Mozilla...

enfin ça ne nous avance pas bcp, parce qu'on savait bien que ça bloquait au
pipe...


Vous peut-être... moi pas ;-)

Si un script CGI ne se termine pas, Apache
ne peut pas dire que tout s'est bien déroulé... Si vous tuez un script
CGI, vous devriez récupérez au minimum un message dans error_log.


Et pourtant...


Lorsque le script se bloque, pouvez-vous regardez les processus fils de
httpd ?

Il devrait y avoir : httpd -> perl -> (ba)sh -> cat ?

Y sont-ils tous les quatre ? Sinon lesquels manquent ?

En fait Apache tourne sous suexec, donc à priori il doit utiliser le shell
de l'utilisateur, à savoir /bin/bash. Quand à nobody il utilise /bin/sh.
Mais quelque soit le bash utilisé sur nobody ou l'utilisateur, ça ne change
rien.


(sur Linux sh == bash)

N'y aurait-il pas un problème de fichiers de configuration (.profile ou
autres...) ?

--
Paul Gaborit - <http://www.enstimac.fr/~gaborit/>
Perl en français - <http://www.enstimac.fr/Perl/>



Avatar
Christophe Baegert
Paul GABORIT wrote:
Lorsque le script se bloque, pouvez-vous regardez les processus fils de
httpd ?

Il devrait y avoir : httpd -> perl -> (ba)sh -> cat ?

Y sont-ils tous les quatre ? Sinon lesquels manquent ?


nobody 3450 0.0 0.3 79720 5852 ? S 08:17 0:00 _ httpd
xxxxx 5804 0.0 0.1 3660 1684 ? S 10:35 0:00 | _ test.pl

Il manque (ba)sh et cat...


N'y aurait-il pas un problème de fichiers de configuration (.profile ou
autres...) ?


C'est un utilisateur qui ne sert que pour un site web, donc aucune config
particulière, le compte est tel qu'il est après un "adduser", le skel n'a
rien de particulier.

Avatar
Paul GABORIT
À (at) Fri, 18 Jun 2004 14:19:16 +0200,
Christophe Baegert écrivait (wrote):
Paul GABORIT wrote:
Lorsque le script se bloque, pouvez-vous regardez les processus fils de
httpd ?

Il devrait y avoir : httpd -> perl -> (ba)sh -> cat ?

Y sont-ils tous les quatre ? Sinon lesquels manquent ?


nobody 3450 0.0 0.3 79720 5852 ? S 08:17 0:00 _ httpd
xxxxx 5804 0.0 0.1 3660 1684 ? S 10:35 0:00 | _ test.pl

Il manque (ba)sh et cat...


Donc soit le pipe n'est pas encore lancé soit il s'est déjà terminé.

Pour en être sûr, il faudrait que vous utilisiez la version modifiée avec des
'print STDERR "OKn"' entre chaque ligne du script. Toute écriture sur STDERR
doit apparaître dans le fichier 'error_log' de Apache. C'est le seul moyen sûr
de savoir où est bloqué votre script. (Si c'est un Apache 2.x, la fichier
error_log se remplit parfois avec retard - par exemple après que vous ayez tué
le process bloqué.)

Une autre méthode consisterait à effacer le fichier /tmp/null pour voir si il
est recréé.

Après, si c'est vraiment le lancement du pipe qui bloque, vous pouvez tenter
la manip suivante :

open(PIPE, "|-", "/bin/bash", "/le/chemin/d/un/script")
or die "Pb avec PIPE: $!n";
print PIPE "coucoun";
close PIPE;

En mettant un truc du genre dans /le/chemin/d/un/script :
----------------
#!/bin/bash
/usr/bin/cat > /tmp/null
----------------

En fait, il faudrait tester en imposant les chemins des exécutables...

Ensuite, si ça ne marche toujours pas, on arrive à la solution que j'évoquais
précédemment : faire le fork soi-même... juste pour voir si ça marche.

Pouvez-vous nous donner un exemple d'un autre script CGI utilisant un pipe qui
marche cette fois ?

En fait, de manière plus générale, il faut faire du debug :

- imaginer une cause possible du bug,

- modifier les conditions d'expériences pour valider ou invalider cette
cause,

- découper l'exécution en élémentss successifs indépendants testables
séparément pour isoler le problème,

etc.

--
Paul Gaborit - <http://www.enstimac.fr/~gaborit/>
Perl en français - <http://www.enstimac.fr/Perl/>


Avatar
Samuel Mouniée
Bonjour,


Samuel Mouniée wrote:


conclusion, apache peut restreindre grandement ta liberte de mouvement (
%ENV $< $> $( $) ).




que veux tu dire ?




je veux dire que apache peut restreintre le contexte, et ce pour plein
de raisons.

enfin ça ne me dit pas pourquoi mon script perl part en exécution infinie
sans faire quoi que ce soit. C'est un bug de perl, pas d'Apache. Quel que
soit le comportement d'Apache, perl doit fonctionner ou faire une erreur,
pas continuer infiniment sans faire d'erreur.


FYI, je n'arrive pas a reproduire le bug sur des Debian/Sarge et Sid .


je pense donc que cela tiens plus d'un probleme de conf.

les permissions sont elles bonnes ?
SuExec est il activé ?
avez vous vous meme ecrit le httpd.conf ?

pouvez vous le copier integralement ( en retirant les commentaires par
defaut )

que dit le %ENV du CGI ? et en execution shell ?


.s'nuoM


Avatar
Samuel Mouniée
Bonjour,


je pense donc que cela tiens plus d'un probleme de conf.

les permissions sont elles bonnes ?
SuExec est il activé ?
avez vous vous meme ecrit le httpd.conf ?

pouvez vous le copier integralement ( en retirant les commentaires par
defaut )

que dit le %ENV du CGI ? et en execution shell ?


avez vous un loader en mod_perl ?


.s'nuoM

Avatar
Jyce
"Christophe Baegert" a écrit dans
le message de news:cau9qr$2b63$
DominiX wrote:
il faut TOUJOURS tester le retour de open
open (...) or die "aie aie aie $!";


C' est un script minimal que j'ai fait pour montrer le problème, pas le
vrai

script qui lui en avait un, donc je sais bien que le die ne renvoie rien
(et d'ailleurs j'ai bien précisé que le script ne mourrait pas)


Peut-etre que tu peux tracer le process qui boucle avec gdb.
Tu n'as qu'a attacher son pid dans gdb pour voir il se bloque...

--
"Si la politique pouvait changer notre vie,
cela ferait longtemps qu'elle serait interdite."
- Federation Anarchiste de France


Avatar
Denis -esp2008-
Bonsoir,

À priori, tel quel, je ne vois pas de problème majeur. Passons sur la première
ligne qui dit qu'elle envoie du text/html alors que c'est du text/plain et qui
utilise des n alors qu'il faut des 1215 (HTTP est un protocole réseau).


Pas avec CGI, la spécification prévoit que le serveur web doit traduire
la séquence de fin de ligne du système d'exploitation sur lequel il
s'exécute en CRLF.

--
Denis

Avatar
Paul GABORIT
À (at) Fri, 18 Jun 2004 23:34:51 +0200,
Denis -esp2008- écrivait (wrote):
Bonsoir,

À priori, tel quel, je ne vois pas de problème majeur. Passons sur la
première ligne qui dit qu'elle envoie du text/html alors que c'est du
text/plain et qui utilise des n alors qu'il faut des 1215 (HTTP est un
protocole réseau).


Pas avec CGI, la spécification prévoit que le serveur web doit traduire la
séquence de fin de ligne du système d'exploitation sur lequel il s'exécute
en CRLF.


Certes... jusqu'au jour où on décide de faire des scripts nph (non parsed
header) et où on ne comprend plus pourquoi les en-têtes qui marchaient si bien
avant ne marchent plus. De plus la traduction, n'a lieu que pour les en-têtes
(heureusement). Et là encore, l'utilisateur peu formé ne comprend pas pourquoi
les en-têtes sont traduits (en fait il ne le sait pas) et pourquoi son beau
fichier texte Mac ou Unix n'est pas lisible sur Windows (par exemple).

Les mécanismes par défaut ne devraient être utilisés que par ceux qui savent
ce qu'ils font. En fait, il faudrait un flag pour les activer... mais ils ne
seraient plus "par défaut". ;-)

--
Paul Gaborit - <http://www.enstimac.fr/~gaborit/>
Perl en français - <http://www.enstimac.fr/Perl/>


1 2