Watch at Ease看見世界,讀懂生活。

科技 · 實用指南

rm 顯示「Operation not permitted」?chmod 或 chattr 前先證明 unlink 邊界

保存精確 errno,檢查父目錄與 inode 屬性,區分 sticky、掛載、命名空間與政策原因,再用一次性同層探針驗收單一修復。

原創示意圖:依路徑、父目錄、inode 屬性、sticky 所有權、掛載、能力與政策逐層定位 rm 的 EPERM。
原創插畫:修改權限或特權前,先證明 unlink 邊界。 Watch at Ease

「Operation not permitted」是 unlink 邊界的證據,不代表 rm 需要更強制。真正控制操作的可能是父目錄、immutable/append-only 屬性、sticky 所有權、檔案系統規則、命名空間能力或安全政策。

先保存精確路徑與 errno,不做更改地逐層檢查。只修復一個已證明原因,用一次性同層探針驗證父目錄;只有明確獲准且已備份時,才刪除精確目標。

1. 固定路徑與真實錯誤

保存完整命令、精確 stderr、有效使用者、工作目錄與命名空間。目標應存在時以 realpath -e 解析,分別記錄目標與父目錄的 stat;也保存原始路徑,因為 unlink 操作的是目錄項目,符號連結、bind mount 或改名的父目錄都會改變對象。

不要把所有「cannot remove」都視為 EPERM。Linux 將父目錄缺少寫入或搜尋權限列為 EACCES、唯讀檔案系統列為 EROFS,掛載點或部分 NFS 情況列為 EBUSY。若需要 strace,只在一次性復現環境或刪除已獲准且已備份時使用,因為成功追蹤會真的刪掉名稱。

2. 先查父目錄,再看檔案模式

用 namei -l 逐元件檢查,並分別 stat 直接父目錄與目標。刪除名稱會修改父目錄;讓檔案本身可寫不會授予目錄操作。先記錄 owner、group、mode 與 ACL,不先更改。

父目錄有 sticky bit 時,除非有效使用者擁有檔案、擁有目錄或具備相應能力,Linux 可能拒絕 unlink。保留共享目錄保護,證明正確執行者或所有權,不要從 /tmp 或共享工作區移除 sticky。

3. 讀取目標與父目錄的 inode 屬性

對目標與父目錄都執行 lsattr -d --。immutable 會阻止刪除與重新命名,append-only 也可能讓 unlink 回傳 EPERM。不是所有檔案系統都支援全部屬性;不支援只是繼續診斷的證據。

若屬性已證明是原因,先記錄物件擁有者與設定理由,只在精確物件上清除必要的 i 或 a,並由持有 CAP_LINUX_IMMUTABLE 的主機或命名空間操作。不要遞迴 chattr,也不要為了繞過診斷授予容器廣泛特權。

4. 區分掛載、檔案系統與政策邊界

對精確目標執行 findmnt -T,記錄來源、檔案系統類型與選項。唯讀掛載回傳 EROFS,不等於 EPERM;掛載點或 NFS silly rename 可能回傳 EBUSY。overlay、網路與容器檔案系統還增加所有權和命名空間邊界,舊產品特例不能當成通用修復。

若 mode、sticky ownership 與 inode 屬性都不能解釋拒絕,再收集政策證據:可用時查看 ls -lZ、近期 AVC 或核心日誌、有效 capabilities 與相關容器或 user namespace。只修具體政策或擁有層,不要全域關閉 SELinux/AppArmor,也不要改成全面 privileged。

5. 只修一個原因並完成驗收

只做與證據對應的一項可逆更改:修正目標父目錄 owner 或 access、清除一個已證明屬性、以合法 sticky owner 執行、修復 mount/storage 層,或更新具體安全規則。之後重新讀取 stat、lsattr 與 findmnt,留下因果記錄。

接觸真實目標前,政策允許時在同一父目錄建立並刪除一次性同層 probe。它能證明父目錄操作,不代表有權刪除目標。確認精確路徑、備份與 owner 核准後只刪一次。unlink 刪除的是名稱;已開啟檔案會保留 inode 與資料,直到最後一個描述符關閉。

原創示意圖:分開觀察、單一原因修復、一次性同層探針與獲准刪除目標。
原創插畫:先診斷,只修一個原因,用同層探針驗收,再刪除獲准目標。 Watch at Ease