PHP Pipe в фоновый процесс

Я пытаюсь использовать popen для запуска php-скрипта в фоновом режиме. Однако мне нужно передать (довольно большой) сериализованный объект.

$cmd = "php background_test.php >log/output.log &";
$fh = popen($cmd, 'w');
fwrite($fh, $data); 
fclose($fh);
//pclose($fh);

Без амперсанда этот код выполняется нормально, но родительский скрипт будет ждать, пока не завершится выполнение дочернего. С амперсандом STDIN не получает данных.

Любые идеи?


person refeniz    schedule 28.09.2011    source источник


Ответы (3)


Насколько я знаю, в php нет способа отправить процесс в фоновом режиме и продолжать кормить его STDIN (но, возможно, я ошибаюсь). Здесь у вас есть два других варианта:

  1. Рефакторинг вашего background_test.php, чтобы получить его ввод из командной строки и преобразовать вашу командную строку в php background_test.php arg1 arg2 ... >log/output.log &
  2. Если ваш ввод довольно длинный, запишите его во временный файл, а затем передайте сценарий background_test.php с этим файлом, как показано в следующем коде.

Пример для пункта 2:

<?
$tmp_file = tempnam();
file_put_content($tmp_file, $data);
$cmd = "php background_test.php < $tmp_name > log/output.log &";
exec($cmd);
person Fabio    schedule 28.09.2011

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

Что-то вроде этого

// Fork a child process
$pid = pcntl_fork();

// Unable to fork
if ($pid == -1) {
    die('error');
}

// We are the parent
elseif ($pid) {

   // do nothing 
}

// We are the child
else {

    $cmd = "php background_test.php >log/output.log";
    $fh = popen($cmd, 'w');
    fwrite($fh, $data); 
    fclose($fh);
    exit();
}


// parent will continue here
// child will exit above

Подробнее об этом читайте здесь: https://sites.google.com/a/van-steenbeek.net/archive/php_pcntl_fork

Также проверьте функцию pcntl_waitpid() (зомби исчезнут) в документации по php.

person Alexei Tenitski    schedule 28.09.2011
comment
Будьте очень осторожны с зомби-процессами, если вы собираетесь разветвлять свои скрипты. Альтернативой, которую вы могли бы рассмотреть, является диспетчер очередей, такой как Gearman. - person Joshua Kaiser; 29.09.2011

Заставьте фоновые процессы прослушивать файл сокета. Затем откройте файл сокета из PHP и отправьте туда свои сериализованные данные. Когда ваш фоновый демон получает соединение через сокет, сделайте его разветвленным, прочитайте данные, а затем обработайте.

Вам нужно будет немного почитать, но я думаю, что это лучший способ добиться этого. Под сокетом я подразумеваю файл сокета unix, но вы также можете использовать его по сети.

http://gearman.org/ также является хорошей альтернативой, как упоминал @Joshua

person romaninsh    schedule 28.09.2011