Вопрос

У меня есть PHP-скрипт, который должен вызывать скрипт оболочки, но не заботится о выводе. Сценарий оболочки выполняет несколько вызовов SOAP и выполняется медленно, поэтому я не хочу замедлять запрос PHP, пока он ожидает ответа. Фактически, PHP-запрос должен быть в состоянии завершиться без завершения процесса оболочки.

Я просмотрел различные функции exec () , shell_exec () , pcntl_fork () и т. д., но ни одну из кажется, они предлагают именно то, что я хочу. (Или, если они это сделают, мне не ясно, как.) Есть предложения?

Это было полезно?

Решение

Если он "не заботится о выводе", нельзя ли вызвать exec для скрипта с помощью & amp; для создания фона процесса?

РЕДАКТИРОВАТЬ - учитывая, что @ AdamTheHut прокомментировал этот пост, вы можете добавить его в вызов exec :

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

Это перенаправит stdio (сначала > ) и stderr ( 2 > ) в / dev / null и работать в фоновом режиме.

Есть и другие способы сделать то же самое, но это проще всего прочитать.

<Ч>

Альтернатива вышеупомянутому двойному перенаправлению:

" &> /dev/null &"

Другие советы

Я использовал для этого at , поскольку он действительно запускает независимый процесс.

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

Для всех пользователей Windows: я нашел хороший способ запустить асинхронный PHP-скрипт (на самом деле он работает практически со всем).

Он основан на командах popen () и pclose (). И хорошо работает как в Windows, так и в Unix.

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

Оригинальный код от: http://php.net/manual/en/function.exec.php # 86329

В Linux вы можете делать следующее:

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

Это выполнит команду в командной строке, а затем просто вернет PID, который вы можете проверить на наличие > 0, чтобы убедиться, что это сработало.

Этот вопрос похож: Есть ли в PHP многопоточность?

php-execute-a-background-process предлагает несколько полезных советов , Я думаю, что мой довольно хорошо, но я предвзятый :)

В Linux вы можете запустить процесс в новом независимом потоке, добавив амперсанд в конце команды

mycommand -someparam somevalue &

В Windows вы можете использовать " start " Команда DOS

start mycommand -someparam somevalue

правильный способ (!) сделать это -

<Ол> <Литий> вилка () <Литий> setsid () <Литий> execve ()

fork-вилки, setsid указывает текущему процессу стать ведущим (без родительского элемента), execve сообщает вызывающему процессу о необходимости замены вызываемым. так что родитель может выйти, не влияя на ребенка.

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

правильный способ (!) сделать это -

<Ол> <Литий> вилка () <Литий> setsid () <Литий> execve ()

fork-вилки, setsid указывает текущему процессу стать ведущим (без родительского элемента), execve сообщает вызывающему процессу о необходимости замены вызываемым. так что родитель может выйти, не влияя на ребенка.

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

Я использовал это ...

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

(где PHP_PATH - это константа, определенная как define ('PHP_PATH', '/ opt / bin / php5') или аналогичная)

Он передается в аргументах через командную строку. Чтобы прочитать их в PHP, см. argv .

Единственный способ, который я нашел, который действительно работал для меня, был:

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

Я также нашел компонент процесса Symfony полезным для этого.

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

Посмотрите, как это работает, в /it> repo .

Используйте именованный fifo.

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

Затем, когда вы захотите запустить долгосрочное задание, просто напишите новую строку (неблокирующую в файле триггера.

Пока ваш ввод меньше PIPE_BUF и это одна операция write () , вы можете записывать аргументы в fifo и отображать их как $ REPLY в скрипте.

Вы также можете запустить скрипт PHP как демон или cronjob : #! / usr / bin / php -q

без очереди использования вы можете использовать proc_open () вот так:

    $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);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top