На самом деле у меня есть proc_open
функция, которая выполнит команду и передаст ей свои подкоманды. Здесь есть проблема, которая возникает иногда, а не обычно.
проблема
Когда я хочу получить вывод процесса, нет ответа от конечного сервера, и скрипт будет ждать ответа до …..
Вопрос
Я хочу сказать, что ждать ответа в течение 20 секунд, и если вы не получили никакого ответа. возврат из функции. Это важно, что я не хочу останавливать выполнение скрипта, а просто возвращаюсь из функции.
Должен ли я использовать многопоточные библиотеки в качестве POSIX?
Есть ли способ реализовать эту идею?
Любая идея будет оценена. заранее спасибо
Пример кода
<?PHP
set_time_limit(0);
.....
public function test()
{
foreach ($this->commands as $cmd)
{
fwrite($pipes[0], "$cmd \n");
//Sometimes PHP stuck on the following line
//Wait for almost 20 sec if respond did not came return
$read = fread($pipes[1], 2096) . "\n";
}
}
Вы не сказали, на какой ОС это работает, хотя упоминали POSIX. Ни какой SAPI. В совокупности они оказывают большое влияние на ваши варианты.
Кроме того, вы не сказали, что это за процесс, который вы начали, и как его следует обрабатывать, когда он истекает. Закрытие потоков stdio может привести к сбою процесса. Если вы хотите отправить сигнал, вам нужно знать pid (IIRC недоступен из proc_open ()).
Непосредственная проблема, с которой вы столкнулись, заключается в том, что поток по умолчанию блокирует чтение, поэтому простое его установление без блокировки позволяет преодолеть первое препятствие:
set_stream_blocking($pipes[1],false);
...
fwrite($pipes[0], "$cmd \n");
$ttl=time()+20;
while(''==$read && time()<$ttl) {
$read=fread($pipes[1],2096);
if (!$read) sleep(1);
}
if (!$read) echo " timeout";
(Кстати, это, вероятно, не будет работать на mswindows)
использование stream_set_timeout (но после fwrite, если тот же поток):
fwrite($pipes[0], "$cmd \n");
stream_set_timeout($pipes[1], 20);
$read = fread($pipes[1], 2096) . "\n";
редактировать:
В некоторых особых случаях вы должны использовать stream_select () вместо этого, делать с ошибками в PHP.
$r = [$pipes[0]];
$w = $e = null;
if( stream_select($r, $w, $e, 20) !== false )
foreach($r as $s)
$read = fread($s,2096);
Надеюсь, это поможет?