詳細比較 PHP 五種執行外部指令的函數:輸出方式、回傳值、適用場景、安全風險與最佳實踐。
| 函數 | 輸出方式 | 回傳值 | 取得完整輸出 | 取得狀態碼 | 典型用途 |
|---|---|---|---|---|---|
system() | 直接輸出到標準輸出 | 最後一行字串 | 否 | 第 2 參數 | 簡單指令、直接顯示結果 |
exec() | 不輸出 | 最後一行字串 | 第 2 參數 (陣列) | 第 3 參數 | 需處理輸出、取得狀態碼 |
passthru() | 直接輸出 (二進位安全) | 無 (void) | 否 | 第 2 參數 | 圖片串流、二進位輸出 |
shell_exec()/` ` | 不輸出 | 完整輸出字串 | 回傳值即完整輸出 | 無 | 需完整輸出文字 |
popen() | 管道讀/寫 | 檔案指標 | fread/fgets 讀取 | pclose() 回傳 | 雙向互動、長時間程序 |
<?php
// system()
$last = system('ls -la', $ret); // 直接顯示,$last 為最後一行
// exec()
exec('ls -la', $out, $ret); // $out 為陣列每一行,$ret 狀態碼
// passthru() - 輸出圖片
header('Content-Type: image/png');
passthru('./generate_png.sh', $ret);
// shell_exec() / 反引號
$out = shell_exec('ls -la'); // 完整字串
$out = `ls -la`; // 同 shell_exec()
// popen() 雙向互動
$fp = popen('su -c "useradd james"', 'w');
fwrite($fp, 'root_password');
pclose($fp);
?>
escapeshellarg()、escapeshellcmd() 轉義,或改用 proc_open() 陣列式參數繞過 Shell。php.ini 建議 disable_functions = exec,shell_exec,system,passthru,popen,proc_open。mkdir()、unlink()、Imagick、FFMpeg PHP 封裝)優於呼叫外部指令。` ` 補充等同 shell_exec(),不支援狀態碼取得,錯誤輸出需 2>&1 重導向。不建議使用(可讀性差、語法高亮支援差)。