2009-08-25 2 views
2

Я выполняю скрипт TCL из PHP с помощью proc_open.Как сделать блокировку и читать до конца?

  1. Я первый открыть TCL оболочку 2) Отправить команду, используя FWRITE 3) Что мне нужно Fread ждать/блока, пока команда посланного FWRITE не является полной и получить все содержимое .the команды может потребоваться некоторое время для завершения. (Я могу читать всего 2 строки, а затем он переходит к следующему циклу)

Может ли кто-нибудь меня вести.

Настоящий код

<?php 

$app = 'tclsh84'; 
$descriptorspec = array(
0 => array("pipe","r"), 
1 => array("pipe","w"), 
2 => array("file","C:/wamp/www/tcl/bin/g.txt","w") 
) ; 
$process = proc_open($app, $descriptorspec, $pipes); 
if (is_resource($process)) 
{ 


for($i=0;$i<4;$i++) 
{ 

fwrite($pipes[0], 'source c:/wamp/www/tcl/bin/test.tcl'."\n"); 
$content= fread($pipes[1],8192) 
print "$content"; 

}  
    fclose($pipes[0]);  

    fclose($pipes[1]); 


    proc_close($process); 
} 
?> 
+0

Вы уверены, что сценарий генерирует больше выходных данных, чем вы получаете? Документация php для fread предполагает, что она не вернется меньше указанной суммы, если только она не встречает EOF (при чтении из потока пользовательского пространства). – Inshallah

+0

Fread не останавливается для завершения команды TCL. Он переходит к следующему циклу. – Vidya

ответ

1

Я думаю о комбинации

  • stream_select и/или feof()
  • FREAD() и конкатенации частичных результатов ($ результат. = Fread())
  • и, возможно, proc_get_status() для определения конца процесса

Вы хотите дождаться, пока приложение tcl не напишет что-то в его stdout для определенного amo (предполагая, что это означает конец последней команды), а затем отправить следующую команду/строку в свой stdin?

редактировать:
Кажется, как вы можете отправить все команды на TCL оболочки сразу, и они обрабатываются по одному, то есть оболочка считывает следующий входной строки/команды, когда это делается с предыдущим. Я проверил это со сценарием.

incr a 1 
after 1000 
puts [concat [clock seconds] $a] 

и

<?php 
$app = 'c:/programme/tcl/bin/tclsh85.exe'; 
$descriptorspec = array(
    0 => array("pipe","r"), 
    1 => array("pipe","w"), 
    2 => array("file","C:/god.txt","w") 
) ; 
$process = proc_open($app, $descriptorspec, $pipes); 
if (is_resource($process)) { 
    fwrite($pipes[0], "set a 1\n"); 
    for($i=0;$i<4;$i++) { 
    fwrite($pipes[0], "source c:/helloworld.tcl\n"); 
    } 
    // when all scripts are done the shell shall exit 
    fwrite($pipes[0], "exit\n"); 
    fclose($pipes[0]); 

    do { 
    $read=array($pipes[1]); $write=array(); $except=array($pipes[1]); 
    // wait up to 1 second for new output of the tcl process 
    $ready = stream_select($read, $write, $except, 1, 0); 
    if ($ready && $read /* is not empty */) { 
     // get the partial output 
     $r = fread($pipes[1], 2048); 
     echo $r; 
    } 
    // is the process still running? 
    $status = proc_get_status($process); 
    } while($status['running']); 
    fclose($pipes[1]); 
    proc_close($process); 
} 
?> 

Вы, вероятно, хотите добавить еще несколько обработки ошибок. Например. если stream_select() возвращает x раз с таймаутом, что-то могло бы пойти не так.

Редактировать2:
Позвольте оболочке напечатать то, что вы можете сканировать для каждого скрипта.

<?php 
// something that's not in the "normal" output of the scripts 
$id = 'done'. time(); 

$app = 'c:/programme/tcl/bin/tclsh85.exe'; 
$descriptorspec = array(
    0 => array("pipe","r"), 
    1 => array("pipe","w"), 
    2 => array("file","C:/god.txt","w") 
) ; 
$process = proc_open($app, $descriptorspec, $pipes); 
if (is_resource($process)) { 
    fwrite($pipes[0], "set a 1\n"); 
    for($i=0;$i<4;$i++) { 
    $output = ''; 
    $continue = true; 
    $cTimeout = 0; 
    echo 'loop ', $i, "\n"; 
    fwrite($pipes[0], "source c:/helloworld.tcl\n"); 
    fwrite($pipes[0], "puts $id\n"); 
    echo "waiting for idle\n"; 
    do { 
     $read=array($pipes[1]); 
     $write=array(); 
     $except=array($pipes[1]); 
     $ready = stream_select($read, $write, $except, 1, 0); 
     if ($ready && $read) { 
     $output .= fread($pipes[1], 2048); 
     // if the delimiter id shows up in $output 
     if (false!==strpos($output, $id)) { 
      // the script is done 
      $continue = false; 
     } 
     } 
    } while($continue); 
    echo 'loop ', $i, " finished\n"; 
    } 
    proc_close($process); 
} 
?> 
+0

Я посылаю команду (имя proc для выполнения). Я хочу подождать, пока это не завершится. Есть ли способ подождать? Мне не нужно читать данные, которые он отправляет. Мне просто нужно подождать, пока он не завершится. – Vidya

+0

Точно, когда вам нужно подождать? Вы отправляете строку «источник xyz» четыре раза в stdin процесса. Вам нужно подождать, пока каждый скрипт будет обработан, прежде чем вы сможете отправить другой «источник ...»? Или вы (только) должны ждать, пока все сценарии (полностью) не будут выполнены? – VolkerK

+0

Мне нужно дождаться завершения каждого вызова скрипта (proc in tcl). Надеюсь, ты понял. В моем случае я должен ждать 4 раза. – Vidya

0

Try:

$content = ''; 

while(!feof($pipes[1])) 
{ 
    $content .= fread($pipes[1],8192); 
} 

ли, что ждать?

+0

Нет, это не ждет. Ok Есть ли способ подождать, пока команда fwrite не будет завершена? – Vidya

Смежные вопросы