Frage

Ich habe ein PHP-Skript bekam, die ein Shell-Skript aufrufen muss aber überhaupt über die Ausgabe kümmert sich nicht darum. Der Shell-Skript enthält eine Reihe von SOAP-Calls und ist langsam zu vollenden, so will ich nicht die PHP-Anfrage verlangsamen, während er auf eine Antwort wartet. In der Tat sollte die PHP-Anfrage ohne Beenden des Shell-Prozesses zum Beenden der Lage sein.

Ich habe in den verschiedenen exec() sah, shell_exec(), pcntl_fork() usw. Funktionen, aber keiner von ihnen scheinen genau zu bieten, was ich will. (Oder, wenn sie es tun, es ist mir nicht klar, wie.) Irgendwelche Vorschläge?

War es hilfreich?

Lösung

Wenn es „schert sich nicht um den Ausgang“, konnte nicht die exec, um das Skript mit dem & in den Hintergrund aufgerufen werden der Prozess?

Bearbeiten - enthält, was @ AdamTheHut zu diesem Beitrag kommentiert, können Sie fügen Sie diese ein Aufruf an exec:

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

Das wird sowohl stdio (erster >) und stderr (2>) umleiten im Hintergrund /dev/null und ausgeführt werden.

Es gibt auch andere Möglichkeiten, um das Gleiche zu tun, aber das ist am einfachsten zu lesen.


Eine Alternative zu der obigen Doppel Umleitung:

" &> /dev/null &"

Andere Tipps

Ich habe für diese, wie es wirklich ist ein unabhängiger Prozess zu starten.

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

Für all Windows-Benutzer: Ich fand eine gute Möglichkeit, um einen asynchronen PHP-Skript auszuführen (tatsächlich funktioniert es mit fast allem)

.

Es basiert auf popen () und pclose (Befehle). Und gut funktioniert sowohl unter Windows und Unix.

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

Original-Code aus: http://php.net/manual/en/function.exec.php # 86329

Unter Linux Sie tun können, die folgenden:

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

Damit wird der Befehl an der Eingabe prompty ausführen und dann nur die PID zurückkehren, die Sie überprüfen können, für> 0, um sicherzustellen, es hat funktioniert.

Diese Frage ist ähnlich: Ist PHP Threading

php-Execute-a-Hintergrund-Prozess einige gute Vorschläge hat . Ich glaube, ich ist ziemlich gut, aber ich bin voreingenommen:)

Unter Linux können Sie einen Prozess in einem neuen unabhängigen Thread starten durch eine kaufmännische Und am Ende des Befehls Anfügen

mycommand -someparam somevalue &

Unter Windows können Sie den "Start" DOS-Befehl

start mycommand -someparam somevalue

der richtige Weg (!) Zu tun, es ist zu

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

Gabel Gabeln, setsid dem aktuellen Prozess zu sagen, einen Master ein (kein Elternteil) zu werden, execve dem aufrufenden Prozess zu sagen, durch die gerufene ersetzt werden. so dass die Eltern ohne Auswirkungen auf das Kind verlassen können.

 $pid=pcntl_fork();
 if($pid==0)
 {
   posix_setsid();
   pcntl_exec($cmd,$args,$_ENV);
   // child becomes the standalone detached process
 }

 // parent's stuff
 exit();

Ich habe diese ...

/** 
 * 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 &");
}

(wobei PHP_PATH eine const definiert wie define('PHP_PATH', '/opt/bin/php5') oder ähnliches)

Es geht in Argumenten über die Kommandozeile. Um sich in PHP zu lesen, finden Sie unter argv .

Der einzige Weg, dass ich das wirklich für mich gearbeitet wurde gefunden:

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

Ich fand auch Symfony Prozesskomponente nützlich hierfür.

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

Sehen Sie, wie es funktioniert in der GitHub Repo .

Verwenden Sie einen Namen Fifo.

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

Dann, wann immer Sie wollen die lange laufende Aufgabe starten, schreiben Sie einfach eine neue Zeile (nicht blockierend auf die Trigger-Datei.

Solange Ihre Eingabe kleiner als PIPE_BUF ist, und es ist eine einzige write() Operation können Sie Argumente in die Fifo schreiben und sie als $REPLY im Skript angezeigt.

Sie können auch den PHP-Skript als run-Daemon oder Cronjob : #!/usr/bin/php -q

ohne Verwendung Warteschlange, können Sie die proc_open() wie diese :

    $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);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top