Domanda

Ho uno script PHP che deve invocare uno script di shell ma non si preoccupa affatto dell'output. Lo script della shell effettua una serie di chiamate SOAP ed è lento da completare, quindi non voglio rallentare la richiesta PHP mentre attende una risposta. In effetti, la richiesta PHP dovrebbe essere in grado di uscire senza terminare il processo di shell.

Ho esaminato le varie funzioni exec () , shell_exec () , pcntl_fork () , ecc., ma nessuna delle sembrano offrire esattamente quello che voglio. (O, se lo fanno, non mi è chiaro come.) Qualche suggerimento?

È stato utile?

Soluzione

Se " non si preoccupa dell'output " ;, non è possibile richiamare il exec con lo script con & amp; per avviare il processo?

MODIFICA - incorporando ciò che @ AdamTheHut ha commentato questo post, puoi aggiungerlo a una chiamata a exec :

" > /dev/null 2>/dev/null &"

Questo reindirizzerà stdio (prima > ) e stderr ( 2 > ) su / dev / null ed esegui in background.

Esistono altri modi per fare la stessa cosa, ma questa è la più semplice da leggere.


Un'alternativa al doppio reindirizzamento sopra:

" &> /dev/null &"

Altri suggerimenti

Ho usato in per questo, dato che sta davvero avviando un processo indipendente.

<?php
    `echo "the command"|at now`;
?>

Per tutti gli utenti Windows: ho trovato un buon modo per eseguire uno script PHP asincrono (in realtà funziona con quasi tutto).

È basato sui comandi popen () e pclose (). E funziona bene su Windows e Unix.

function execInBackground($cmd) {
    if (substr(php_uname(), 0, 7) == "Windows"){
        pclose(popen("start /B ". $cmd, "r")); 
    }
    else {
        exec($cmd . " > /dev/null &");  
    }
} 

Codice originale da: http://php.net/manual/en/function.exec.php # 86329

Su Linux puoi fare quanto segue:

$cmd = 'nohup nice -n 10 php -f php/file.php > log/file.log & printf "%u" $!';
$pid = shell_exec($cmd);

Questo eseguirà il comando al prompt dei comandi e quindi restituirà il PID, che puoi controllare per > 0 per assicurarsi che abbia funzionato.

Questa domanda è simile: PHP ha threading?

php-execute-a-background-process ha alcuni buoni suggerimenti . Penso che il mio sia abbastanza buono, ma sono di parte :)

In Linux, puoi avviare un processo in un nuovo thread indipendente aggiungendo una e commerciale alla fine del comando

mycommand -someparam somevalue &

In Windows, puoi utilizzare " start " Comando DOS

start mycommand -someparam somevalue

il modo giusto (!) per farlo è

  1. fork ()
  2. setsid ()
  3. execve ()

fork fork, setsid indica al processo corrente di diventare master (no parent), execve dice al processo chiamante di essere sostituito da quello chiamato. in modo che il genitore possa smettere senza influire sul figlio.

 $pid=pcntl_fork();
 if($pid==0)
 {
   posix_setsid();
   pcntl_exec($cmd,$args,

il modo giusto (!) per farlo è

  1. fork ()
  2. setsid ()
  3. execve ()

fork fork, setsid indica al processo corrente di diventare master (no parent), execve dice al processo chiamante di essere sostituito da quello chiamato. in modo che il genitore possa smettere senza influire sul figlio.

<*>ENV); // child becomes the standalone detached process } // parent's stuff exit();

L'ho usato ...

/** 
 * Asynchronously execute/include a PHP file. Does not record the output of the file anywhere.  
 * Relies on the PHP_PATH config constant.
 *
 * @param string $filename  file to execute
 * @param string $options   (optional) arguments to pass to file via the command line
 */ 
function asyncInclude($filename, $options = '') {
    exec(PHP_PATH . " -f {$filename} {$options} >> /dev/null &");
}

(dove PHP_PATH è una const definita come define ('PHP_PATH', '/ opt / bin / php5') o simile)

Passa in argomenti tramite la riga di comando. Per leggerli in PHP, vedi argv .

L'unico modo in cui ho scoperto che ha funzionato davvero per me è stato:

shell_exec('./myscript.php | at now & disown')

Ho anche trovato utile Componente del processo Symfony per questo.

use Symfony\Component\Process\Process;

$process = new Process('ls -lsa');
// ... run process in background
$process->start();

// ... do other things

// ... if you need to wait
$process->wait();

// ... do things after the process has finished

Guarda come funziona nel suo GitHub repo .

Usa un quindicesimo nome.

#!/bin/sh
mkfifo trigger
while true; do
    read < trigger
    long_running_task
done

Quindi, ogni volta che si desidera avviare l'attività con esecuzione prolungata, è sufficiente scrivere una nuova riga (senza bloccare il file trigger.

Fintanto che il tuo input è più piccolo di PIPE_BUF ed è una singola operazione write () , puoi scrivere argomenti nel Fifo e mostrarli come $ REPLY nello script.

Puoi anche eseguire lo script PHP come demone o cronjob : #! / usr / bin / php -q

senza utilizzare la coda, è possibile utilizzare proc_open () in questo modo:

    $descriptorspec = array(
        0 => array("pipe", "r"),
        1 => array("pipe", "w"),
        2 => array("pipe", "w")    //here curaengine log all the info into stderror
    );
    $command = 'ping stackoverflow.com';
    $process = proc_open($command, $descriptorspec, $pipes);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top