2017-02-27 91 views
1

我試圖從php執行一個bash腳本並實時獲取其輸出。從PHP執行的Bash腳本實時輸出

我申請的答案找到here

但是他們不是爲我工作。

當我調用這個方式.SH腳本,它工作正常:

<?php 
    $output = shell_exec("./test.sh"); 
    echo "<pre>$output</pre>"; 
?> 

但是,這樣做的時候:

<?php 
    echo '<pre>'; 
    passthru(./test.sh); 
    echo '</pre>'; 
?> 

或:

<?php 
    while (@ ob_end_flush()); // end all output buffers if any 
    $proc = popen(./test.sh, 'r'); 
    echo '<pre>'; 
    while (!feof($proc)) 
    { 
    echo fread($proc, 4096); 
    @ flush(); 
    } 
    echo '</pre>'; 
?> 

我沒有在我的瀏覽器中輸出。

我也試着撥打變量,而不是腳本在兩種情況下,我的意思是:

<?php 
    $output = shell_exec("./test.sh"); 
    echo '<pre>'; 
    passthru($output); 
    echo '</pre>'; 
?> 

這是我的test.sh腳本:

#!/bin/bash 
whoami 
sleep 3 
dmesg 
+0

應該引用文件名 - passthru(「./test.sh」);' - 即使這樣,它也不起作用? – ewcz

+0

@ewcz它可以和我的test.sh例子一起工作,謝謝。然而,它不適用於我想要使用的實際腳本。至少這是一個開始,我可以從現在開始進一步分析。如果你寫你的評論作爲答案,我會驗證它。 –

回答

2

使用以下命令:

<?php 
ob_implicit_flush(true); 
ob_end_flush(); 

$cmd = "bash /path/to/test.sh"; 

$descriptorspec = array(
    0 => array("pipe", "r"), // stdin is a pipe that the child will read from 
    1 => array("pipe", "w"), // stdout is a pipe that the child will write to 
    2 => array("pipe", "w") // stderr is a pipe that the child will write to 
); 


$process = proc_open($cmd, $descriptorspec, $pipes, realpath('./'), array()); 

if (is_resource($process)) { 

    while ($s = fgets($pipes[1])) { 
     print $s; 

    } 
} 

?> 

將test.sh更改爲:

#!/bin/bash 
whoami 
sleep 3 
ls/

說明:

dmesg的需要權限。您需要爲此授予Web服務器的用戶權限。在我的情況下,apache2正在通過www-data用戶運行。

ob_implicit_flush(true):打開隱式刷新。在每次輸出調用後,隱式刷新都將導致刷新操作,因此不再需要對flush()的明確調用。

ob_end_flush():關閉輸出緩衝,所以我們立即看到結果。

+0

'stream_select()'+'stream_get_contents()'更適合這項工作,因爲'fgets()'在換行符(這很可能發生)時停止讀取。檢查我以前的答案在這裏:http://stackoverflow.com/a/37526704/1957951 –