功能需求
- 主伺服器透過 FTP 將指定檔案同步至多台備份/分流伺服器
- 支援排除檔案清單(如 robots.txt)
- Web 介面輸入檔案清單(每行一個路徑),jQuery AJAX 提交
- 即時顯示成功/失敗訊息
核心同步邏輯
function sync() {
$files = array_filter(array_map('trim', explode("\n", $_POST['files'])));
if (!$files) exit('沒有檔案');
$servers = [
'server1' => ['host1.com', 'ftp_user', 'ftp_pass', 'remote_root_path'],
// 'server2' => ['host2.com', 'user', 'pass', 'path'],
];
$abortFiles = ['robots.txt'];
$errors = [];
$success = [];
foreach ($servers as $name => $ftp) {
$conn = ftp_connect($ftp[0]);
if (!$conn) { $errors[] = "$name 無法連線"; continue; }
if (!ftp_login($conn, $ftp[1], $ftp[2])) { $errors[] = "$name 登入失敗"; continue; }
$remoteRoot = $ftp[3] ?? '';
if ($remoteRoot) ftp_chdir($conn, $remoteRoot);
$remoteRoot = rtrim(ftp_pwd($conn), '/');
foreach ($files as $file) {
$base = basename($file);
if (in_array($base, $abortFiles)) { $errors[] = "$file 禁止同步"; continue; }
if (!file_exists('.' . $file)) { $errors[] = "$file 不存在"; continue; }
if (!ftp_put($conn, "$remoteRoot/$file", '.' . $file, FTP_BINARY)) {
$errors[] = "$file 上傳失敗";
} else {
$success[] = $file;
}
}
ftp_close($conn);
}
if (!$errors) exit('上傳成功:' . implode('、', $success));
exit(implode('
', $errors));
}
前端介面
echo '';
echo <<
EOF;
安全性與生產環境建議
- 身分驗證:實務必加入登入檢查或 API Token,防止未授權呼叫
- 傳輸加密:改用 FTPS (FTP over SSL) 或 SFTP (SSH2),
ftp_ssl_connect / ssh2_scp_send
- 路徑防遍歷:驗證
$file 不含 ../,限制在專案根目錄下
- 大檔案支援:
ftp_put 可能逾時,分塊上傳或調整 ftp_set_option($conn, FTP_TIMEOUT_SEC, 300)
- 並行化:多伺服器可用
curl_multi 或非同步程式庫並行傳輸
- 日誌審計:記錄同步時間、操作人、檔案清單、結果供追蹤
適用場景
- 程式碼部署同步至多台 Web 節點
- 靜態資源(圖片、CSS、JS)分發至 CDN 邊緣節點
- 設定檔、SSL 憑證批量分發
- 災備檔案異地備份