Eseguire uno script php come processo demone

Ho bisogno di eseguire uno script php come processo demone (in attesa di istruzioni e fare le cose). cron job non lo faccio per me, perché sono le azioni da intraprendere non appena l’istruzione arriva. So che PHP non è davvero la migliore opzione per il demone processi a causa di problemi di gestione della memoria, ma a causa di vari motivi devo usare PHP in questo caso. Mi sono imbattuto in uno strumento da libslack chiamato Daemon (http://libslack.org/daemon) sembra che mi aiuti a gestire i processi del demone, ma non c’è stato alcun aggiornamento negli ultimi 5 anni, quindi mi chiedo se è a conoscenza di qualche altra alternative adatto per il mio caso. Ogni informazione sarà molto apprezzato.

InformationsquelleAutor Beier | 2010-01-10



14 Replies
  1. 159

    Si potrebbe iniziare il vostro script php da linea di comando (es. bash) utilizzando

    nohup php myscript.php &

    il & mette il processo in background.

    Edit:

    Sì, ci sono alcuni svantaggi, ma non è possibile controllare? Questo è un errore.

    Un semplice kill processid si fermerà. Ed è ancora la soluzione migliore e più semplice.

    • non se si utilizza nohup
    • Se il terminale esiste il processo NON si esce. Ecco perché il “nohup” comando c’è. Ho usato uno script PHP come demone su tutti i server come questo per anni. Ci potrebbe essere la soluzione migliore, ma questo è il modo più veloce uno.
    • Questo non riavviare il demone se non riesce, e non vi è alcun modo semplice per gestire il demone a tutti.
    • Sono d’accordo con quello che è stato detto qui-questa è una cattiva soluzione. Si dovrebbe creare uno script di init per un paio di motivi: 1) Init script viene lanciato automaticamente all’avvio 2) È possibile gestire il demone con start/stop/restart comandi. Qui è un esempio da servefault: serverfault.com/questions/229759/…
    • ehi ragazzi … mi sembra nohup e & fa la stessa cosa: se si scollega il processo avviato dall’attuale intance della shell. Perché ho bisogno di entrambi? Non posso proprio fare php myscript.php & o nohup myscript.php?? Grazie
    • Aggiungere un pò più di chiarezza a questo. nohup renderà script ignorare un SIGTERM sarà, ovviamente, continuano a morire con un KILL. Hai bisogno di entrambi, il nohup farà in modo che se il processo padre muore lo script non è preso con esso, il & farà sicuramente sarà spinto a fondo come presto come si chiama. In breve questo è una bella anche se hacky modo per demonizzare e in PHP siete molto dipende hacky modi per questo caso d’uso.
    • Se lo script scrive su stdout (via eco o un var_dump) poi si può prendere queste informazioni con un file di log come questo: nohup php myscript.php > myscript.log &
    • -1: i consigli qui è scarsa e si tradurrà in un processo non è adeguatamente isolato dal terminale di controllo, e dando luogo a zombie.

  2. 155

    Un’altra opzione è quella di utilizzare Upstart. È stato originariamente sviluppato per Ubuntu (e viene fornito con esso per impostazione predefinita), ma è destinato ad essere adatto per tutte le distribuzioni Linux.

    Questo approccio è simile a Supervisord e daemontools, che automaticamente avvia il demone all’avvio del sistema e ricompare sul completamento di script.

    Come impostare il tutto:

    Creare un nuovo file di script /etc/init/myphpworker.conf. Qui è un esempio:

    # 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

    Di partenza & fermare il demone:

    sudo service myphpworker start
    sudo service myphpworker stop

    Verificare se il demone è in esecuzione:

    sudo service myphpworker status

    Grazie

    Un grande grazie a Kevin van Zonneveld, dove ho imparato questa tecnica da.

    • amare questo. Chiedo solo, è possibile avere più di un concorrente lavoratori? Ho solo il problema che un lavoratore non è più abbastanza.
    • Sopra il mio livello di esperienza, mi dispiace!
    • questo sarà l’esecuzione automatica all’avvio del sistema?
    • Sudo “servizio myphpworker start” non ha funzionato per me. Ho usato il comando “sudo start myphpworker” e funziona perfettamente
    • Durante l’esecuzione di “sudo service myphpworker start” che mostra il suo myphpworker: non riconosciuto di servizio.
    • Ecco perché c’è un errore nel post – io non sono esattamente sicuro di cosa (e non testato questo), ma penso che sudo service myphpworker start/stop/status funziona solo con i servizi che sono in /etc/init.d non upstart servizi. @matt-sich sembra aver scoperto la sintassi corretta. Un’altra opzione è quella di utilizzare Gearman o Resque, che permette l’elaborazione in background & deamonization.
    • Penso che questo ha bisogno di più upvotes! Come posso avviare lo script con sudo anche se, come in $(exec sudo /usr/bin/php ... questo chiaramente non funziona, ma il mio script PHP esigenze su diritti, come posso fare?
    • si desidera che il demone principale per fork() o generare ulteriori istanze di se stesso o di un altro script che viene eseguito come bambini. Io di solito sono il mio demone principale la gestione di più di un bambino quando necessario. Perché PHP non permettere a questi processi di ” parlare,’ si deve essere creativi. Ho avuto successo con le prese, i file e database, per questo scopo, ma le prese sono state le più facili da lavorare. È semplicemente passare una porta per il bambino per la connessione o il bambino connettersi a uno standard configurabili porta e segnalare il PID del padre.
    • Ubuntu si è in movimento all’utilizzo di systemd invece di upstart: zdnet.com/article/after-linux-civil-war-ubuntu-to-adopt-systemd
    • I file di Log per ogni demone in questo percorso: /var/log/upstart/
    • Come faccio a passare un argomento al .conf script? Vorrei che i suoi ricordato da qualche parte, in modo che usi gli stessi parametri quando il demone si riavvia automaticamente. Il mio obiettivo è questo: exec /usr/bin/php -f /path/to/your/script.php SOME_PARAM1 SOME_PARAM2

  3. 49

    Con nuovi systemd è possibile creare un servizio.

    È necessario creare un file o una symlink in /etc/systemd/system/, ad esempio. myphpdaemon.il servizio e inserire contenuti come questo, myphpdaemon sarà il nome del servizio:

    [Unit]
    Description=My PHP Daemon Service
    #May your script needs MySQL or other services to run, eg. MySQL Memcached
    Requires=mysqld.service memcached.service 
    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

    Si sarà in grado di iniziare, avere lo stato, riavviare e interrompere i servizi utilizzando il comando

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

    Script PHP deve avere una sorta di “loop” per continuare l’esecuzione.

    <?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
            }
        }
    }

    Di lavoro esempio:

    [Unit]
    Description=PHP APP Sync Service
    Requires=mysqld.service memcached.service
    After=mysqld.service memcached.service
    
    [Service]
    User=root
    Type=simple
    TimeoutSec=0
    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=mixed
    
    Restart=on-failure
    RestartSec=42s
    
    [Install]
    WantedBy=default.target

    Se il PHP routine deve essere eseguito una volta in un ciclo (come un diggest) si potrebbe essere necessario utilizzare una shell o script bash per essere richiamato in servizio di systemd file invece di PHP direttamente, per esempio:

    #!/usr/bin/env bash
    script_path="/app/services/"
    
    while [ : ]
    do
    #    clear
        php -f "$script_path"${1}".php" fixedparameter ${2}  > /dev/null 2>/dev/null
        sleep 1
    done

    Se si sceglie questa opzione si dovrebbe cambiare il KillMode per mixed per processi, bash(principale) e PHP(bambino) essere ucciso.

    ExecStart=/app/phpservice/runner.sh phpfile parameter  > /dev/null 2>/dev/null
    KillMode=process

    This method also is effective if you're facing a memory leak.

    Nota: Ogni volta che si cambia “myphpdaemon.servizio” si deve
    eseguire `systemctl demone-ricarica”, ma non preoccupatevi, se non lo farà, sarà
    avvisati quando è necessario.

    • Sottovalutato risposta. Hai il mio +1.
    • Impressionante. Vorremmo risposte cuore troppo, perché questo non dovrebbe essere sepolto in questa pagina.
    • Ehi, sto cercando di fare systemctl stop servicename ma il file php mantiene l’output di file .. sto lavorando off di “esempio” file.
    • Forse i tuoi sono con ignorando interruzione utente abilitato nel tuo php.
    • Ehi, grazie per il suggerimento ma .. per il servizio ancora non si ferma. Ho copiato il codice php verbatum, e quando faccio ps -ef | grep php questo è quello che ottengo utente 14020 1 0 13:03 ? 00:00:00 /bin/sh -c /usr/bin/php -f /app/folder/test.php 2>&1 > /app/cartella/log.utente 14021 14020 0 13:03 ? 00:00:00 /usr/bin/php -f /app/folder/test.php L’unico cambiamento che ho fatto per il regolatore pid è ho impostato utente e di gruppo di un certo valore. Ho provato con root prima, ofc, nessuna differenza.
    • Si dovrebbe controllare systemctl status <your_service_name> -l uscita, che vi darà un indizio di quello che accade.
    • utilizzare questa risposta per ubuntu/debian e/o 2018+
    • Per ubuntu, mysqld è mysql, e memcache deve essere installato prima. Inoltre, è più pratico utilizzare un collegamento simbolico a qualcosa come /var/www/demoni/myservice.servizio
    • MySQL e Memcached è stata una dimostrazione di come utilizzare le dipendenze del servizio non è necessario.
    • Im utilizzando mysqli in php, non è necessario il servizio di mysql di riferimento ?
    • Si dovrebbe fare riferimento tutti i servizi che la tua versione di PHP del server dipende, proprio per evitare il fallimento, ma non è necessario.
    • grazie per il vostro aiuto. Come hai potuto mettere questo come autostart?
    • attivare phpdaemon.di servizio
    • Ho diversi problemi a fermare il demone, anche con execStop, php verrà eseguita sempre e non si fermerà, più script verrà eseguito, allo stesso tempo, con il concorso problemi
    • Se l’avvio del servizio sub-script si dovrebbe provare altre configurazioni di KillMode e ExecStop freedesktop.org/software/systemd/man/systemd.kill.html
    • Questo in realtà dovrebbe sostituire accettato di rispondere a vedere come è ora 2019.

  4. 47

    Se è possibile – di fare una copia di Programmazione avanzata in Ambiente UNIX. L’intero capitolo 13 è dedicata al demone di programmazione. Esempi sono in C, ma a tutte le funzioni devi avere il wrapper in PHP (in pratica il pcntl e posix estensioni).

    In poche parole – la scrittura di un demone (questo è possibile solo su *nix based OS-es – Windows utilizza servizi) è simile a questo:

    1. Chiamata umask(0) per evitare problemi di autorizzazione.
    2. fork() e sono il padre di uscita.
    3. Chiamata setsid().
    4. Installazione di elaborazione del segnale di SIGHUP (di solito questo viene ignorato o utilizzati per segnalare il demone per ricaricare la sua configurazione) e SIGTERM (a dire il processo per uscire con grazia).
    5. fork() di nuovo e sono il padre di uscita.
    6. Modificare l’attuale directory di lavoro con chdir().
    7. fclose() stdin, stdout e stderr e non scrivere per loro. Il corrrect modo è quello di reindirizzare i a /dev/null o un file, ma non riuscivo a trovare un modo per farlo in PHP. È possibile quando si avvia il demone per reindirizzare loro di usare la shell (dovrete scoprire voi stessi come fare, non so :).
    8. Fare il vostro lavoro!

    Inoltre, dal momento che si sta utilizzando PHP, attenzione per i riferimenti ciclici, in quanto il PHP garbage collector, prima di PHP 5.3, non ha modo di raccogliere i riferimenti e il processo di perdita di memoria, fino a quando alla fine si blocca.

    • Grazie per le info. Sembra che libslack del demone programma praticamente fa tutto il lavoro di preparazione come hai accennato. Penso che per ora mi bastone con esso fino a quando ho trovato altre buone alternative.
    • Trovato questo post, previsto codice di copia&incolla in un’orribile vecchia applicazione che non riesce a chiudere stdin ecc…. è stato deluso. :p
    • Perché (5) fork() di nuovo?
    • Sì, perché per nuovo?
    • Ha funzionato per me – ottimo lavoro!
    • Per i futuri lettori chiedendo perché a forcella due volte: stackoverflow.com/questions/881388/… — TL;DR: Impedisce zombie.
    • Ho letto alcune risposte al link che hai postato, e direi che una forcella a doppia è anche usato per prevenire il secondo figlio per aprire un terminale TTY. È possibile evitare gli zombie se la forcella una volta causa il primo bambino diventerà un bambino di init e sarà pulito fino al momento della sua esecuzione da init‘s periodico wait chiamate di sistema.

  5. 24

    Ho eseguito un gran numero di PHP demoni.

    Sono d’accordo con te che il PHP non è il migliore (o anche un buon linguaggio per fare questo, ma i demoni condividere il codice con il web-di fronte a componenti in modo che nel complesso è una buona soluzione per noi.

    Usiamo daemontools per questo. È intelligente, pulito e affidabile. Infatti possiamo utilizzare per l’esecuzione di tutti i nostri demoni.

    È possibile controllare questo fuori a http://cr.yp.to/daemontools.html.

    EDIT: UN breve elenco di caratteristiche.

    • Automaticamente avvia il demone al riavvio
    • Riavvia automaticamente dameon in caso di fallimento
    • La registrazione è gestita, tra cui rollover e potatura
    • Interfaccia di gestione: ‘svc’ e ‘svstat’
    • UNIX amichevole (non un plus per tutti forse)
    • Anche installabile dai repository, ad esempio in apt!
  6. 14

    È possibile

    1. Utilizzare nohup come Henrik suggerito.
    2. Utilizzare screen ed eseguire il programma PHP come un processo regolare all’interno che. Questo ti dà più controllo rispetto all’utilizzo di nohup.
    3. Utilizzare un daemoniser come http://supervisord.org/ (è scritto in Python, ma può daemonise qualsiasi programma a riga di comando e dare un telecomando per gestire).
    4. Scrivere il proprio daemonise wrapper come Emil suggerito ma è critico IMO.

    Mi consiglia il metodo più semplice (schermo a mio parere) e poi se vuoi più funzionalità, spostare a metodi più complessi.

    • Potrebbe fornire un simile supervisord config?
  7. 11

    C’è più di un modo per risolvere questo problema.

    Non conosco le specifiche, ma forse c’è un altro modo per attivare il processo PHP. Per esempio, se avete bisogno il codice da eseguire sulla base degli eventi in un database SQL si potrebbe impostare un trigger per eseguire il tuo script. Questo è veramente facile da fare in PostgreSQL: http://www.postgresql.org/docs/current/static/external-pl.html .

    Onestamente penso che la vostra scommessa migliore è quello di creare un Damon processo utilizzando nohup. nohup permette il comando per continuare a eseguire anche dopo che l’utente ha effettuato il login:

    nohup php myscript.php &

    Però c’è un problema molto serio. Come hai detto tu PHP gestore della memoria è completa spazzatura, è stato costruito con il presupposto che uno script è solo l’esecuzione per un paio di secondi e poi esiste. Il tuo script PHP iniziare a utilizzare GIGABYTE di memoria dopo un paio di giorni. È INOLTRE NECESSARIO creare un cron script che viene eseguito ogni 12 o forse 24 ore che uccide e ri-genera script php come questo:

    killall -3 php
    nohup php myscript.php &

    Ma cosa succede se lo script è stato al centro di un lavoro? Anche uccidere -3 è un interrupt, la sua la stessa cosa che fare un ctrl+c sulla CLI. Il tuo script php può prendere questo interrupt e uscire normalmente utilizzando il PHP pcntl biblioteca: http://php.oregonstate.edu/manual/en/function.pcntl-signal.php

    Qui è un esempio:

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

    L’idea dietro il $lock è che lo script PHP in grado di aprire un file con fopen(“file”,”w”);. Solo un processo può avere un blocco di scrittura su un file, in modo da utilizzare questo si può fare in modo che solo una copia del tuo script PHP è in esecuzione.

    Buona Fortuna!

  8. 3

    Recentemente ho avuto bisogno di una soluzione multi-piattaforma (Windows, Mac e Linux) per il problema dell’esecuzione di script PHP come demoni. Ho risolto il problema scrivendo la mia C++ soluzione e facendo binari:

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

    Pieno supporto per Linux (via sysvinit), ma anche servizi di Windows e Mac OSX launchd.

    Se avete solo bisogno di Linux, poi un paio di altre soluzioni presentate qui funziona abbastanza bene e, a seconda del gusto. C’è anche Upstart e systemd in questi giorni, che hanno fallbacks di script sysvinit. Ma la metà del punto di utilizzo di PHP è che è cross-platform in natura, in modo che il codice scritto in linguaggio ha una buona possibilità di lavorare ovunque come-è. Carenze di iniziare a mostrare quando alcuni nativo esterno a livello di sistema operativo aspetti inserire l’immagine come servizi di sistema, ma si otterrà il problema con la maggior parte dei linguaggi di scripting.

    Tentativo di catturare segnali come qualcuno qui proposta in PHP userland non è una buona idea. Leggi la documentazione pcntl_signal() con attenzione e si impara rapidamente che PHP gestisce segnali, alcuni piuttosto sgradevole metodi (in particolare ‘zecche’) che masticano un po ‘ di cicli di qualcosa di raramente visto da processi (cioè i segnali). Gestione del segnale in PHP è anche solo di poco disponibile su piattaforme POSIX, e il supporto è diverso in base alla versione di PHP. Inizialmente sembra una soluzione decente, ma cade abbastanza a corto di essere veramente utile.

    PHP è stato anche sempre meglio di problemi di perdita di memoria, come il tempo progredisce. È ancora necessario fare attenzione (DOM parser XML tende a fuoriuscire ancora), ma mi capita raramente di vedere i processi di runaway in questi giorni e il PHP bug tracker è abbastanza tranquilla, a confronto con i giorni di un tempo.

  9. 1

    Come altri hanno già detto, l’esecuzione di PHP come un demone è abbastanza semplice e può essere fatto utilizzando una singola riga di comando. Ma il vero problema è mantenere in esecuzione e la gestione di esso. Ho avuto lo stesso problema qualche tempo fa e anche se ci sono un sacco di soluzioni già disponibili, la maggior parte di loro hanno un sacco di dipendenze o sono difficili da usare e non adatta per la base usi. Ho scritto uno script di shell in grado di gestire un qualsiasi processo/applicazione PHP script cli. Può essere impostato come un cronjob per avviare l’applicazione che contiene l’applicazione e la gestione. Se viene eseguita di nuovo, per esempio, tramite la stessa cronjob, è controllare se l’applicazione è in esecuzione o non, se è così, allora semplicemente esce e lascia la sua precedente istanza di continuare a gestire l’applicazione.

    Ho caricato su github, sentitevi liberi di usarlo : https://github.com/sinasalek/EasyDeamonizer

    EasyDeamonizer

    Semplicemente veglia sulla vostra applicazione (start, restart, log, monitor, ecc). uno script generico per assicurarsi che il vostro appliation rimane in esecuzione correttamente. Intenzionalmente si utilizza il nome del processo instread di pid/file di lock per evitare che tutti i suoi effetti collaterali e mantenere lo script semplice e stirghforward possibile, in modo che funziona sempre, anche quando EasyDaemonizer stesso è riavviato.
    Caratteristiche

    • Avvia l’applicazione e, facoltativamente, un ritardo su misura per ogni start
    • Assicura che solo una è in esecuzione l’istanza
    • Controlla l’utilizzo della CPU e riavvia l’app automaticamente quando raggiunge la soglia definita
    • Impostazione EasyDeamonizer per eseguire tramite cron per eseguire di nuovo se è interrotta per qualsiasi motivo
    • Registra la sua attività
  10. 1

    Estendere Emil Ivaov risposta, È possibile effettuare le seguenti operazioni per chiudere STDIN, STDOUT E STDERROR in php

    if (!fclose(STDIN)) {
        exit("Could not close STDIN");
    }
    
    if (!fclose(STDOUT)) {
        exit("Could not close STDOUT");
    }
    
    if (!fclose(STDERR)) {
        exit("Could not close STDERR");
    }
    
    $STDIN = fopen('/dev/null', 'r');
    $STDOUT = fopen('/dev/null', 'w');
    $STDERR = fopen('/var/log/our_error.log', 'wb');

    Fondamentalmente si chiude flussi standard in modo che PHP non ha posto per scrivere. I seguenti fopen chiamate standard IO per /dev/null.

    Ho letto questo libro di Rob Aley – PHP oltre il web

Lascia un commento