PHP-канал в фоновый процесс

#php #process #background #stdin #popen

#php #процесс #фон #stdin #popen

Вопрос:

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

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

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

Есть идеи?

Ответ №1:

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

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

 // 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() (zombies be gone) в документации php.

Комментарии:

1. Будьте очень осторожны с процессами-зомби, если вы собираетесь разветвлять свои скрипты. Альтернативой, которую вы можете рассмотреть, является диспетчер очередей, такой как Gearman.

Ответ №2:

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

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

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

 <?
$tmp_file = tempnam();
file_put_content($tmp_file, $data);
$cmd = "php background_test.php < $tmp_name > log/output.log amp;";
exec($cmd);
  

Ответ №3:

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

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

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