J'ai besoin d'exécuter un script php en tant que processus démon (attendre les instructions et faire des choses). cron job ne le fera pas pour moi car des actions doivent être prises dès que l'instruction arrive. Je sais que PHP n'est pas vraiment la meilleure option pour les processus démons en raison de problèmes de gestion de la mémoire, mais pour diverses raisons, je dois utiliser PHP dans ce cas. Je suis tombé sur un outil de libslack appelé Daemon ( http://libslack.org/daemon ) il semble m'aider à gérer les processus démon, mais il n'y a pas eu de mises à jour au cours des 5 dernières années, donc je me demande si vous en connaissez d'autres alternatives adaptées à mon cas. Toute information sera vraiment appréciée.
154
Réponses:
Vous pouvez démarrer votre script php à partir de la ligne de commande (ie bash) en utilisant
nohup php myscript.php &
les
&
met votre processus en arrière-plan.Edit:
Oui, il y a quelques inconvénients, mais impossible à contrôler? C'est tout simplement faux.
Un simple
kill processid
l'arrêtera. Et c'est toujours la solution la meilleure et la plus simple.la source
nohup
et&
fait exactement la même chose: détacher le processus lancé de l'intance actuelle du shell. Pourquoi ai-je besoin des deux? Puis-je ne pas simplement fairephp myscript.php &
ounohup myscript.php
?? Mercinohup php myscript.php > myscript.log &
Une autre option consiste à utiliser Upstart . Il a été initialement développé pour Ubuntu (et est livré avec lui par défaut), mais est destiné à convenir à toutes les distributions Linux.
Cette approche est similaire à Supervisord et daemontools , en ce sens qu'elle démarre automatiquement le démon au démarrage du système et réapparaît à la fin du script.
Comment le configurer:
Créez un nouveau fichier de script sur
/etc/init/myphpworker.conf
. Voici un exemple:Démarrage et arrêt de votre démon:
Vérifiez si votre démon est en cours d'exécution:
Merci
Un grand merci à Kevin van Zonneveld , d'où j'ai appris cette technique.
la source
sudo service myphpworker start/stop/status
ne fonctionne qu'avec des services qui ne sont/etc/init.d
pas des services de démarrage. @ matt-sich semble avoir découvert la syntaxe correcte. Une autre option consiste à utiliser Gearman ou Resque, qui permet le traitement en arrière-plan et la désamonisation.Avec new systemd, vous pouvez créer un service.
Vous devez créer un fichier ou un lien symbolique dans
/etc/systemd/system/
, par exemple. myphpdaemon.service et placez le contenu comme celui-ci, myphpdaemon sera le nom du service:Vous pourrez démarrer, obtenir le statut, redémarrer et arrêter les services à l'aide de la commande
systemctl <start|status|restart|stop|enable> myphpdaemon
Le script PHP doit avoir une sorte de "boucle" pour continuer à fonctionner.
Exemple de travail:
Si votre routine PHP doit être exécutée une fois dans un cycle (comme un diggest), vous pouvez utiliser un script shell ou bash pour être appelé dans le fichier de service systemd au lieu de PHP directement, par exemple:
Si vous avez choisi ces options, vous devriez changer le KillMode en
mixed
processus, bash (main) et PHP (enfant) être tués.This method also is effective if you're facing a memory leak.
la source
systemctl status <your_service_name> -l
sortie, cela vous donnera un indice de ce qui se passe.Si vous le pouvez, prenez une copie de la programmation avancée dans l'environnement UNIX . L'ensemble du chapitre 13 est consacré à la programmation des démons. Les exemples sont en C, mais toutes les fonctions dont vous avez besoin ont des wrappers en PHP (essentiellement les extensions pcntl et posix ).
En quelques mots - écrire un démon (cela n'est possible que sur les systèmes d'exploitation basés sur * nix - Windows utilise des services) est comme ceci:
umask(0)
pour éviter les problèmes d'autorisation.fork()
et que le parent quitte.setsid()
.SIGHUP
(généralement ignoré ou utilisé pour signaler au démon de recharger sa configuration) etSIGTERM
(pour indiquer au processus de se terminer correctement).fork()
à nouveau et que le parent quitte.chdir()
.fclose()
stdin
,stdout
etstderr
et ne leur écrivez pas. La bonne façon est de les rediriger vers/dev/null
ou l' ou vers un fichier, mais je n'ai pas trouvé de moyen de le faire en PHP. Il est possible lorsque vous lancez le démon de les rediriger à l'aide du shell (vous devrez trouver vous-même comment faire cela, je ne sais pas :).De plus, puisque vous utilisez PHP, faites attention aux références cycliques, car le garbage collector PHP, avant PHP 5.3, n'a aucun moyen de collecter ces références et le processus perdra de la mémoire, jusqu'à ce qu'il finisse par se planter.
la source
J'exécute un grand nombre de démons PHP.
Je suis d'accord avec vous que PHP n'est pas le meilleur (ni même un bon) langage pour faire cela, mais les démons partagent le code avec les composants Web, donc dans l'ensemble, c'est une bonne solution pour nous.
Nous utilisons daemontools pour cela. C'est intelligent, propre et fiable. En fait, nous l'utilisons pour exécuter tous nos démons.
Vous pouvez vérifier cela à http://cr.yp.to/daemontools.html .
EDIT: une liste rapide des fonctionnalités.
la source
Vous pouvez
nohup
comme Henrik l'a suggéré.screen
et exécutez votre programme PHP comme un processus régulier à l'intérieur. Cela vous donne plus de contrôle que d'utilisernohup
.Je recommanderais la méthode la plus simple (écran à mon avis), puis si vous voulez plus de fonctionnalités ou de fonctionnalités, passez à des méthodes plus complexes.
la source
Il existe plusieurs manières de résoudre ce problème.
Je ne connais pas les détails mais il existe peut-être un autre moyen de déclencher le processus PHP. Par exemple, si vous avez besoin que le code s'exécute en fonction d'événements dans une base de données SQL, vous pouvez configurer un déclencheur pour exécuter votre script. C'est vraiment facile à faire sous PostgreSQL: http://www.postgresql.org/docs/current/static/external-pl.html .
Honnêtement, je pense que votre meilleur pari est de créer un processus Damon en utilisant nohup. nohup permet à la commande de continuer à s'exécuter même après la déconnexion de l'utilisateur:
Il y a cependant un problème très sérieux. Comme vous l'avez dit, le gestionnaire de mémoire de PHP est une poubelle complète, il a été construit avec l'hypothèse qu'un script ne s'exécute que pendant quelques secondes, puis existe. Votre script PHP commencera à utiliser des GIGABYTES de mémoire après seulement quelques jours. Vous DEVEZ ÉGALEMENT créer un script cron qui s'exécute toutes les 12 ou peut-être 24 heures qui tue et ré-génère votre script php comme ceci:
Mais que se passerait-il si le script était au milieu d'un travail? Eh bien kill -3 est une interruption, c'est la même chose que de faire un ctrl + c sur la CLI. Votre script php peut intercepter cette interruption et quitter gracieusement en utilisant la bibliothèque PHP pcntl: http://php.oregonstate.edu/manual/en/function.pcntl-signal.php
Voici un exemple:
L'idée derrière $ lock est que le script PHP peut ouvrir un fichier avec un fopen ("file", "w") ;. Un seul processus peut avoir un verrou d'écriture sur un fichier, vous pouvez donc vous assurer qu'une seule copie de votre script PHP est en cours d'exécution.
Bonne chance!
la source
Kevin van Zonneveld a écrit un très bel article détaillé à ce sujet , dans son exemple il utilise le
System_Daemon
package PEAR (dernière sortie le 02/09/2009).la source
Consultez https://github.com/shaneharter/PHP-Daemon
Il s'agit d'une bibliothèque de démons orientée objet. Il prend en charge des éléments tels que la journalisation et la récupération d'erreur, et prend en charge la création de travailleurs en arrière-plan.
la source
J'ai récemment eu besoin d'une solution multiplateforme (Windows, Mac et Linux) pour résoudre le problème de l'exécution de scripts PHP en tant que démons. J'ai résolu le problème en écrivant ma propre solution basée sur C ++ et en créant des binaires:
https://github.com/cubiclesoft/service-manager/
Prise en charge complète de Linux (via sysvinit), mais aussi des services Windows NT et du launchd Mac OSX.
Si vous avez juste besoin de Linux, alors quelques autres solutions présentées ici fonctionnent assez bien et, selon la saveur. Il y a aussi Upstart et systemd ces jours-ci, qui ont des solutions de secours pour les scripts sysvinit. Mais la moitié de l'intérêt d'utiliser PHP est qu'il est de nature multiplateforme, donc le code écrit dans le langage a de bonnes chances de fonctionner partout tel quel. Des lacunes commencent à apparaître lorsque certains aspects externes au niveau du système d'exploitation natif entrent dans l'image, tels que les services système, mais vous rencontrerez ce problème avec la plupart des langages de script.
Tenter d'attraper des signaux comme quelqu'un l'a suggéré ici dans le userland PHP n'est pas une bonne idée. Lisez
pcntl_signal()
attentivement la documentation et vous apprendrez rapidement que PHP gère les signaux en utilisant des méthodes plutôt désagréables (spécifiquement, les «ticks») qui grugent un tas de cycles pour quelque chose de rarement vu par les processus (c'est-à-dire les signaux). La gestion du signal en PHP est également à peine disponible sur les plates-formes POSIX et le support diffère en fonction de la version de PHP. Au départ, cela ressemble à une solution décente, mais elle est loin d'être vraiment utile.PHP s'est également amélioré sur les problèmes de fuite de mémoire au fil du temps. Il faut encore faire attention (l'analyseur DOM XML a encore tendance à fuir) mais je vois rarement des processus emballés ces jours-ci et le traqueur de bogues PHP est assez silencieux par rapport à autrefois.
la source
Comme d'autres l'ont déjà mentionné, exécuter PHP en tant que démon est assez simple et peut être fait en utilisant une seule ligne de commande. Mais le problème réel est de le faire fonctionner et de le gérer. J'ai eu le même problème il y a un certain temps et bien qu'il y ait déjà beaucoup de solutions disponibles, la plupart d'entre elles ont beaucoup de dépendances ou sont difficiles à utiliser et ne conviennent pas aux usages de base. J'ai écrit un script shell qui peut gérer n'importe quel processus / application, y compris les scripts PHP cli. Il peut être défini comme un cronjob pour démarrer l'application et contiendra l'application et la gérera. S'il est à nouveau exécuté, par exemple via le même cronjob, il vérifie si l'application est en cours d'exécution ou non, s'il le fait, il se ferme simplement et laisse son instance précédente continuer à gérer l'application.
Je l'ai téléchargé sur github, n'hésitez pas à l'utiliser: https://github.com/sinasalek/EasyDeamonizer
EasyDeamonizer
Surveille simplement votre application (démarrer, redémarrer, enregistrer, surveiller, etc.). un script générique pour vous assurer que votre appliation continue de fonctionner correctement. Intentionnellement, il utilise le nom du processus au lieu du fichier pid / lock pour éviter tous ses effets secondaires et garder le script aussi simple et réactif que possible, de sorte qu'il fonctionne toujours même lorsque EasyDaemonizer lui-même est redémarré. Caractéristiques
la source
Étendre la réponse d' Emil Ivaov , vous pouvez faire ce qui suit pour fermer STDIN, STDOUT ET STDERROR en php
En gros, vous fermez les flux standard pour que PHP n'ait pas de place pour écrire. Les
fopen
appels suivants définiront l'IO standard sur/dev/null
.J'ai lu ceci dans le livre de Rob Aley - PHP au-delà du web
la source
J'ai écrit et déployé un simple php-daemon, le code est en ligne ici
https://github.com/jmullee/PhpUnixDaemon
Fonctionnalités: suppression des privilèges, gestion du signal, journalisation
Je l'ai utilisé dans un gestionnaire de file d'attente (cas d'utilisation: déclencher une opération longue depuis une page web, sans faire attendre le php générateur de page, c'est-à-dire lancer une opération asynchrone) https://github.com/jmullee/PhpIPCMessageQueue
la source
vous pouvez vérifier pm2 ici est, http://pm2.keymetrics.io/
créez un fichier ssh, tel que worker.sh mis dans votre script php que vous allez traiter.
worker.sh
démarrage du démon
Bravo, c'est tout.
la source