首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 執行 Shell 腳本實戰:exec、shell_exec、passthru 選型與安全防範

     編輯:PHP 綜合知識

三大函數比較

函數回傳值輸出處理適用場景
exec()最後一行輸出(字串),第二參數可接收完整輸出陣列不自動輸出需處理輸出每一行、取得狀態碼
shell_exec()完整輸出字串(含換行),失敗回傳 null不自動輸出只需完整輸出字串、不關心狀態碼
passthru()無(回傳狀態碼由參數接收),直接輸出原始二進位資料直接輸出到瀏覽器/標準輸出二進位輸出(圖片、PDF)、即時串流、需狀態碼判斷

實戰範例:rsync 備份整合

<?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() 呼叫備份指令,根據回傳碼寫入資料庫狀態、發送郵件通知。

安全防範:輸入過濾與最小權限

  1. 絕不直接拼接使用者輸入:exec("ls $dir") 極度危險。
  2. 白名單驗證:使用者只能從下拉選單選擇預設指令/參數。
  3. 移除危險字元:escapeshellarg()、escapeshellcmd() 雙重防護。
  4. 禁用 Shell 元字元:; & | ` $ ( ) < > 等。
  5. 以低權限使用者執行 PHP-FPM:www-data、nginx,禁止 sudo。
  6. open_basedir 限制可存取路徑。
  7. 搭配 disable_functions 禁用 exec/shell_exec/passthru 等:若業務必須用,獨立出 Worker 服務,透過訊息佇列(RabbitMQ、Redis Stream)非同步處理,Web 端僅發送任務。

進階替代方案

  • Symfony Process Component:物件導向封裝、超時控制、非同步、管道處理。
  • proc_open():雙向管道、長時間互動、需精細控制 STDIN/STDOUT/STDERR。
  • Swoole/RoadRunner 協程 + Process:高併發下非阻塞執行外部程式。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved