Discussion:
fopen quand Safe Mode = On
(trop ancien pour répondre)
Jean-Francois Ortolo
2008-05-08 14:37:29 UTC
Permalink
Bonjour

Mon hébergeur ( Sivit mutualisé ) a le Safe Mode à On.

Celà implique des restrictions sur les fonctions, en particulier de
manipulation de fichiers.

Il me semblait avoir vu dans le PHP Manual sur le web, des
commentaires indiquant que pour faire une ouverture en écriture d'un
fichier sur le répertoire courant, il était mieux de faire d'abord un
touch($filename) puis en suite seulement un fopen($filename, "w").

Donc, mon instruction globale est la suivante:

if(!@touch($filename)||(!($fp = @fopen ($filename, "w")))
{
echo "Message d'erreur\n";
die(""); // Je pourrais
aussi bien mettre un exit;
}


Or, le script où se trouvent ces instructions, semble s'arrêter 1
fois sur 5 ou 6, sans créer le fichier $filename.

Le fichier $filename n'est pas accédé simultanément par un autre
script, seulement après par un autre script, qui s'aperçoit que le
fichier n'existe pas.

Je ne peux pas tester le message d'erreur, car le script est en
batch. Les errreurs sont imprévisibles.

Théoriquement, l'instruction $fp = @fopen($filename, "w") dans son
ensemble, rend la valeur de $fp d'après ce que je pense. Donc, je peux
grouper l'affectation et le test.

J'ai créé le répertoire courant et tous ses répertoires pères
manuellement, par le FTP.
Les permissions de tous les répertoires, sont au maximum de permissivité.

Je ne crée jamais de répertoire à partir d'un script PHP.

Le script PHP est lancé en mode module Apache.

D'où vient l'erreur ?

Merci beaucoup de vos réponses.

Jean-François Ortolo
P'tit Marcel
2008-05-08 16:30:58 UTC
Permalink
Post by Jean-Francois Ortolo
{
echo "Message d'erreur\n";
die(""); // Je pourrais
aussi bien mettre un exit;
}
Or, le script où se trouvent ces instructions, semble s'arrêter 1
fois sur 5 ou 6, sans créer le fichier $filename.
1/ Tu as bien placé un fclose($fp) avant la fin du script ?
Post by Jean-Francois Ortolo
Je ne peux pas tester le message d'erreur, car le script est en
batch.
Ben si. Cela fait plus de 40 ans que des ordinateurs font tourner des
batch et permettent d'en suivre le bon fonctionnement. Il faut alors
faire en sorte qu'on ait suffisamment d'information dans le flux de
sortie. Dans ton cas il faut supprimer les @ placés avant les fonctions
php.

Si le script est lancé en ligne de commande, c'est très simple :
.../php -f script.php > script.log
Post by Jean-Francois Ortolo
Le script PHP est lancé en mode module Apache.
Selon la même logique, tu peux lancer le script en demandant une trace
d'exécution :
.../lynx -source http://domaine/script.php > script.log
Post by Jean-Francois Ortolo
D'où vient l'erreur ?
en supprimant les @ et en stockant le flux de sortie dans un fichier log
comme indiqué ici, tu en sauras plus. Sinon tu peux toujours chercher
dans la log d'erreur d'apache et/ou de php.


eça
--
P'tit Marcel
stats sur les forums modérés http://www.centrale-lyon.org/ng/
Jean-Francois Ortolo
2008-05-08 19:40:02 UTC
Permalink
Bonjour P'tit Marcel

Finalement, le problème ne venait ( probablement ) pas du fichier non
ouvert.

J'ai deux script genere_stats.php et tache1_new_courses.php , il
s'exécutent en même temps.

Cependant, je croyais que le premier script était lancé par le
deuxième script, à la fin de celui-ci, ce qui est contrradictoire avec
la simultanéité des deux scripts, compte tenu du fait que le deuxième
script lance le premier script, à la fin du du second script, après un
traitement réseau par curl_exec(), qui doit nécessairement prendre du temps.

En fait, genere_stats.php a été lancé par un troisième script,
comportant une condition if/else , dont les deux branches sont
exécutées, car la condition du if est réévaluée lors du else, et se
trouve vérifiée dans les deux cas, suite au traitement du if. C'est du
moins ce que je crois constater, ne pouvant m'expliquer autrement la
simultanéité des deux scripts genere_stats.php et
tache1_new_courses.php, qui semblent tous les deux être lancés par ce
troisième script.

Cependant, dernier problème: Le code http de lancement de
tache1_new_courses.php est 200, alors que celui de genere_stats.php est
302. Les deux devraient être 302, ou à la rigueur 301, ç-à-d:
redirection temporaire ou permanente. ( J'ai plus le temps de vérifier
si la redirection est permanente ).

Donc méfiance: code 200 semble indiquer que ce script
tache1_new_courses.php est lancé de l'extérieur, donc pas par
redirection. Or, new_courses.php lance ce script ( théoriquement ) par
redirection dans ce cas.

D'où le problème: Le code 200 ( d'après les logs de mon hébergeur
Sivit mutualisé, je n'ai pas les moyens de lancer aucun script en ligne
de commande ). Ce code 200, indique-t-il obligatoirement, que le script
a été lancé de l'extérieur ?

L'adresse ip de provenance, est la même que les autres adresses ip (
les redirections ne changent pas l'adresse de provenance ). C'est
l'adresse ip du serveur qui lance le traitement batch sur mon site.

Le blème, c'est que ce lancement depuis ce serveur, n'aurait pas du
avoir lieu, car le traitement batch est lancé à partir d'un script Shell
sur le serveur, ce script Shell utilise la commande curl ( avec
paramètre -L, au plus 50 redirections ) pour lancer le script de départ,
à partir duquel les autres scripts PHP sur mon site seront
redirectionnés. Il est donc hors de question que le serveur lance ce
script tache1_new_courses.php, qui n'est pas le script de départ.

Donc, pensez-vous que le code 200 indique bien que ce script
tache1_new_courses.php , a été lancé depuis l'extérieur, en aucun cas
par redirection ?

A ce moment-là, je ferai des recherches sur le serveur en question,
pour détecter où a été lancé directement le script tache1_new_courses.php

Merci beaucoup de vos réponses.

Jean-François Ortolo
Christophe Meresse
2008-05-09 21:39:34 UTC
Permalink
On 8 mai, 21:40, Jean-Francois Ortolo
Post by Jean-Francois Ortolo
En fait, genere_stats.php a été lancé par un troisième script,
comportant une condition if/else , dont les deux branches sont
exécutées, car la condition du if est réévaluée lors du else, et se
trouve vérifiée dans les deux cas, suite au traitement du if. C'est du
moins ce que je crois constater, ne pouvant m'expliquer autrement la
simultanéité des deux scripts genere_stats.php et
tache1_new_courses.php, qui semblent tous les deux être lancés par ce
troisième script.
Heureusement non. Pour t'en convaincre:

<?php
if (true) {
echo "1";
}
elseif (true) {
echo "2";
}
?>

n'affiche que "1"...

Christophe
Paul
2008-05-09 21:39:34 UTC
Permalink
Post by Jean-Francois Ortolo
{
D'où vient l'erreur ?
AMHA, si la commabde touch n'a pas terminé son travail, et que tu
exécute fopen, ça plante.... tu le dis toi même : il faut D'ABORD créer
le fichier (touch) et ENSUITE ten(s)ter (fopen) son ouverture.
Olivier Miakinen
2008-05-09 22:54:32 UTC
Permalink
Post by Paul
AMHA, si la commabde touch n'a pas terminé son travail, et que tu
exécute fopen, ça plante.... tu le dis toi même : il faut D'ABORD créer
le fichier (touch) et ENSUITE ten(s)ter (fopen) son ouverture.
La fonction touch() ne serait donc pas synchrone ? Comment pourrait-elle
rendre la valeur « true » avant de savoir si tout s'est bien passé ou non ?
Mickael Wolff
2008-05-10 15:05:34 UTC
Permalink
Post by Olivier Miakinen
La fonction touch() ne serait donc pas synchrone ?
Tout à fait. Ça dépend du système d'exploitation et du système de
fichiers.
Post by Olivier Miakinen
Comment pourrait-elle
rendre la valeur « true » avant de savoir si tout s'est bien passé ou non ?
Parce que le système d'exploitation lui dit que c'est ok.

Il ne faut pas oublier que derrière PHP il y a un code en C, qui
fonctionne sur un OS. Le PHP est soumis à ces facteurs.
--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Paul
2008-05-10 15:05:34 UTC
Permalink
Post by Olivier Miakinen
Post by Paul
AMHA, si la commabde touch n'a pas terminé son travail, et que tu
exécute fopen, ça plante.... tu le dis toi même : il faut D'ABORD créer
le fichier (touch) et ENSUITE ten(s)ter (fopen) son ouverture.
La fonction touch() ne serait donc pas synchrone ? Comment pourrait-elle
rendre la valeur « true » avant de savoir si tout s'est bien passé ou non ?
Peut être, mais même si cette attente a lieu, si le fichier existe, que
dit elle ?
Mickael Wolff
2008-05-11 17:39:32 UTC
Permalink
Post by Paul
Peut être, mais même si cette attente a lieu, si le fichier existe, que
dit elle ?
D'après la documentation et le code source, l'âge du fichier n'est pas
vérifié sur un touch. Donc ça renvoie true si tout se passe bien.
--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Paul
2008-05-11 18:13:42 UTC
Permalink
Post by Mickael Wolff
Post by Paul
Peut être, mais même si cette attente a lieu, si le fichier existe, que
dit elle ?
D'après la documentation et le code source, l'âge du fichier n'est pas
vérifié sur un touch. Donc ça renvoie true si tout se passe bien.
sauf si l'OS décide que touch = créer et donc que si le fichier existe,
ça marche pas...
Mickael Wolff
2008-05-11 23:29:34 UTC
Permalink
Post by Paul
sauf si l'OS décide que touch = créer et donc que si le fichier existe,
ça marche pas...
Étant donné que utime (la fonction cachée par touch) doit être
conforme à SVr4 et POSIX.1-2001, ça me ferait bien mal. Et PHP
n'utilises pas les flags ad hoc pour forcer le comportement que tu
attends éventuellement.
--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Olivier Miakinen
2008-05-11 23:31:16 UTC
Permalink
Post by Paul
Post by Mickael Wolff
D'après la documentation et le code source, l'âge du fichier n'est pas
vérifié sur un touch. Donc ça renvoie true si tout se passe bien.
sauf si l'OS décide que touch = créer et donc que si le fichier existe,
ça marche pas...
J'espère bien qu'il n'existe aucun O.S. de ce genre, ou que si PHP est
porté sur un tel O.S. les développeurs auront l'intelligence de ne pas
se faire avoir par le nom de cette commande et qu'ils en utiliseront
une autre pour implémenter le touch() ! Mais personnellement ça me
semblerait aussi stupide qu'un commande cd qui ferait rmdir, ou une
commande date qui ferait reboot.

Jean-Francois Ortolo
2008-05-10 15:05:34 UTC
Permalink
Post by Olivier Miakinen
Post by Paul
AMHA, si la commabde touch n'a pas terminé son travail, et que tu
exécute fopen, ça plante.... tu le dis toi même : il faut D'ABORD créer
le fichier (touch) et ENSUITE ten(s)ter (fopen) son ouverture.
La fonction touch() ne serait donc pas synchrone ? Comment pourrait-elle
rendre la valeur « true » avant de savoir si tout s'est bien passé ou non ?
Bonjour Monsieur

Mais... Est-il vrai que quand le Safe Mode est à On, il faille
nécessairement faire précéder un fopen en mode "w" par un touch ?

Merci beaucoup à vous pour cette question épineuse, je ne vois plus
de commentaires d'Américains sur le PHP Manual à ce sujet.

Et puis... Autre point important: Est-il vrai qu'en Safe Mode, il
soit impossible de faire des curl_exec(), avec des headers comportant la
variable suivante FOLLOW_LOCATION, égale à 1 ?

Et quel effet exact a cette variable ? Permettre plusieurs
redirections après l'exécution du curl_exec() ? Ou permettre au moins
une rediection dans l'url cible, par header("Location:$url2") ?

Merci beaucoup de vos réponses.

Jean-François Ortolo
Continuer la lecture sur narkive:
Loading...