2011-10-09 175 views
4

當我從PHP運行exec像這樣:在命令仍在運行時從php exec()中獲取結果?

$result = exec('command'); 

從這個結果將保存在$result。但在我目前的情況下,我的命令可能需要幾分鐘時間並在運行時輸出結果。有沒有辦法在運行時獲得輸出?我知道passthru方法會輸出結果作爲瀏覽器,但我實際上直接需要它。

+0

使用CGI而不是PHP,可能嗎? –

回答

5

你應該看看proc_open

使輸出流非阻塞(與stream_set_blocking)後,你可以從它,只要你想,而無需你的PHP代碼阻止讀取。

CNC中 如果使用

$result = exec('command > /path/to/file &'); 

它會在後臺運行,你可以讀取/路徑輸出/到/文件

3

指定第二個參數

exec('command', $result); 

如果輸出參數存在,則該指定的數組將 填充來自指令輸出的每一行。尾數 空格(例如\ n)未包含在此數組中。請注意,如果 數組已包含某些元素,則exec()將追加到數組的末尾 。如果您不希望函數追加元素, 在將數組傳遞給exec()之前會調用unset()方法。

+0

謝謝,但從我的理解,這仍然需要exec完成之前,我可以得到輸出。我特別希望在命令運行時獲得輸出,以便我可以更新進度條。 – Kyle

+0

@Zenox:啊。在這種情況下,這是不可能的。 PHP不是異步 – genesis

+0

好的。謝謝(你的)信息! – Kyle

4

也許不是最好的方式做到這一點(但爲我工作):

<?php 

$cmd = "ping 127.0.0.1 -c 5"; //example command 

$descriptorspec = array(
    0 => array("pipe", "r"), 
    1 => array("pipe", "w"), 
    2 => array("pipe", "a") 
); 

$pipes = array(); 

$process = proc_open($cmd, $descriptorspec, $pipes, null, null); 

echo "Start process:\n"; 

$str = ""; 

if(is_resource($process)) { 
    do { 
     $curStr = fgets($pipes[1]); //will wait for a end of line 
     echo $curStr; 
     $str .= $curStr; 

     $arr = proc_get_status($process); 

    }while($arr['running']); 
}else{ 
    echo "Unable to start process\n"; 
} 

fclose($pipes[0]); 
fclose($pipes[1]); 
fclose($pipes[2]); 
proc_close($process); 

echo "\n\n\nDone\n"; 

echo "Result is:\n----\n".$str."\n----\n"; 

?> 
0

對於任何人,它可以幫助,我用埃迪的答案,並修改了它爲我的目的(輸出一個MySQL轉儲文件而不會淹沒服務器的RAM)

$dumpCommand = "mysqldump --skip-lock-tables -u $dbuser -p$dbpasswd $dbname"; 
$dumpFileName = 'backup_'.$dbname.'-'.date('Ymd-Hi').'.sql'; 

$descriptorSpec = array(
    0 => array("pipe", "r"), 
    1 => array("pipe", "w"), 
    2 => array("pipe", "a") 
); 

$pipes = array(); 

$process = proc_open($dumpCommand, $descriptorSpec, $pipes, null, null); 

if(!is_resource($process)) { 
    die('Unable to start process'); 
} 

header('Content-Type: application/octet-stream'); 
header('Content-Disposition: attachment; filename="'.$dumpFileName.'"'); 

do { 
    echo fgets($pipes[1]); // Will wait for EOL 
    $arrStatus = proc_get_status($process); 
} while($arrStatus['running']); 

fclose($pipes[0]); 
fclose($pipes[1]); 
fclose($pipes[2]); 
proc_close($process);