Exécuter un script au-delà du timeout de php

Soyez le premier à donner votre avis sur cette source.

Vue 19 577 fois - Téléchargée 598 fois

Description

Ce script montre une méthode permettant d'exécuter un script au-delà du timeout de PHP.

J'en suis venu à cette idée ainsi: si je fais par exemple un export d'une grosse base de données avec un script PHP, je risque de dépasser les 30 secondes (le max_execution_time) autorisées par le serveur où je suis hébergé.

Alors comment faire? En associant AJAX à PHP!

Le principe: Ajax surveille que le script ne s'exécute que pendant un temps t<timeout et fait boucler le script jusqu'à ce que l'exécution soit terminée.

Le code présenté ici est un exemple. A vous de l'adapter si vous en avez l'intérêt!

Source / Exemple :


############# FICHIER index.php

<html>
	<head>
		<title>Exécuter un script au-delà du timeout de PHP</title>
		<!-- script mootools.js téléchargé sur http://mootools.net/download -->
		<script type="text/javascript" src="mootools.js"></script>
		<script type="text/javascript">
			<?php
			
				// temps maximal d'exécution du script autorisé par le serveur
				$max_time = ini_get('max_execution_time');
				// 30 secondes par défaut:
				if ($max_time == '') $max_time = 30;
				
				// on prend 10% du temps maximal comme marge de sécurité
				$ourtime = ceil(0.9*$max_time);
				
				// variable pour les tests, à retirer en production
				$ourtime = 4;
				
				// variable(s) devant être surveillée(s) - exemple
				$i = 10;
				
			?>
		
			window.addEvent('domready', function(){
				$('start').addEvent('click', function(e) {
					e = new Event(e).stop();
					var url = "time.php?t=<?php echo $ourtime;?>&i=<?php echo $i;?>";
					new Ajax(url, {method: 'get', evalScripts:true}).request();
				});
			}); 	
		</script>
	</head>
	<body>
		<h3>Exécuter un script au-delà du timeout de PHP</h3>
		<p><a id="start" href="#">Cliquez ici</a> pour lancer le test</p>
		Timeout après: <b><?php echo $ourtime;?> secondes</b><br />
		Temps d'une boucle: <b>environ 1 seconde</b><br /><br />
		Résultat:<br /><div id="result"></div>
	</body>
</html>

############# FICHIER time.php

<?php
header('Content-type: text/html; charset=iso-8859-1');

echo '<script type="text/javascript">'."\n";

// récupération des variables;
$main_ourtime = $_GET['t'];
$i = $_GET['i'];
$temps_total = $_GET['tillnow'];
$ourtime = $main_ourtime;

function timer(){ //chronomètre - http://www.phpcs.com/code.aspx?ID=32471
	$time=explode(' ',microtime());
	return $time[1] + $time[2];
}

$rep = '';

$start_while=timer(); // début du chronométrage du while
while ($i>0 && $ourtime>0){

	$start=timer(); // début du chronométrage de l'itération
	
	sleep(1); // traitement - le sleep simule un temps de traitement de une seconde
	
	$i--;
	
	$ourtime -= (int)number_format(timer()-$start,7);
	$rep .= $i.'... ';// texte de sortie
}
$end_while = number_format(timer()-$start_while,7);
$temps_total += $end_while;

echo '$(\'result\').innerHTML += \'<b>'.$rep.'(<font color="#00aa00">'.$end_while.' sec.</font>)</b><br />\';'."\n";

if($i>0){ // si l'exécution du script a été interrompue pour éviter le timeout, on reprend où on s'est arrêté
echo 'var url = "time.php?t='.$main_ourtime.'&i='.$i.'&tillnow='.$temps_total.'";

	new Ajax(url, {
			method: \'get\',';
if ($i>0)
	echo 'evalScripts:true,';
echo '}).request();';
}
else
	echo '$(\'result\').innerHTML += \'<b><font color="#0000aa">terminé en '.$temps_total.' secondes!</font></b><br />\';'."\n"; // traitement des données
	
echo '</script>';
?>

Conclusion :


AJAX est traité ici avec l'excellente librairie mootools disponible sur http://www.mootools.net

Une condition sine qua none pour que cette astuce fonctionne est que le temps d'exécution d'une itération dans la boucle soit inférieur au time out.

L'exécution de l'exemple ci-dessus donne:

9... 8... 7... 6... (4.0000000 sec.)
5... 4... 3... 2... (4.0000000 sec.)
1... 0... (2.0000000 sec.)
terminé en 10 secondes!

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

LeFauve42
Messages postés
239
Date d'inscription
vendredi 20 octobre 2006
Statut
Membre
Dernière intervention
20 avril 2009
-
> Si cela est toutefois possible, je ne vois pas o? ins?rer mon script dans ce code.

Je dirais a la place du sleep(1);

Le code a inserer doit pouvoir generer une image d'apres le numero de la variable $i, que tu initialiseras a 1200.

Bonne chance.
cs_arnotw
Messages postés
3
Date d'inscription
samedi 27 mai 2006
Statut
Membre
Dernière intervention
28 mai 2008
-
Bonjour,

Désolé de reveiller ce post, mais ça m'interesse.
Je cherche à éviter le time out car j'ai un script PHP avec une boucle qui doit générer des images à la volée (pas loin de 1200).
Si cela est toutefois possible, je ne vois pas où insérer mon script dans ce code.

merci !

arno
verdy_p
Messages postés
203
Date d'inscription
vendredi 27 janvier 2006
Statut
Membre
Dernière intervention
29 janvier 2019
-
Je n'ai pas attaqué Microsoft sur ce coup là. Justement j'ai écrit que la méthode choisie par Mirosoft était plus générale que celle utilisée dans d'autre navigateurs qui ont choisi d'intégrer une seule version des API d'interactivité asynchrone avec un serveur web.

Personnellement je trouve que la solution de Microsoft (XmlHttpRequest) est une réponse intelligente face au développement d'une autre technologie qui était, elle, totalement propriétaire: Macromédia Flash, devenu Adobe. Microsoft a démontré qu'on pouvait mettre à profit des standards interopérable (notamment HTTP qui est très versatile) pour créer la fonctionalité attendue. Il est naturel que Microsoft l'ait expérimenté d'abord dans un composant nécessaitnat ActiveX, avant de vouloir l'intégrer d'une façon plus ouverte (ce qu'il a fait depuis). XmlhttpRequest dans ses fonctionalités ne nécessite pas Activex puisqu'il n'a pas besoin d'obtenir des informations du navigateur mais se comporte comme un objet autonome. on doit pouvoir l'instancier de n'importe quel moyen, l'objet lui-même nepouvant interagir qu'à l'aide d'évènements qu'il appartient à l'outil voulant l'intégrer, d'intercepter. ActiveX est une méthode possible d'intégration d'un objet, mais on peut évidemment faire la même chose avec toute autre méthode (DCOM chez Microsoft aussi, ou Corba, ou des bindings spécifiques en Javascript, ou en Java dand un objet Applet, etc. voire même dans d'autres systèmes propiétaires y compris en Flash, ou VB...)

L'important est de comprendre son API, en traitant l'objet comme une boite noire également en dehors de son utilisation (Ajax par exemple n'en est qu'une application d'une toute petite partie de ses fonctionalités), et de comprendre que pour fonctionner, son hôte doit supporter la création de threads (ou processus) séparés, et la transmission asynchrone d'évènements d'un thread (ou processus) dédié à l'objet à un autre, celui spécifié par l'application ; hors il se trouve que XmlHttpRequest n'est qu'une formalisation des fonctionalités de HTTTP (pas de XML) et que donc c'est une façon d'exposer HTTP (un standard international) au travers d'une API. L'objet en lui même n'a rien de propriétaire (ce qui l'est, c'est son intégration via ActiveX). Ce qui peut tromper ici est le nom de l'objet "XmlHttpRequest" qui en fait devrait n'être que "HttpRequest", puisqu'il ne fait absolument rien en XML lui-même (la partie XML est faite par l'application cliente utilisant l'objet, c'est à dire ici la librairie Ajax).
malalam
Messages postés
10843
Date d'inscription
lundi 24 février 2003
Statut
Modérateur
Dernière intervention
2 mars 2010
17 -
Hello,

déjà, ce n'est pas mon script :-) J'ai développé avant celui-ci (et posté sur CS) un concept similaire, sans utiliser de librairie JS.
L'utilisation d'une librairie JS se justifie dans le cas où on l'utilise réellement, dans un cadre plus global : Malik nous montre ici ujne astuce, qui peut s'intégrer dans un applicatif web; c'est un outil. Et en ce sens, il est vrai que l'utilisation d'une librairie JS est de plus en plus fréquente dans les applicatifs web. Malik a choisi mootools, bon, c'est son choix. Il est très simple de reprendre le concept qu'il montre avec ses propres outils, sa propre façon de coder. C'est même nécessaire : ce code-ci n'est qu'un exemple, une démonstration de l'astuce dont il nous fait part.

Pour ce qui est des particularités de l'objet xmlhttprequest en fonction du navigateur, c'est une réalité...qui n'est absolument pas propre à cet objet, mais au web en général : chaque navigateur propose SON implémentation des technologies web côté client, que ce soit pour cet objet, pour JS, html, css, xsl etc...c'est malheureusement comme ça.
Et pour une fois, je vais "défendre" Microsoft sur les objets xmlhttprequest : c'est Microsoft qui a créé cette méthode. Et commercialement parlant, comme svt avec Microsoft, ils ont fait le choix du "on offre une fonctionnalité géniale, mais si vous voulez en profiter, vous devez utiliser du Microsoft! C'est à nous...!". On en pensera ce que l'on veut...mais du coup, on peut aussi se faire l'avocat du diable et se dire : ils l'ont inventé, leut technologie passe par un ActiveX, c'était peut-être aux autres à s'adapter...
D'ailleurs, le W3C travaille depuis quelques temps à un "clone" de xmlhttprequest mais "standardisé" W3C. Une reco, quoi.
verdy_p
Messages postés
203
Date d'inscription
vendredi 27 janvier 2006
Statut
Membre
Dernière intervention
29 janvier 2019
-
Ceci dit mootools.js est la concaténation de 3 scripts:
- un premier fournit des méthodes itératives pour les collections d'objets, de propriétés et de méthodes applicables aux objets ou chaines, et quelques méthodes numériques. Il essaye aussi de détecter le type de navigateur utilisé en consultant l'existence de certaines propriétés accessibles via le DOM en Javascript (à partir de "window" ou de "document").
- un second "XHR" fournit un wrapper simple pour XmlHttpRequest, mais s'arrête là. il ne réalise pas le décodage XML, mais permet de distinguer les réponses de type "text" ou "xml" (qui seront analysées plus tard). Il comporte le support du protocole HTTP (mais incomplet). Il dépend du premier script.
- le dernier fournit le décodage XML et les bindins en collections javascript, et des méthodes facilitant la construction d'objets HTML dans la page à partir des collections XML. C'est lui qui fournit l'objet "Ajax".

Il y a un problème dans le second objet (XHR). Il ne semble pas traiter correctement les réponses HTTP autres que 200 à 299 comme succès, et traite les réponses de progresssion 100 à 199 comme des erreurs alors qu'elles ne mettent pas fin à la requête en cours. Le wrapper ne semble pas prendre en compte non plus les redirections (300 à 399) pour aller chercher la réponse ailleurs: ce sont pour lui des erreurs; l'objet Ajax du 3e script supporte assez mal le traitement des erreurs HTTP, et partiellement les erreurs de conformité puis de validation XML (qui ne sont pas traitées); il ne gère pas non plus les réponses au format HTML (sauf ceux compatibles XHTML) qui ne peuvent être traitées que comme du texte.

Ce script mootools.js est peut être très bien écrit, mais c'est un vériable marteau pour écraser une mouche, de fait il est complexe d'en percevoir les limites s'il ne marche pas. Ici, je suggérerais plutôt de montrer le principe plus simple à partir de xmlHttpRequest (avec le traitement particulier demandé par IE). On peut ensuite référencer ce script mootools.js mais à condition d'avoir compris ce que fait XmlHttpRequest et ses possibilités et limitations.

Personnellement je n'ai jamais eu besoin d'utiliser un tel script, j'utilise XmlHttpRequest directement (avec quelques tests pour la compatibilité IE) sans toute cette surcouche, avec de bien meilleures performances (sachant qu'IE est relativement lent avec Javascript à cause de ses validations constantes via ActiveX qui est un goulot d'étranglement de la plupart des objets, même s'il est là pour fournir une couche de sécurité et d'isolation entre objets). Ce qui me permet aussi de faire plus facilement n'importe quel type de requête, pas seulement des requêtes XML bien structurées: je ne demande pas au navigateur de valider les plus petites données que génère le serveur, ou de les remettre en forme (blancs, capitalisation, notation Camel, etc...)

En Javascript souvent, plus c'est simple, et mieux ça marche.

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.