crear php linux unix daemon

crear un daemon en php



Ejecuta script php como proceso daemon (12)

Necesito ejecutar un script php como proceso daemon (esperar instrucciones y hacer cosas). El trabajo cron no lo hará por mí porque las acciones deben tomarse tan pronto como llegue la instrucción. Sé que PHP no es realmente la mejor opción para los procesos de daemon debido a problemas de administración de memoria, pero debido a varias razones, tengo que usar PHP en este caso. Encontré una herramienta de libslack llamada Daemon ( http://libslack.org/daemon ) que parece ayudarme a gestionar los procesos de daemon, pero no ha habido actualizaciones en los últimos 5 años, así que me pregunto si conocen alguna otras alternativas adecuadas para mi caso. Cualquier información será realmente apreciada.


Como otros ya han mencionado, ejecutar PHP como daemon es bastante fácil, y se puede hacer usando una sola línea de comando. Pero el problema real es mantenerlo funcionando y administrarlo. He tenido el mismo problema hace bastante tiempo y aunque hay muchas soluciones disponibles, la mayoría de ellas tienen muchas dependencias o son difíciles de usar y no son adecuadas para usos básicos. Escribí un script de shell que puede administrar cualquier proceso / aplicación, incluidos los scripts de PHP cli. Se puede configurar como cronjob para iniciar la aplicación y contendrá la aplicación y la administrará. Si se ejecuta de nuevo, por ejemplo, a través del mismo cronjob, comprueba si la aplicación se está ejecutando o no, si lo hace, simplemente sale y deja que su instancia anterior continúe administrando la aplicación.

Lo cargué en github, no dude en usarlo: https://github.com/sinasalek/EasyDeamonizer

EasyDeamonizer

Simplemente vigila su aplicación (inicio, reinicio, registro, monitor, etc.). una secuencia de comandos genérica para asegurarse de que su aplicación siga funcionando correctamente. Intencionalmente, utiliza el nombre de proceso instread del archivo pid / lock para evitar todos sus efectos secundarios y mantener el script lo más simple y sofisticado posible, por lo que siempre funciona incluso cuando EasyDaemonizer se reinicia. Caracteristicas

  • Inicia la aplicación y, opcionalmente, un retraso personalizado para cada inicio
  • Asegura que solo se está ejecutando una instancia
  • Supervisa el uso de la CPU y reinicia la aplicación automáticamente cuando alcanza el umbral definido
  • Configurar EasyDeamonizer para que se ejecute a través de cron para ejecutarlo nuevamente si se detiene por algún motivo
  • Registra su actividad

Con el nuevo systemd puede crear un servicio (en rhel basado en Linux).

Debe crear un archivo o un symlink en /etc/systemd/system/ , ej. myphpdaemon.service y coloque un contenido como este, myphpdaemon será el nombre del servicio:

[Unit] Description=My PHP Daemon Service #Requires=mysqld.service memcached.service #May your script needs mysql or other services to run. #After=mysqld.service memcached.service [Service] User=root Type=simple TimeoutSec=0 PIDFile=/var/run/myphpdaemon.pid ExecStart=/usr/bin/php -f /srv/www/myphpdaemon.php arg1 arg2> /dev/null 2>/dev/null #ExecStop=/bin/kill -HUP $MAINPID #It''s the default you can change whats happens on stop command #ExecReload=/bin/kill -HUP $MAINPID KillMode=process Restart=on-failure RestartSec=42s StandardOutput=null #If you don''t want to make toms of logs you can set it null if you sent a file or some other options it will send all php output to this one. StandardError=/var/log/myphpdaemon.log [Install] WantedBy=default.target

Podrá iniciar, obtener el estado, reiniciar y detener los servicios utilizando el comando

systemctl <start|status|restart|stop|enable> myphpdaemon

El script PHP debe tener un tipo de "bucle" para continuar ejecutando.

<?php gc_enable();// while (!connection_aborted() || PHP_SAPI == "cli") { //Code Logic //sleep and usleep could be useful if (PHP_SAPI == "cli") { if (rand(5, 100) % 5 == 0) { gc_collect_cycles(); //Forces collection of any existing garbage cycles } } }

Ejemplo de trabajo:

[Unit] Description=PHP APP Sync Service Requires=mysqld.service memcached.service After=mysqld.service memcached.service [Service] User=root Type=simple TimeoutSec=0 #Restart=on-failure #RestartPreventExitStatus=1 #PrivateTmp=false PIDFile=/var/run/php_app_sync.pid ExecStart=/bin/sh -c ''/usr/bin/php -f /var/www/app/private/server/cron/app_sync.php 2>&1 > /var/log/app_sync.log'' KillMode=process Restart=on-failure RestartSec=42s [Install] WantedBy=default.target

Nota: Cada vez que cambie su "myphpdaemon.service" debe ejecutar `systemctl daemon-reload '', pero si no lo hace, pregúntese cuando sea necesario.


Consulte https://github.com/shaneharter/PHP-Daemon

Esta es una biblioteca daemon orientada a objetos. Tiene soporte incorporado para cosas como el registro y la recuperación de errores, y tiene soporte para crear trabajadores en segundo plano.


Ejecuto una gran cantidad de daemons de PHP.

Estoy de acuerdo con usted en que PHP no es el mejor (ni siquiera un buen) lenguaje para hacer esto, pero los daemons comparten el código con los componentes que se encuentran en la web, por lo que, en general, es una buena solución para nosotros.

Usamos daemontools para esto. Es inteligente, limpio y confiable. De hecho, lo usamos para ejecutar todos nuestros daemons.

Puede verificar esto en daemontools .

EDITAR: una lista rápida de características.

  • Inicia automáticamente el daemon al reiniciar
  • Reiniciar automáticamente dameon en caso de falla
  • El registro se maneja por usted, incluido el vuelco y la poda
  • Interfaz de gestión: ''svc'' y ''svstat''
  • UNIX amigable (no un plus para todos quizás)

Escribí e implementé un php-daemon simple, el código está en línea aquí

https://github.com/jmullee/PhpUnixDaemon

Características: caída de privilegios, manejo de señal, registro

Lo usé en un manejador de colas (caso de uso: desencadenar una operación prolongada desde una página web, sin hacer esperar a la generación de páginas php, es decir, iniciar una operación asincrónica) https://github.com/jmullee/PhpIPCMessageQueue


Hay más de una forma de resolver este problema.

No conozco los detalles, pero tal vez haya otra forma de activar el proceso de PHP. Por ejemplo, si necesita que el código se ejecute en función de los eventos en una base de datos SQL, puede configurar un disparador para ejecutar su secuencia de comandos. Esto es realmente fácil de hacer en PostgreSQL: http://www.postgresql.org/docs/current/static/external-pl.html .

Honestamente, creo que tu mejor opción es crear un proceso Damon usando nohup. nohup permite que el comando continúe ejecutándose incluso después de que el usuario haya cerrado la sesión:

nohup php myscript.php &

Sin embargo, hay un problema muy serio. Como dijo que el administrador de memoria de PHP es una basura completa, se construyó con la suposición de que un script solo se ejecuta durante unos segundos y luego existe. Su script PHP comenzará a usar GIGABYTES de memoria después de solo unos días. También DEBE crear un script cron que se ejecute cada 12 o tal vez 24 horas que mata y vuelve a generar su script php de esta manera:

killall -3 php nohup php myscript.php &

Pero, ¿y si el guión estuviera en el medio de un trabajo? Bueno, kill -3 es una interrupción, es lo mismo que hacer un ctrl + c en la CLI. Su script php puede detectar esta interrupción y salir con gracia utilizando la biblioteca PHP pcntl: http://php.oregonstate.edu/manual/en/function.pcntl-signal.php

Aquí hay un ejemplo:

function clean_up() { GLOBAL $lock; mysql_close(); fclose($lock) exit(); } pcntl_signal(SIGINT, ''clean_up'');

La idea detrás del $ lock es que el script PHP puede abrir un archivo con un fopen ("archivo", "w"); Solo un proceso puede tener un bloqueo de escritura en un archivo, así que al usarlo puede asegurarse de que solo se esté ejecutando una copia de su script PHP.

¡Buena suerte!



Otra opción es usar Upstart . Originalmente fue desarrollado para Ubuntu (y viene empaquetado con él por defecto), pero está destinado a ser adecuado para todas las distribuciones de Linux.

Este enfoque es similar a Supervisord y daemontools , ya que inicia automáticamente el daemon en el arranque del sistema y reaparece en la finalización del script.

Cómo configurarlo:

Cree un nuevo archivo de script en /etc/init/myphpworker.conf . Aquí hay un ejemplo:

# Info description "My PHP Worker" author "Jonathan" # Events start on startup stop on shutdown # Automatically respawn respawn respawn limit 20 5 # Run the script! # Note, in this example, if your PHP script returns # the string "ERROR", the daemon will stop itself. script [ $(exec /usr/bin/php -f /path/to/your/script.php) = ''ERROR'' ] && ( stop; exit 1; ) end script

Iniciando y deteniendo a tu daemon:

sudo service myphpworker start sudo service myphpworker stop

Verifica si tu daemon se está ejecutando:

sudo service myphpworker status

Gracias

Muchas gracias a Kevin van Zonneveld , de donde aprendí esta técnica.


Puedes comenzar tu script php desde la línea de comando (es decir, bash) usando

nohup php myscript.php &

el & pone su proceso en segundo plano.

Editar:
Sí, hay algunos inconvenientes, pero no es posible controlarlos? Eso está mal.
Un simple kill processid lo detendrá. Y sigue siendo la mejor y más simple solución.


Recientemente tuve la necesidad de una solución multiplataforma (Windows, Mac y Linux) para el problema de ejecutar scripts PHP como daemons. Resolví el problema escribiendo mi propia solución basada en C ++ y haciendo binarios:

https://github.com/cubiclesoft/service-manager/

Soporte completo para Linux (a través de sysvinit), pero también servicios de Windows NT y Mac OSX.

Si solo necesita Linux, entonces algunas de las otras soluciones presentadas aquí funcionan bastante bien y, dependiendo del sabor. También hay Upstart y systemd en estos días, que tienen inconvenientes con sysvinit scripts. Pero la mitad del punto de utilizar PHP es que es de naturaleza multiplataforma, por lo que el código escrito en el idioma tiene una gran posibilidad de funcionar en todas partes tal como está. Las deficiencias comienzan a aparecer cuando ciertos aspectos externos del nivel del sistema operativo nativo entran en escena, como los servicios del sistema, pero obtendrá ese problema con la mayoría de los lenguajes de scripting.

Intentar captar señales como alguien sugirió aquí en PHP userland no es una buena idea. Lea la documentación en pcntl_signal() cuidado y rápidamente aprenderá que PHP maneja las señales usando algunos métodos bastante desagradables (específicamente, ''tics'') que mastican un montón de ciclos por algo que los procesos raramente ven (es decir, señales). El manejo de señales en PHP apenas está disponible en plataformas POSIX y el soporte difiere según la versión de PHP. Inicialmente suena como una solución decente, pero no llega a ser realmente útil.

PHP también ha mejorado sus problemas de pérdida de memoria a medida que pasa el tiempo. Aún debe tener cuidado (el analizador DOM XML tiende a filtrarse) pero rara vez veo procesos fuera de control en estos días y el rastreador de fallos de PHP es bastante silencioso en comparación con los días de antaño.


Si puede, obtenga una copia de Programación avanzada en el entorno UNIX . Todo el capítulo 13 está dedicado a la programación daemon. Los ejemplos están en C, pero todas las funciones que necesita tienen envoltorios en PHP (básicamente las extensiones pcntl y posix ).

En pocas palabras, escribir un daemon (esto es posible solo en OS-es * basados ​​en * nix - Windows usa servicios) es como esto:

  1. Llame a umask(0) para evitar problemas de permisos.
  2. fork() y hacer que el padre salga.
  3. Llamar setsid() .
  4. Configure el procesamiento de la señal de SIGHUP (generalmente esto se ignora o se usa para indicar al daemon que vuelva a cargar su configuración) y SIGTERM (para indicarle al proceso que salga con elegancia).
  5. fork() nuevamente y haga que el padre salga.
  6. Cambia el directorio de trabajo actual con chdir() .
  7. fclose() stdin , stdout y stderr y no les escribas. La forma correcta es redirigirlos a /dev/null o a un archivo, pero no pude encontrar la forma de hacerlo en PHP. Es posible cuando ejecutas el daemon para redirigirlos usando el shell (tendrás que averiguar cómo hacerlo, no sé :).
  8. ¡Haz tu trabajo!

Además, dado que está utilizando PHP, tenga cuidado con las referencias cíclicas, ya que el recolector de basura PHP, antes de PHP 5.3, no tiene forma de recopilar esas referencias y el proceso perderá memoria, hasta que finalmente se bloquee.


Usted puede

  1. Use nohup como sugirió Henrik.
  2. Usa la screen y ejecuta tu programa PHP como un proceso regular dentro de eso. Esto le da más control que usar nohup .
  3. Utilice un daemonizador como Supervisord (está escrito en Python pero puede demonizar cualquier programa de línea de comandos y darle un control remoto para administrarlo).
  4. Escribe tu propia envoltura daemonise como sugirió Emil, pero es IMO excesivo.

Yo recomendaría el método más simple (en mi opinión, la pantalla) y luego, si quieres más características o funcionalidades, pasa a métodos más complejos.