Surveiller la disponibilité d'un site 
Rien de bien extraordinaire , mais le principe m'amuse alors autant partager , et pourquoi pas récupérer des idées dans vos commentaires .
Le principe :
L'on me demande un moyen de vérifier si des sites distants sont disponibles , ou non de façon permanente .
J'ai donc décidé de développer un bout de script , qui ne fait ni plus ni moins que:
- Tester la résolution DNS ( Type A uniquement pour le moment )
- récupérer les en-têtes envoyés par le serveur en réponse à une requête HTTP.
- Récupération de ce qui m'intéresse , à savoir le code de status http , et le temps qu'a mis la réponse à me parvenir .
Ensuite , grâce à ces informations , je peux faire toute sorte de graphiques m'indiquant la disponibilité du/des sites surveillés dans le temps .
Exemple :

Le code
pour récupérer des données le plus proche de la réalité possible Comme j'ai dit plus haut , le code est très simple et rapide à mettre en place , il vous faudra cependant activer curl pour l'utiliser .
Vérifier la résolution de nom
Pour cette étape , nous allons utiliser la fonction native à php 4&5 checkdnsrr() :
checkdnsrr($adresse,"A");
Récupérer les entêtes HTTP
Pas besoin de récupérer la totalité , celà surchargerais inutilement les deux cotés , une première solution consiste à utiliser la fonction get_headers() en natif dans php5 :
get_headers ( "htp://".$adresse , true );
L'inconvénient de cette fonction , est qu'elle ne possède pas de timeout hormis celui de php , qui est bien trop long et peut pratique .
Les tests avec cette fonction se sont donc révélé bon , mais a généré l'augmentation de la consommation de mémoire de façon spectaculaire , voyez vous-même !

La solution , est donc d'utiliser curl , qui s'est révélé bien plus efficace , voici donc la fonction de remplacement de get_headers() ( sources fr2.php.net )
function get_headers_curl($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 20);
$r = curl_exec($ch);
$r = split("\n", $r);
return $r;
}
Si vous ne pouvez pas utiliser curl , vous pouvez aussi utiliser la fonction suivante , qui se base sur fsockopen() en natif dans php .
Note:merci à clochix de m'avoir signalé cette autre alternative.
/*
* Fonction de remplacement de get_headers
* Attention à ne pas mettre les http:// devant l'adresse
*/
function get_headers_sock($adresse, $timeout=15){
//Tableau qui vat contenir les entêtes
$Theaders = array();
$UserAgent = "User-Agent : Mozilla/4.0 (compatible; MSIE 5.0; Windows 95)";
$fp = fsockopen($adresse, 80, $errno, $errstr, $timeout);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
$out = "HEAD / HTTP/1.1\r\n";
$out .= "Host: $adresse\r\n";
$out .= "$UserAgent\r\n";
$out .= "Connection : Close\r\n\r\n";
fwrite($fp, $out);
while (!feof($fp)) {
$Theaders[] = fgets($fp, 128);
}
fclose($fp);
}
//renvoi des entêtes
if(!empty($Theaders)){
return $Theaders;
}else{
return null;
}
}
Cette fonction retourne tout comme get_headers() un tableau avec une ligne = une entrée .
Le timeout est ici défini à 20 secondes , car je juge que si l'entête n'est toujours pas là en 20secondes , le site n'est pas navigable normalement , donc indisponible .
Le code de status HTTP
Après avoir reçut la réponse HTTP , l'on décortique l'entrée du tableau n°0 qui correspond normalement à : HTTP/1.1 <code http> <etat>
Une petite expression régulière plus tard , on se retrouve avec le code http seul
//récupération des entêtes
$header = get_headers_curl($adresse);
if(!empty($header){
//le code http sera disponible dans $retour[1]
preg_match('#([0-9]{3})#',$header[0],$retour);
}
Le temps pour faire tout ça !
Il ne nous reste plus qu'à récupérer le temps total pour effectuer ces opérations ( temps d'envoi + temps de réception ).
Rien de plus simple , comme dans beaucoup d'exemple sur le net , nous utiliserons microtime()
$debut = microtime(true);
$header = get_headers_curl("http://".$adresse) ;
//ou get_headers_sock($adresse); ( attention à ne pas mettre http devant )
$fin = microtime(true);
$temps = round($fin-$debut,4);
Et voilà , nous avons toutes les infos nécessaire , ne reste plus qu'à les enregistrer .. en base , fichier .. comme vous voulez .
Exemple de code complet :
<?php
//definition du user_agent
$useragent="Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1";
//adresse à surveiller ( sans les http )
$adresse = "lindev.fr";
$retour = array(0,0);
$dns = 0;
$temps = 0;
//test du dns
if( checkdnsrr($adresse,"A")){
$debut = microtime(true);
$header = get_headers_curl("http://".$adresse) ;
$fin = microtime(true);
$temps = round($fin-$debut,4);
preg_match('#([0-9]{3})#',$header[0],$retour);
$dns = 1;
}else{
echo "Résolution DNS impossible";
}
//enregistrement des resulats
$result = array(
"DNS" => $dns,
"reponse" => $retour[1],
"tempsReponse" => $temps
);
//si timeout , impose le code 503
if($result['reponse'] == NULL){
$result['reponse'] = 503;
}
//enregistrement dans la base de données / ou fichier
... ... ...
function get_headers_curl($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 20);
$r = curl_exec($ch);
$r = split("\n", $r);
return $r;
}
?>
Mise en place
Il faut maintenant lancer ce script de façon régulière afin de surveiller le site de façon précise .
Je vais donc dans mon cas le lancer toutes les 10min , via cron
Vous voilà avec une table qui se remplis toute seule des informations citées ci-dessus , il ne vous reste plus qu'à en faire ce que bon vous semble avec .
Pour info , les graphiques générés ci-dessus sont fait via JPgraph qui fera pourquoi pas l'objet d'un billet pour son initiation .
Conclusion
Voilà une approche d'un outil qui je pense peut s'avérer utile , à partir du moment ou les sites surveillés ne se trouvent pas au même endroit que ce script de monitoring .
Ensuite , n'a de limite que votre imagination pour le faire évoluer , pour par exemple lancer des alertes au bout de X minutes de non-disponibilités , tester d'autres type de services comme les mails , ftp ect ...
J'attends vos retours et vos critiques sur l'idée ou la façon de faire afin d'améliorer tout ça .
A bientôt ,
Ch.
