"Daemonizer" un script PHP

16/10/2005 21:04:07

Suite à mon document sur la création de serveurs en PHP, peut-être certains d’entre vous ont dû se poser la question : comment « daemonizer » un script PHP ? En clair, comment faire en sorte qu’il fonctionne en arrière-plan sans user de saletés telles que nohup, comme un véritable serveur tel que Apache, MySQL, Samba, etc ?

Il est clair que la documentation de PHP manque de précision sur ce point, ce qui m’a forcé à aller récupérer quelques morceaux de réponse un peu partout et même à m’inspirer de programmes écrits en C ou en Perl. Je vais récapituler dans ce billet ce que j’ai appris.

Pour « daemonizer » un script PHP, il faut 3 étapes bien distinctes :

  • Le script doit se relancer lui-même en redirigeant tous les flux (STDIN, STDOUT, STDERR) vers /dev/null. Faute de quoi la sortie du script sera envoyée sur votre terminal. De plus, un problème avec OpenSSH se produit également lorsqu’on ne le fait pas.
  • Le processus doit être « forké ». En d’autres termes, on va faire une copie à l’identique du processus. La seule différence est que cette copie sera orpheline, c’est à dire qu’elle sera enfant direct de INIT (le processus racine du système), et non du terminal à partir duquel le démon a été lancé. On fermera ensuite le processus original. Si le fork n’st pas fait, l’administrateur se verra contraint de faire CTRL + C pour détacher le démon, ce qui n’est pas problématique (le processus ne sera pas fermé), mais peu esthétique.
  • Le processus doit être transformé en « chef de session ». Cela n’est pas réellement nécéssaire mais plus propre : ça évitera que le processus ne soit encore rattaché au terminal qui l’a lancé.

Pour programmer ces trois points, nous aurons besoin de 3 fonctions (respectivement) : proc_open(), pcntl_fork() et posix_setsid().

Voici le code :

// On se place dans le même répertoire que le script
chdir(dirname(__FILE__));

// On vérifie que l’extension PCNTL est bien là
if (!is_callable(‘pcntl_fork’))
{
	die(‘Error : PCNTL extension not available, recompile PHP with –enable-pcntl’.« \n »);
}


// Si cela n’est pas déjà été fait…
if (!in_array(‘/redirected’, $argv))
{
	// … on relance le script en redirigeant les flux
	
	$desc = array(
		0 => array(‘file’, ‘/dev/null’, ‘r’),
		1 => array(‘file’, ‘/dev/null’, ‘a’),
		2 => array(‘file’, ‘/dev/null’, ‘a’)
	);
	// Note : on peut améliorer ceci en repassant les paramètres de ligne de commande
	proc_open(‘php -f ‘.basename(__FILE__).‘ /redirected’, $desc, $null);
	
	// Puis on ferme le processus parent
	die();
}


// On tente de forker
$pid = pcntl_fork();

if ($pid == -1)
{
	// Erreur lors du fork
	die(‘Error: cannot fork’.« \n »);
}

if ($pid)
{
	// Fork réalisé : on ferme le processus original
	die();
}
else
{
	// Fork déjà réalisé : on ne fait rien

}

// On devient maître de session
posix_setsid();

// Let’s go !

Vous pouvez coder tout ce que vous voulez à la suite, ce sera « daemonizé ».

Rédigé par e-t172 |

3 réponses to “"Daemonizer" un script PHP”

  1. Mekza a répondu le 22/10/2005 à 19:02 #

    hum y a plus simple pour qu’un script tourne en background sans rien renvoyer dans le prompt, /path/vers/php -f MonFichier.php & > /dev/null

  2. e-t172 a répondu le 22/10/2005 à 19:58 #

    "hum y a plus simple pour qu’un script tourne en background sans rien renvoyer dans le prompt, /path/vers/php -f MonFichier.php & > /dev/null"

    Oui, oui, je le sais depuis pas mal de temps ;) mais comme l’objectif est de faire un script PHP "présentable", il est plus esthétique qu’il le fasse lui même… de plus ta méthode ne détache pas réellement le script de la session. Certes ça marche, mais ce n’est pas très propre.

  3. memphisto a répondu le 26/10/2005 à 20:04 #

    salut,
    on peut aussi lancer le serveur a travers screen, mais de toutes facon ce n’est pas aussi élégant que de programmer directement un demon comme tu le propose.
    a plus…

URL de trackback |