OVH Cloud OVH Cloud

recuperer erreur de depassement de temps

11 réponses
Avatar
Olivier Masson
Bonjour,

est-il possible de savoir si une erreur de dépassement de temps
d'execution a eu lieu pendant un exec() (outre l'error_reporting qui
sera désactivé) et de reprendre l'execution ?

Cet exec va produire un fichier mais, malheureusement, si le script PHP
est interrompu, le fichier ne sera pas vide : je ne peux donc pas faire
de vérification en fonction de l'existence et la taille de ce fichier.

Y'a-t'il une solution ?

Merci.

10 réponses

1 2
Avatar
loufoque

Y'a-t'il une solution ?


Regarde s'il y a une erreur sur stderr ou alors regarde la valeur de
retour, le tout avec proc_open.

Avatar
Marc
Olivier Masson wrote:

est-il possible de savoir si une erreur de dépassement de temps
d'execution a eu lieu pendant un exec() (outre l'error_reporting qui
sera désactivé) et de reprendre l'execution ?

Cet exec va produire un fichier mais, malheureusement, si le script PHP
est interrompu, le fichier ne sera pas vide : je ne peux donc pas faire
de vérification en fonction de l'existence et la taille de ce fichier.



tu peux mettre en place un mécanisme qui par defaut marque le
traitement comme non terminé, et si par bonheur le traitement
se termine, tu changes l'état du résultat du traitement.

De cette facon lorsque tu arrives sur ton script, tu sais si
le traitement s'est terminé ou pas.

L'emplacement ou va resider l'information est soit un fichier
soit une base de données en fonction du contexte.

voici un exemple presque complet :

<?php

# ce booleen devrait etre sauvegardé en BD ou fichier
# ce n'est pas l'objet de ce script.

$bool = null;

fonction traitement_long(){
global $bool;

# on marque le traitement comme non terminé
$bool = false;

$res = exec(...);

$bool = true;
return $bool;
}



function main(){
global $bool;
if($bool == false){
echo "le dernier traitement a echoué par timeout (trop long)n";
}

traitement_long();


}

main();

?>

Avatar
Olivier Masson

Regarde s'il y a une erreur sur stderr ou alors regarde la valeur de
retour, le tout avec proc_open.


Pas possible puisque : Fatal error: Maximum execution time of 30 seconds
exceeded in...
Le script est arrêté donc pas de lecture de la sortie possible.

Avatar
Olivier Masson


tu peux mettre en place un mécanisme qui par defaut marque le
traitement comme non terminé, et si par bonheur le traitement
se termine, tu changes l'état du résultat du traitement.

De cette facon lorsque tu arrives sur ton script, tu sais si
le traitement s'est terminé ou pas.



Oui mais puisque le script s'arrête, je ne peux pas contrôler cette
variable justement !
Il faudrait pour cela que l'utilisateur relance le script pour cela et
c'est bien ce que je veux éviter.

Avatar
ftc
Bonjour,

est-il possible de savoir si une erreur de dépassement de temps
d'execution a eu lieu pendant un exec() (outre l'error_reporting qui
sera désactivé) et de reprendre l'execution ?


Tiré de la documentation:
"Note : La fonction set_time_limit() et la directive de configuration
max_execution_time n'affectent que le temps d'exécution du script
lui-même. Tout temps passé en dehors du script, comme un appel système
utilisant system(), des opérations sur les flux, les requêtes sur base
de données, etc. n'est pas pris en compte lors du calcul de la durée
maximale d'exécution du script."


Si j'en crois cette note, ton exec doit s'exécuter en intégralité
quelque soit la valeur de max_execution_time.

Mais j'imagine que c'est dans le script lancé qu'il y a un dépassement
de temps, je vois deux solutions:
- écrire ce script dans un autre langage disponible ( shell, python,
perl ... )
- placer un fichier comme drapeau au moment du lancement du script que
celui-ci efface lorsqu'il a terminer. Au retour de la fonction exec(),
tu testes la présence du fichier, s'il est présent, le script ne s'est
pas bien déroulé ( Attention à la concurrence des script, il faudrait
générer le nom de façon unique ).

Avatar
Marc
Olivier Masson wrote:

Oui mais puisque le script s'arrête, je ne peux pas contrôler cette
variable justement !
Il faudrait pour cela que l'utilisateur relance le script pour cela et
c'est bien ce que je veux éviter.


oui, tu peux relancer, c'est la seule chose a faire, il n'y a pas
d'alternative sauf a etre hebergé sur un serveur dont tu maitrises
ces aspects.

Avatar
Olivier Masson


Tiré de la documentation:
"Note : La fonction set_time_limit() et la directive de configuration
max_execution_time n'affectent que le temps d'exécution du script
lui-même. Tout temps passé en dehors du script, comme un appel système
utilisant system(), des opérations sur les flux, les requêtes sur base
de données, etc. n'est pas pris en compte lors du calcul de la durée
maximale d'exécution du script."


Si j'en crois cette note, ton exec doit s'exécuter en intégralité
quelque soit la valeur de max_execution_time.


Je n'avais jamais lu cette note qui me réjouit mais qui me pose un
nouveau problème, car c'est bel et bien l'exec qui provoque l'erreur
fatale !
Enfin non puisqu'ils disent que non, mais oui parce qu'il n'y a rien
avant (il y a un echo qui écrit la commande que je passe ensuite à
l'exec()) et rien ensuite (un autre echo pour confirmer).
Le temps passé ne provient donc *que* de l'exec. J'ai testé system() et
proc_open() pour le même résultat.


Mais j'imagine que c'est dans le script lancé qu'il y a un dépassement
de temps, je vois deux solutions:
- écrire ce script dans un autre langage disponible ( shell, python,
perl ... )


Tiens, je ne m'étais jamais posé la question : sur les hébergements
mutualisé, il y a également un tps d'exec max pour Perl et Python (moins
répandu chez les hébergeurs) ?
Mais bon, je n'ai pas envie de réécrire mon script.

Avatar
loufoque

Pas possible puisque : Fatal error: Maximum execution time of 30 seconds
exceeded in...
Le script est arrêté donc pas de lecture de la sortie possible.


Je ne vois pas le problème.

lanceur.php
<?php
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("file", "w")
);

$process = proc_open('php lescript.php', $descriptorspec, $pipes);

fclose($pipes[2]);
fclose($pipes[1]);
fclose($pipes[0]);

$return_value = proc_close($process);

echo "La commande a retourné $return_valuen";

?>

lescript.php
N'importe quel script php qui prend du temps

lanceur.php ne dépassera jamais de la limite de temps.

Avatar
Olivier Masson

Je ne vois pas le problème.

lanceur.php
<?php
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("file", "w")
);

$process = proc_open('php lescript.php', $descriptorspec, $pipes);

fclose($pipes[2]);
fclose($pipes[1]);
fclose($pipes[0]);

$return_value = proc_close($process);

echo "La commande a retourné $return_valuen";

?>

lescript.php
N'importe quel script php qui prend du temps

lanceur.php ne dépassera jamais de la limite de temps.


Merci.
Bon, ça ne fonctionne pas mais c'est gentil :)
Bon, j'ai perdu aussi 2 heures à triturer ça dans tous les sens, mais
c'est pas grave :(
Bref, c'est censé être très simple, c'est censé fonctionner puisque
exec() ne devrait pas être comptabilisé dans le temps d'exécution, etc.
mais pourtant *rien ne fonctionne*.

Quoique je fasse, dont un exec (ou system ou proc_open) qui lance un
php, le script principal s'arrête à cause du temps d'exécution.

Avatar
loufoque

Bon, ça ne fonctionne pas mais c'est gentil :)


Faut juste corriger les erreurs que j'ai faites en copiant/collant...
s/file/pipe/

Et bien sûr comprendre le code, sinon il est inutilisable.

1 2