Взаимодействие с консольной программой

Destroyer

Новичок
Взаимодействие с консольной программой

Здравствуйте, у меня такая проблема:
Windows. Есть консольное приложение (не коммандная строка, именно приложение), надо средствами php запустить его, прочитать результат, возможно, послать какие-нибудь команды и закрыть его. Проблема в том, что приложение может долго выводить результат своей работы и php ждет пока программа не сделает всю работу и только потом выдает результат на страницу. Делаю так:

PHP:
$descriptorspec = array(
	0 => array("pipe", "r"),  // stdin
	1 => array("pipe", "w"),  // stdout
	2 => array("pipe", "w")   // stderr
	);
$cmd = 'c:\\prog.exe -params';
$command = '"'.$cmd.'"'; // так надо чтобы параметры правильно передались
$process = proc_open($command, $descriptorspec, $pipes);
stream_set_blocking($pipes[1], FALSE);
if (is_resource($process)) 
{
while($s= fgets($pipes[1], 2)) {
// read from the pipe
// перекодируем из ДОСовской кодировки
$s = iconv("cp866", "cp1251", $s);
echo $s;
fflush($pipes[1]);
}

fclose($pipes[1]);
	
proc_close($process);
}
В итоге результат выдается только после того как программа закончит работу или пока ее принудительно вручную незакрыть.
Висит, ожидая, похоже на $s= fgets($pipes[1], 2).
Как сделать так, чтобы результат выводился в браузер на страничку, например, каждую секунду или еще лучше как только прийдет новая информация от программы?
 

dimagolov

Новичок
ob_start, .... ob_flush, flush

какая связь между вопросом и темой топика?
 

Destroyer

Новичок
Т.е. это все из-за того что под Win? Очень сомневаюсь.
Думаю данный код будет работать и под nix без изменений, так?

Теперь по теме.
сделал так:
PHP:
<?php
ob_start();
...
$descriptorspec = array( 
    0 => array("pipe", "r"),  // stdin 
    1 => array("pipe", "w"),  // stdout 
    2 => array("pipe", "w")   // stderr 
    ); 
$cmd = 'c:\\prog.exe -params'; 
$command = '"'.$cmd.'"'; // так надо чтобы параметры правильно передались 
$process = proc_open($command, $descriptorspec, $pipes); 
stream_set_blocking($pipes[1], FALSE); 
if (is_resource($process))  
{ 
while($s= fgets($pipes[1], 2)) { 
// read from the pipe 
// перекодируем из ДОСовской кодировки 
$s = iconv("cp866", "cp1251", $s); 
echo $s; 
ob_flush();
flush();
fflush($pipes[1]); 
} 

fclose($pipes[1]); 
     
proc_close($process); 
}
?>
Ксожалению результат все тотже - выводит после окончания работы программы или после ее принудительного завершения.
Если можно, поясните, плз, поподробнее.
 

dimagolov

Новичок
если броузер IE, то он хочет не просто данные, а данные минимум определенного размера. если размер меньше, то он не отображает сразу, значит надо выводить какой-то html каммент на нужный размер. размер смотреть поиском.
 

Destroyer

Новичок
Вышеописанный код работает одинаково как на IE, так и на Опере. Посмотрите, может где ошибка или неточность. Советы приветствуются
 

Alexandre

PHPПенсионер
Как сделать так, чтобы результат выводился в браузер на страничку, например, каждую секунду или еще лучше как только прийдет новая информация от программы?
кури ajax

лично я делал так:

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

далее браузер по таймауту таскает скрипт,
которому как параметр передается имя темпового файла
скрипт отдает содержимое темпового файла в браузер...

остается определить маркер отработки программы.
 

Destroyer

Новичок
Дело в том, что на Ajax тоже самое - просто идет ожидание.
По какой-то причине, похоже, стоит вот здесь:
$s= fgets($pipes[1], 2)
И пока программа не будет закрыта, результата нет.
Как бы читать из пайпа сразу как только прийдет информация в него?

-~{}~ 09.06.08 17:35:

Добавлю, всвязи с редактированием сообщения:
хотелось бы получить универсальный скрипт - под win и nix.
А создание темпового файла, в который сливается лог программы - это демон, который в винде и никсах разный.
Остается проблема:
По какой-то причине, похоже, стоит вот здесь:
$s= fgets($pipes[1], 2)
И пока программа не будет закрыта, результата нет.
Как бы читать из пайпа сразу как только прийдет информация в него?
 

Alexandre

PHPПенсионер
Дело в том, что на Ajax тоже самое - просто идет ожидание
если использовать popen - то будет ожидание
если запустить процесс, который запустит твою программу в бэкграунде а сам завершится, то нет.
но такая форма не подойдет, обсуждалась 10 раз: myproga.exe &
 

zaartix

Новичок
proc_open под виндами по-моему работает полукриво, ну всмысле частично. Мне кажется Alexandre правильно предложил, как вариант подстраховки в параметрах программе можно передавать и имя темпового файла
 

Alexandre

PHPПенсионер
в параметрах программе можно передавать и имя темпового файла
имя темпового файла может и генерить программа, которая запускает myprog.exe,
а может генерить его и сам запускающий пхп скрипт - это не принципиально. главное - это имя отдается пхп-скрипту, которое сохраняется в сессию. а браузер уже тягает другой скрипт, который берет из сессии имя файла и смотрит:
либо прогресс расчета чего-либо
либо промежуточный вывод проги
либо любая иная информация, которая должна отдаться через аджакс
 

Destroyer

Новичок
Спасибо за ответы, да, это как один из вариантов, но такой вариант несовсем подходит, т.к. нужна мультиплатформенность - win, nix.
Я так понял в предложенном варианте: получается моя программа-демон (на любом языке) должна запускать ту консольную программу, с которой надо работать. Сам демон должен, получается, завершиться, тогда php пройдет дальше и небудет ожидания. Другой демон должен отлавливать вывод этой консольной программы и складывать все это в лог фаил, из которого уже идет чтение средствами php и вывод на страничку.
Получается громоздко и демоны под nix и win разные - мультиплатформенности нет.
Если я что-то нетак понял, поясните плз.
 

dimagolov

Новичок
Destroyer, консольная прога сама должна результат складывать в файл, получаемый как параметр. пускать ее как процесс будет php скрипт, который начинает процесс, а потом JS на клиенте будет дергать ajax-ом php скрипт чтения лога и при появлении обновлений отображать клиенту.
 

Destroyer

Новичок
Автор оригинала: cDLEON
а свою prog.exe ты тоже на никсах запускать собираешься?
В том то и проблема, что консольная программа (или как тут выразились prog.exe) не моя, логи складывать в фаил не умеет. Она есть под nix и win, так что мультиплатформенность актуальна.
 

Destroyer

Новичок
Спасибо, только там так к ответу и не пришли.

Еще вопрос параллельный: а под win форкинг неработает?

На счет stdout - имеется ввиду что-то типа "...\prog.exe -params > log.txt" Да, вариант, но в моем случае почему-то лог не пишется. Почему не знаю. Да и если бы он работал, то, насколько я понял, он запишется после того, как программа отработает, а мне надо выводить результат на страницу прямо в процессе работы.

Все советы/мысли приветствуются
 

Alexandre

PHPПенсионер
На счет stdout - имеется ввиду что-то типа "...\prog.exe -params > log.txt" Да, вариант, но в моем случае почему-то лог не пишется
а может прога пишет в stderror &
на врядли она пишет сразу на tty....и то это возможно перехватить средствами Ось.
Да и если бы он работал, то, насколько я понял, он запишется после того, как программа отработает
ну это от программы зависит, сам понимаешь... ни кто не знает что за программа и как она работает, за-то все знают одно золотое правило:
систему надо разрабатывать максимально приближенно в той среде, в которой она будет эксплуатироваться. маловероятно, что продавкшен будет винда.
если бы продакшен была бы винда, я бы вообще на пхп разработку не вел, дотнет рулит.

если все-таки выберете никсовую платформу, то запускающую программу-скрипт можно сделать на php(use pcntl)/perl

-~{}~ 10.06.08 01:17:

так что мультиплатформенность актуальна
в чем такая актуальность мультиплатформенности?
 

kode

never knows best
Автор оригинала: Alexandre
а может прога пишет в stderror &
на врядли она пишет сразу на tty....и то это возможно перехватить средствами Ось.ну это от программы зависит, сам понимаешь... ни кто не знает что за программа и как она работает, за-то все знают одно золотое правило:
систему надо разрабатывать максимально приближенно в той среде, в которой она будет эксплуатироваться. маловероятно, что продавкшен будет винда.
если бы продакшен была бы винда, я бы вообще на пхп разработку не вел, дотнет рулит.

если все-таки выберете никсовую платформу, то запускающую программу-скрипт можно сделать на php(use pcntl)/perl

-~{}~ 10.06.08 01:17:

в чем такая актуальность мультиплатформенности?
консоль винды не поддерживает пайпы, те prog.exe > my.log сделать не удастся (те работать не будет)
 
Сверху