根據網路上各式各樣的文章和最近的經驗,我觀察到您不能依賴 proc_close 傳回子程序準確的傳回碼。傳回碼也取決於您是否從 stdout/stderr 管道讀取,如我的範例所示。我透過將結束碼寫入額外的檔案描述器來解決這個問題。
<?
$descriptorspec = array(
0 => array('pipe', 'r'), // stdin 是一個管道,子程序將從中讀取
1 => array('pipe', 'w'), // stdout 是一個管道,子程序將寫入其中
2 => array('pipe', 'w'), // stderr 是一個管道,子程序將寫入其中
);
$proc = @proc_open("/bin/ls -l /etc/passwd", $descriptorspec, $pipes);
fclose($pipes[0]);
$output = array();
while (!feof($pipes[1])) array_push($output, rtrim(fgets($pipes[1],1024),"\n"));
fclose($pipes[1]);
while (!feof($pipes[2])) array_push($output, rtrim(fgets($pipes[2],1024),"\n"));
fclose($pipes[2]);
$exit=proc_close($proc);
print_r($output);
echo "exitcode $exit\n\n";
$descriptorspec = array(
0 => array('pipe', 'r'), // stdin 是一個管道,子程序將從中讀取
1 => array('pipe', 'w'), // stdout 是一個管道,子程序將寫入其中
2 => array('pipe', 'w'), // stderr 是一個管道,子程序將寫入其中
);
$proc = @proc_open("/bin/ls -l /etc/passwd", $descriptorspec, $pipes);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
$exit=proc_close($proc);
echo "exitcode $exit\n\n";
$descriptorspec = array(
0 => array('pipe', 'r'), // stdin 是一個管道,子程序將從中讀取
1 => array('pipe', 'w'), // stdout 是一個管道,子程序將寫入其中
2 => array('pipe', 'w'), // stderr 是一個管道,子程序將寫入其中
3 => array('pipe', 'w'), // stderr 是一個管道,子程序將寫入其中
);
$proc = @proc_open("/bin/ls -l /etc/passwd;echo $? >&3", $descriptorspec, $pipes);
fclose($pipes[0]);
$output = array();
// 註解下一行以取得正確的結束碼
while (!feof($pipes[1])) array_push($output, rtrim(fgets($pipes[1],1024),"\n"));
fclose($pipes[1]);
while (!feof($pipes[2])) array_push($output, rtrim(fgets($pipes[2],1024),"\n"));
fclose($pipes[2]);
if (!feof($pipes[3])) $output['exitcode']=rtrim(fgets($pipes[3],5),"\n");
fclose($pipes[3]);
proc_close($proc);
print_r($output);
?>
在我系統上的輸出
陣列
(
[0] => -rw-r--r-- 1 root root 1460 2005-09-02 09:52 /etc/passwd
[1] =>
[2] =>
)
exitcode -1
exitcode 1
陣列
(
[0] => -rw-r--r-- 1 root root 1460 2005-09-02 09:52 /etc/passwd
[1] =>
[2] =>
[exitcode] => 0
)