運算技術 · 實用指南
Linux 顯示「Invalid cross-device link」?先證明掛載邊界,再決定重新命名、複製或發布
EXDEV 是契約警告,不是路徑字串謎題。先在呼叫程序的掛載命名空間映射兩端,再判斷是否需要原子重新命名;若要跨檔案系統複製,應在刪除來源前於目的端暫存、驗證並完成本地重新命名。

Linux 在 rename 無法於同一已掛載檔案系統完成移動時回傳 EXDEV,常顯示為「Invalid cross-device link」。目錄名稱看似相關,也可能因 bind mount、容器磁碟區、tmpfs、overlay 層或獨立檔案系統而屬於不同掛載身分。修改程式或權限前,必須從失敗程序所在的同一掛載命名空間檢查兩條路徑。
跨檔案系統的備援並不是偽裝的 rename,而是複製、驗證,以及成功後才刪除來源。若讀者不能看到半成品,應在目的檔案系統寫入臨時物件,刷新並驗證,再於同一目的掛載把臨時名稱改為最終名稱。只保留工具與目的端實際支援的中繼資料,並明確說明整體跨掛載移動不是原子操作。
1. 記錄失敗操作及其命名空間
記錄真實呼叫者的精確來源、目的、程序身分、容器或服務環境及實際錯誤。若故障發生在容器或私有掛載命名空間,不能只在主機 shell 重現,因為同一路徑字串可能對應不同掛載表。
也要說明這是一般搬移、取代既有名稱,還是對讀者承諾全有或全無的發布步驟。這項要求決定複製再刪除是否可接受。
2. 將兩條路徑映射到掛載身分
在呼叫者的命名空間對來源與目的目錄執行 findmnt --target。調查另一程序時,可在權限允許下使用 findmnt --task PID 或讀取 /proc/PID/mountinfo。比較掛載 ID、根、掛載點、檔案系統類型與來源,不要依賴目錄前綴。
若最終檔案尚不存在,就解析其父目錄。bind mount 可能顯示相同底層裝置卻有不同掛載身分;rename(2) 也指出,即使同一檔案系統掛載在兩個位置,跨已掛載檔案系統的重新命名仍可能遭拒。
3. 決定操作真正需要的保證
若操作必須是一次原子命名空間變更,就讓臨時名稱與最終名稱位於同一掛載,並在那裡使用 rename。應重新設定臨時目錄、工作區、磁碟區或發布暫存位置,而非盲目加入跨檔案系統複製。
若允許短暫重複與整體非原子移動,複製流程可以正確,但必須寫明保證。在目的端通過驗證前,來源始終是權威副本。
4. 在目的檔案系統暫存並驗證
在目的目錄建立唯一臨時名稱,複製資料,依耐久性政策關閉並刷新,再驗證大小或密碼摘要。還要檢查應用程式依賴的中繼資料:模式、擁有者、時間戳、ACL、延伸屬性、符號連結身分和稀疏配置不一定都能保留。
驗證後,把目的端臨時物件改成最終名稱。因為兩個名稱位於同一掛載,最後這次重新命名可以是原子的。刪除原件前,確認最終物件及其存取政策。
5. 測試故障邊界,而不是隱藏 EXDEV
分別測試複製完成前中斷、驗證後中斷、目的端本地重新命名後中斷,以及刪除來源前中斷。復原程序應能安全處理殘留臨時目的、完整最終目的加未刪來源,以及程序崩潰後重試。
不要靠改權限、重試相同 rename 或壓掉錯誤來「修復」EXDEV。它證明所要求的原子契約跨越掛載邊界;應選擇明確記錄強弱保證的工作流程。
