Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

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

10 réponses

1 2
Avatar
Paul GABORIT
À (at) Thu, 17 Jun 2004 14:40:05 +0200,
Christophe Baegert écrivait (wrote):
Voici mon problème donc :

Le script :

#!/usr/bin/perl
print "Content-type: text/htmlnnOK1n<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


À 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).

Pour essayer de comprendre :

- regardez si le shell utilisé est le même depuis Apache que depuis la ligne
de commande.

- ajoutez des 'print SDTERR "Ok"' entre chacune de vos lignes de scripts pour
essayer de voir où ça bloque.

- testez le résultat de chacun de vos appels système (open en particulier).

- ajoutez 'use warnings;' (on ne sait jamais).

- indiquez-nous l'OS (Windows ? Unix ?) et sa version (je pencherais pour un
Unix au vu de 'cat'... mais on ne sait jamais).

- au pire, redéveloppez vous-même le open à coup de fork, exec et autres (lire
perlipc) pour tenter de situer le problème plus précisémment.

- Sur la même machine sur d'autres scripts ça marche très bien ! Sur ce
script jamais !


Ces autres scripts utilisent-ils eux aussi des pipes ?



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

Avatar
Samuel Mouniée

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/htmlnnOK1n<br>";
open(LEPIPE,"|cat > /tmp/test");
print LEPIPE "test";
close LEPIPE;
print "OK2";




heu ... je ne veux pas dire, mais IPC::Open2 me semble plus adequat, ou
un fork() + exec() avec des pipe() ( equivalent plus souple du popen() ).

sinon, la difference entre un shell et un cgi par apache, tiens dans un
mot : contexte .
avec ton shell tu es passé par un login, donc ton execution est "sur" a
priori.
avec apache, n'importe qui peut executer ton cgi, donc l'execution n'est
pas "sur" a priori.

conclusion, apache peut restreindre grandement ta liberte de mouvement (
%ENV $< $> $( $) ). peut etre que cela vient de là. avis{ evite
d'appeler le shell dans un cgi sans raison valable car tu forkexec ce
qui coute }

.s'nouM

Avatar
Christophe Baegert
Paul GABORIT wrote:


Pour essayer de comprendre :

- regardez si le shell utilisé est le même depuis Apache que depuis la
ligne de commande.


tiens, je ne me suis jamais posé la question... comment je fais ça ?
$ENV{'SHELL'} est vide en tout cas.


- ajoutez des 'print SDTERR "Ok"' entre chacune de vos lignes de scripts
pour essayer de voir où ça bloque.

- testez le résultat de chacun de vos appels système (open en
particulier).

- ajoutez 'use warnings;' (on ne sait jamais).



pas mieux avec ça :

#!/usr/bin/perl
use warnings;
print "Content-type: text/htmlnnOK1n<br>";
print STDERR "OKA";
open(LEPIPE,"|cat > /tmp/null") or die "impossible d'ouvrir le pipe : $!";
print STDERR "OKB";
print LEPIPE "test";
print STDERR "OKC";
close LEPIPE;
print STDERR "OKD";
print "OK2";



- indiquez-nous l'OS (Windows ? Unix ?) et sa version (je pencherais pour
un Unix au vu de 'cat'... mais on ne sait jamais).


oui bien sur. Linux Mandrake 9.2


- au pire, redéveloppez vous-même le open à coup de fork, exec et autres
(lire perlipc) pour tenter de situer le problème plus précisémment.


Pfff je sens qu'il va falloir en passer par là...


- Sur la même machine sur d'autres scripts ça marche très bien ! Sur ce
script jamais !


Ces autres scripts utilisent-ils eux aussi des pipes ?


Oui !!!


Avatar
Christophe Baegert
Samuel Mouniée wrote:
conclusion, apache peut restreindre grandement ta liberte de mouvement (
%ENV $< $> $( $) ).


que veux tu dire ?

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.

Avatar
Paul GABORIT
À (at) Fri, 18 Jun 2004 08:34:27 +0200,
Christophe Baegert écrivait (wrote):
Paul GABORIT wrote:


Pour essayer de comprendre :

- regardez si le shell utilisé est le même depuis Apache que depuis la
ligne de commande.


tiens, je ne me suis jamais posé la question... comment je fais ça ?
$ENV{'SHELL'} est vide en tout cas.


print `echo $SHELL`



- ajoutez des 'print SDTERR "Ok"' entre chacune de vos lignes de scripts
pour essayer de voir où ça bloque.

- testez le résultat de chacun de vos appels système (open en
particulier).

- ajoutez 'use warnings;' (on ne sait jamais).


pas mieux avec ça :

#!/usr/bin/perl
use warnings;
print "Content-type: text/htmlnnOK1n<br>";
print STDERR "OKA";


print STDERR "OKAn"; #c'est plus propre dans un log ;-)

open(LEPIPE,"|cat > /tmp/null") or die "impossible d'ouvrir le pipe : $!";
print STDERR "OKB";
print LEPIPE "test";
print STDERR "OKC";
close LEPIPE;
print STDERR "OKD";
print "OK2";


Et qu'avez-vous dans votre fichier error_log si vous tuez le script qui
bloque ?


Ces autres scripts utilisent-ils eux aussi des pipes ?


Oui !!!


Dans ce cas, vous pouvez peut-être soupçonner la commande 'cat'...

print `which cat`

Avez-vous le droit d'écrire le fichier /tmp/null ?

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


Avatar
Christophe Baegert
Paul GABORIT wrote:


tiens, je ne me suis jamais posé la question... comment je fais ça ?
$ENV{'SHELL'} est vide en tout cas.


print `echo $SHELL`



Ce script se comporte exactement comme le premier !!!!

#!/usr/bin/perl


print "Content-type: text/plainnnSHELL:";
print `echo $SHELL`;


Et qu'avez-vous dans votre fichier error_log si vous tuez le script qui
bloque ?


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



Ces autres scripts utilisent-ils eux aussi des pipes ?


Oui !!!


Dans ce cas, vous pouvez peut-être soupçonner la commande 'cat'...


Justement j'ai mis le cat pour avoir la commande la plus basique possible,
car le problème est sur le pipe. En fait dans le vrai programme, ce n'est
pas cat que je veux utiliser (aucun intérêt...) mais sendmail.


print `which cat`

Avez-vous le droit d'écrire le fichier /tmp/null ?


-rw-rw-rw- 1 xxxx xxxx 4 jun 18 08:28 /tmp/null



Avatar
Paul GABORIT
À (at) Fri, 18 Jun 2004 09:41:10 +0200,
Christophe Baegert écrivait (wrote):
Paul GABORIT wrote:


tiens, je ne me suis jamais posé la question... comment je fais ça ?
$ENV{'SHELL'} est vide en tout cas.


print `echo $SHELL`



Ce script se comporte exactement comme le premier !!!!


Il se bloque indéfiniment ?

#!/usr/bin/perl


print "Content-type: text/plainnnSHELL:";
print `echo $SHELL`;


Et qu'avez-vous dans votre fichier error_log si vous tuez le script qui
bloque ?


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 ? 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.

En fait, je pense vraiment que vous avez un problème de shell. Les autres
scripts qui font appel à des pipes ne doivent pas utiliser le shell car ils
n'utilisent ni des redirections (>) ni des variables ($...) dans leur commande
d'exécution. Dans ce cas, perl ne passe pas par le shell.

Pour connaître le shell affecté à Apache, le plus simple est de demander à
l'administrateur de la machine...


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



Avatar
DominiX
"Christophe Baegert" a écrit dans
le message de news:cas3f5$1ajo$
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/htmlnnOK1n<br>";
open(LEPIPE,"|cat > /tmp/test");


il faut TOUJOURS tester le retour de open
open (...) or die "aie aie aie $!";

ensuite peut etre sera il evident que si /tmp/test existe appartenant
a root:root alors apache:nobody ne peux pas open it or cat to it.
qui sait ...

bonsoir a tous.

-- dominix

Avatar
Christophe Baegert
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>

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

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...


En fait, je pense vraiment que vous avez un problème de shell. Les autres
scripts qui font appel à des pipes ne doivent pas utiliser le shell car
ils n'utilisent ni des redirections (>) ni des variables ($...) dans leur
commande d'exécution. Dans ce cas, perl ne passe pas par le shell.

Pour connaître le shell affecté à Apache, le plus simple est de demander à
l'administrateur de la machine...


C'est lui-même...

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.


Avatar
Christophe Baegert
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)

1 2