Pregunta Ejecuta script php como proceso daemon


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) parece que me ayuda a gestionar los procesos de daemon, pero no ha habido actualizaciones en los últimos 5 años, por lo que me pregunto si conoces algunas otras alternativas adecuadas para mi caso. Cualquier información será realmente apreciada.


133
2018-01-10 10:06


origen


Respuestas:


Puede iniciar su script php desde la línea de comando (es decir, bash) utilizando

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.


149
2018-01-10 10:46



Otra opción es usar Advenedizo. 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 Daemon Tools, ya que inicia automáticamente el daemon en el arranque del sistema y reaparece en la finalización del script.

Cómo configurarlo:

Crea 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.


143
2018-05-16 01:54



Si puede, tome 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 toda la función que necesita tiene envoltorios en PHP (básicamente el pcntl y posix extensiones).

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

  1. Llamada umask(0) para evitar problemas de permisos.
  2. fork() y hacer que el padre salga.
  3. Llamada setsid().
  4. Configurar el procesamiento de 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 decirle al proceso que salga con gracia).
  5. fork() de nuevo y hacer que el padre salga.
  6. Cambiar el directorio de trabajo actual con chdir().
  7. fclose()  stdin, stdout y stderr y no les escribas La forma correcta es redirigirlos a cualquiera /dev/null o un archivo, pero no pude encontrar la manera 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.


44
2018-01-10 11:24



Con nuevo sistemad puedes crear un servicio (en rhel basado en Linux).

Debe crear un archivo o una enlace simbólico en /etc/systemd/system/, p.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   ejecuta `systemctl daemon-reload ', pero si no lo haces, te preocupes: será   cuando se necesita.


32
2018-06-07 18:35



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.

Puedes ver esto en http://cr.yp.to/daemontools.html.

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)

23
2018-01-19 05:32



Usted puede

  1. Utilizar nohup como Henrik sugirió.
  2. Utilizar screen y ejecuta tu programa PHP como un proceso regular dentro de eso. Esto le da más control que usar nohup.
  3. Use un daemonizador como http://supervisord.org/ (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.


14
2018-01-19 07:09



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 atrapar 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!


11
2018-01-18 22:57



Kevin van Zonneveld escribió un muy buen artículo detallado sobre este, en su ejemplo, él hace uso de la System_Daemon Paquete PEAR (última fecha de lanzamiento el 2009-09-02).


10
2018-01-15 15:19