在 Linux 生產環境中,替換正在被進程使用的文件(二進制可執行檔、共享庫 `.so`、配置檔、靜態資源)是高風險操作。錯誤使用 `cp`/`scp` 會導致進程崩潰、邏輯錯誤、甚至觸發 `SIGBUS` 信號。本文深度剖析底層機制,確立 **`mv`/`rsync` 原子性替換** 為唯一正規作法,並提供標準化操作流程與驗證清單。
rsync -a --inplace --no-whole-file new_file target_file
# --inplace: 直接寫入目標文件(非建立臨時文件再重命名),但仍有截斷風險
# 更安全模式:
rsync -a new_file target_file.new && mv target_file.new target_file
# 利用 mv 原子性重命名完成切換
# 1. 驗證新文件完整性
sha256sum new_binary
file new_binary # 確認架構、動態鏈接信息
ldd new_binary # 依賴檢查
# 2. 確保同分區(關鍵!)
df -h /opt/app/bin/ # 目標目錄掛載點
df -h /tmp/new_binary # 源文件掛載點
# 必須相同掛載點
# 3. 原子替換
mv /tmp/new_binary /opt/app/bin/app_binary
# 4. 重啟服務(必要步驟)
systemctl restart app-service
# 或滾動重啟:新流量導向新進程,舊進程優雅退出
# 應用支援 SIGHUP/信號熱加載
mv /tmp/new_config.yaml /etc/app/config.yaml
kill -HUP $(pidof app) # 觸發重讀配置
# 應用不支援熱加載 -> 必須重啟
mv /tmp/new_config.yaml /etc/app/config.yaml
systemctl restart app
# 1. 準備新版本目錄 (同分區)
rsync -a --delete /source/new_version/ /deploy/staging/
# 2. 原子切換符號鏈接 (推薦:藍綠部署/當前版本指針)
ln -sfn /deploy/staging /deploy/current
# -f 強制覆蓋 -n 不解引用目標目錄 -s 符號鏈接
# 此操作原子性更新 /deploy/current 指向
# 3. 通知服務重載 (如 Nginx)
nginx -s reload
| 錯誤操作 | 後果 | 正確做法 |
|---|---|---|
| `cp new.so /usr/lib/libfoo.so` | 運行中進程 `SIGBUS` 崩潰 | `mv new.so /usr/lib/libfoo.so` + 重啟相關服務 |
| 跨分區 `mv` | 退化為複製+刪除,失去原子性 | 確保源目標同分區,或用 `rsync`+`mv` 兩階段 |
| 直接編輯運行中配置 `vim /etc/app.conf` | 保存瞬間進程可能讀到半寫內容 | 編輯臨時文件 -> `mv` 替換 -> 熱加載/重啟 |
| 用 `scp` 直接覆蓋遠程運行文件 | 同 `cp`,遠程進程崩潰 | `scp` 到臨時目錄 -> 遠程 `ssh mv` 替換 |
| 替換後未重啟服務 | 舊代碼繼續運行,變更不生效 | 建立「替換必重啟/重載」檢查清單 |

Linux 線上文件替換的鐵律:**拒絕 `cp`/`scp` 直接覆蓋運行中文件,擁抱 `mv` 原子重命名(同分區)與 `rsync`+`mv` 兩階段模式,配合服務優雅重啟/熱加載機制**。將此 SOP 內嵌至 CI/CD 部署腳本、Ansible Playbook、Runbook 手冊,以機制對抗人為失誤,守護生產穩定。