| 函數 | 回傳值 | 輸出處理 | 適用場景 |
|---|---|---|---|
exec() | 最後一行輸出(字串),第二參數可接收完整輸出陣列 | 不自動輸出 | 需處理輸出每一行、取得狀態碼 |
shell_exec() | 完整輸出字串(含換行),失敗回傳 null | 不自動輸出 | 只需完整輸出字串、不關心狀態碼 |
passthru() | 無(回傳狀態碼由參數接收),直接輸出原始二進位資料 | 直接輸出到瀏覽器/標準輸出 | 二進位輸出(圖片、PDF)、即時串流、需狀態碼判斷 |
<?php
// 1. 使用 passthru 執行 rsync 腳本,即時顯示進度,並取得狀態碼
$script = '/usr/local/bin/backup_rsync.sh';
passthru($script, $returnVar);
if ($returnVar !== 0) {
error_log("Backup failed with code $returnVar");
// 發送告警、寫入資料庫錯誤日誌
} else {
// 成功:可選擇導向完成頁面
header('Location: /backup/success');
}
// 2. 使用 exec 列出程序,解析輸出陣列
exec('ps aux | grep php-fpm', $output, $status);
foreach ($output as $line) {
// 解析 PID、CPU、記憶體...
}
// 3. 使用 shell_exec 取得完整輸出字串
$disk = shell_exec('df -h /');
echo "$disk
";
獨立 PHP 腳本 + cron 比在 Web 請求中執行長時間任務更穩健:
# crontab -e
0 2 * * * /usr/bin/php /var/www/scripts/nightly_backup.php >> /var/log/backup.log 2>&1
腳本內用 exec() 呼叫備份指令,根據回傳碼寫入資料庫狀態、發送郵件通知。
exec("ls $dir") 極度危險。escapeshellarg()、escapeshellcmd() 雙重防護。; & | ` $ ( ) < > 等。www-data、nginx,禁止 sudo。