核心命令:`shutdown.exe`
shutdown [/i | /l | /s | /r | /a] [/f] [/m \\Computer] [/t xxx] [/c "msg"] [/d [p|u:]xx:yy]
| 參數 | 說明 |
| `/s` | 關機 |
| `/r` | 重啟 |
| `/m \\Computer` | 指定遠端電腦名稱或 IP (需 RPC 通訊) |
| `/t xxx` | 延遲秒數 (預設 30,範圍 0-315360000) |
| `/c "msg"` | 顯示於關機對話框的訊息 (最長 512 字元) |
| `/f` | 強制關閉應用程式 (不提示儲存) |
| `/a` | 中止已排程的關機 |
| `/d p:xx:yy` | 記錄原因 (計劃/非計劃、主要/次要代碼) |
前置條件:目標機器權限設定
- 啟用遠端關機權限:
`gpedit.msc` → 電腦設定 → Windows 設定 → 安全性設定 → 本地原則 → 用戶權利指派 → **從遠端系統強制關機** → 加入 `Guest` 或專用服務帳號 (如 `PHPSHUTDOWN`)。
- 啟用檔案與印表機共享 / RPC:
防火牆 → 允許「檔案和印表機共享 (SMB-In)」、「遠端服務管理 (RPC)」、「Windows 管理儀器 (WMI-In)」。
- 網路發現與共享:
網路和共用中心 → 進階共用設定 → 啟用「網路發現」、「檔案和印表機共享」。
- 相同工作群組/網域:確保 PHP 伺服器與目標機器在同一網域或工作群組,且 DNS/NetBIOS 可解析電腦名。
PHP 呼叫範例
<?php
function remoteShutdown(string $target, int $delay = 60, string $msg = 'System maintenance'): bool {
// 參數過濾
$target = escapeshellarg($target);
$delay = (int)$delay;
$msg = escapeshellarg($msg);
// 構建命令
$cmd = "shutdown /s /f /m {$target} /t {$delay} /c {$msg}";
// 執行 (需 PHP 進程用戶具備上述權限)
$output = [];
$return = 0;
exec($cmd, $output, $return);
if ($return !== 0) {
error_log("Remote shutdown failed for {$target}: " . implode("\n", $output));
return false;
}
return true;
}
// 使用
if (remoteShutdown('\\\\WORKSTATION01', 120, 'Scheduled maintenance at 22:00')) {
echo "Shutdown command sent successfully.";
} else {
echo "Failed to send shutdown command.";
}
?>
常見失敗原因排查
| 錯誤碼/訊息 | 原因 | 解決 |
| `Access denied (5)` | 呼叫者無「從遠端系統強制關機」權限 | 檢查 GPO、本地安全原則、帳號成員資格 |
| `The network path was not found (53)` | 無法解析 `\\Computer` 或 RPC 連接失敗 | 檢查 DNS、WINS、防火牆 RPC 端口 (135, 445, 動態高端口) |
| `The RPC server is unavailable (1722)` | 遠端機器 RPC 服務未啟動或被防火牆阻擋 | 服務 `Remote Procedure Call (RPC)`、`Server` 必須運行 |
| `A system shutdown is in progress (1115)` | 已有排程關機未執行 | 先執行 `shutdown /a /m \\Computer` 中止 |
安全性最佳實踐
- 專用服務帳號:建立 `PHPSHUTDOWN` 帳號,僅授予「從遠端系統強制關機」與「作為批次作業登入」權限,密碼複雜且定期輪換。
- 最小權限原則:PHP-FPM/Apache 以低權限用戶運行,透過 `sudoers` 允許僅執行 `shutdown.exe` (Windows 無 sudo,可用 `psexec -u PHPSHUTDOWN` 或建立 Windows 服務接收指令)。
- 驗證與審計:Web 介面需 **雙因子驗證 (2FA)**、操作日誌寫入不可篡改存儲 (Syslog/ELK)。
- 替代方案:WMI / PowerShell Remoting / SSH:
# PowerShell Remoting (需目標啟用 Enable-PSRemoting)
Invoke-Command -ComputerName WORKSTATION01 -ScriptBlock { Stop-Computer -Force } -Credential (Get-Credential)
# SSH (Windows 10 1809+ 內建 OpenSSH Server)
ssh admin@WORKSTATION01 "shutdown /s /t 60 /c 'Maintenance'"
# PHP 執行 SSH (需 php-ssh2 擴展)
$ssh = ssh2_connect('WORKSTATION01', 22);
ssh2_auth_password($ssh, 'admin', 'pass');
ssh2_exec($ssh, 'shutdown /s /t 60 /c "Maintenance"');
**推薦使用 SSH 或 PowerShell Remoting**,加密傳輸、強認證、跨平台、易審計,避免傳統 RPC 的 NTLM/Kerberos 複雜性與安全風險。