SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor · 已更新 2026-09-14

nano 無法儲存:permission denied 怎麼辦

nano 儲存失敗通常有 4 個原因:檔案或父目錄權限、唯讀或已滿的檔案系統,以及容器中的 uid 不符。依序檢查擁有者、掛載狀態與可用空間。

nano 無法儲存檔案的原因

nano 無法儲存檔案,原因有 4 種:您不是檔案擁有者、父目錄不允許 nano 執行所需操作、檔案系統是唯讀或已無可用空間,或您位於以不同使用者 ID 執行的容器中。前兩項是權限問題,後兩項則不是。請依此順序檢查,因為第一種情況涵蓋大多數案例,只需一個命令即可確認,而且修正方式是 sudoedit,而不是 sudo nano

只要編輯器仍開啟,就不會遺失任何內容。文字仍位於記憶體中,因此您可以讓檔案保持開啟,將緩衝區寫入您擁有的路徑,之後再將它放回原處。這個替代方法位於本指南接近結尾的位置。

在變更任何權限前先執行這些檢查

將每個指令的目標設為你實際編輯的路徑。這些指令回答的問題各不相同,因此在進行任何操作前都應全部執行。尚未確認是哪項檢查失敗前就變更權限,通常會在原有問題上再造成另一個問題。

id
ls -l /etc/nginx/nginx.conf
ls -ld /etc/nginx
namei -l /etc/nginx/nginx.conf
findmnt -no SOURCE,FSTYPE,OPTIONS -T /etc/nginx/nginx.conf
df -h /etc/nginx
df -i /etc/nginx

id會顯示目前使用者 ID 與所屬的群組 ID。ls -l會顯示檔案本身的擁有者、群組與權限位元。ls -ld會顯示包含該檔案的目錄之相同資訊;這是另一個獨立問題,答案也不同。namei -l會逐一檢查路徑中的每個部分,列出各部分的擁有者與權限,因此能在同一份輸出中回答這兩個問題。findmnt會顯示該路徑所在的檔案系統,以及掛載時使用的選項。df -h會報告可用空間,df -i會報告可用 inode;inode 可能會在空間用盡前先耗盡。如果你還不熟悉這些權限字串,請先閱讀如何讀取 ls -l 顯示的權限字串

原因 1:檔案屬於 root,而您不是 root

讀取與寫入是分開的權限,而 /etc 下的大多數檔案都允許所有人讀取。因此,nano 能開啟檔案、顯示內容,也能讓您自由輸入,這些操作都還沒有寫入磁碟。拒絕發生在儲存時,因為 kernel 會比對您在檔案上的 user ID、group ID、擁有者、群組及 other 權限位元。nano 只是轉達 kernel 的結果,因此變更 nano 選項也不會改變結果。

idls -l 合併後即可確認原因。檔案由 root 擁有,而您不是 root;other 權限位元也未授予寫入權限。再次按下 Ctrl-O 不會有幫助。

為何 sudoedit 才是編輯 root 擁有檔案的正確方式

SUDO_EDITOR=nano sudoedit /etc/nginx/nginx.conf

sudo 會建立檔案的暫存副本,將擁有者設為你的使用者,接著以你自己的使用者身分在該副本上執行 nano。編輯器結束後,sudo 再以 root 權限將結果複製回原位置。編輯器不會以 root 身分執行。sudo -e 是相同指令的另一個名稱。編輯器會依序從 SUDO_EDITORVISUAL,再到 EDITOR 取得,因此在 shell 設定檔中設定 export EDITOR=nano,即可讓它在所有情況下成為預設值。如果 sudoers 中的 env_editor 旗標已關閉,這些變數會被忽略,編輯器會改用 sudoers 中 editor 設定的值。

sudo nano 也能儲存檔案,但問題就在這裡。只要工作階段持續,完整的互動式編輯器就會對整個檔案系統擁有 root 權限。因此,在儲存提示中誤輸入路徑,就可能以 root 身分將文字寫入其他系統檔案。養成以一般使用者身分工作,只在必要步驟使用 sudo的習慣很重要;編輯設定檔時,sudoedit 正是這項習慣的實際做法。

sudoedit 有兩項容易讓人意外的規則。它拒絕編輯 symbolic link,也拒絕編輯位於你可寫入目錄中的檔案,除非你是 root。第二項規則是因為任何可寫入該目錄的人,都能在編輯器開啟期間替換檔案。這兩項行為都是 sudoers 的預設設定(sudoedit_follow 關閉、sudoedit_checkdir 開啟)。尚不存在的檔案則會替你建立。

原因 2:父目錄實際控制的內容

針對其他編輯器撰寫的建議指出,儲存檔案需要目錄的寫入權限,因為許多編輯器會寫入新檔案,再將新檔案重新命名以取代舊檔案。nano 並非如此運作。它會開啟你指定的檔案,並直接寫入該檔案。因此,對於已存在的檔案,系統不會檢查目錄的寫入位元。

目錄仍會控制其他操作,這也是 ls -ld 出現在檢查清單中的原因:

  • 建立尚不存在的檔案,需要目錄的寫入與執行權限,因為必須在目錄中加入新的名稱。你的 umask 會決定新檔案建立時的權限
  • 要存取檔案,需要路徑上每個目錄都具備執行權限,也稱為搜尋權限。只要其中一個目錄缺少此權限,該目錄下的所有內容都無法存取,而 namei -l 會顯示是哪個目錄造成問題。
  • 啟用備份或檔案鎖定時,儲存操作會在原檔案旁寫入第二個檔案,因此這些功能需要可寫入的目錄。備份功能是 nanorc 中的 -B 選項或 set backup,鎖定功能則是 -Gset locking。除非你或發行版啟用了這些功能,否則兩者都會停用。

目錄權限在系統其他位置也同樣重要。當你的 home 目錄或 .ssh 目錄可由其他使用者寫入時,SSH server 會拒絕使用該金鑰。這是 SSH 在登入時拒絕你的金鑰的常見原因之一。

由於 nano 會寫入現有檔案,該檔案會保留自己的 inode,也就是檔案名稱背後儲存在磁碟上的識別資訊。任何已開啟該檔案的程式都會持續追蹤它,而 bind mount 至容器中的單一檔案也能繼續正常運作。透過取代檔案來儲存的編輯器會使該掛載失效,因為掛載追蹤的是 inode,而不是檔案名稱。

原因 3:檔案系統為唯讀,或已沒有可用空間

選項中的 findmnt 回報 ro,表示這次寫入原本就不可能成功。檔案系統可能是以該方式掛載,例如透過 /etc/fstab 或唯讀 bind mount;也可能是磁碟發生錯誤後,kernel 將其重新掛載為唯讀。後者較為嚴重。sudo dmesg -T | tail -50 會顯示導致重新掛載的 input/output 與檔案系統錯誤。修復方式是在卸載檔案系統後執行檢查。對 VPS 而言,這表示必須啟動供應商提供的 rescue console。

檔案系統已滿時,也會因不同原因導致相同的寫入失敗。df -h 涵蓋一般情況。df -i 則涵蓋常被忽略的情況:inode 來自建立檔案系統時配置的固定資源池。大量小檔案組成的目錄樹可能耗盡所有 inode,即使 df -h 仍顯示有數 GB 的可用空間。當空間耗盡,且沒有明顯程序持有檔案時,df 與 du 對磁碟已滿的結果不一致 說明了刪除但仍開啟的檔案如何造成這個問題。

這裡有一項細節可以解釋容易混淆的現象。建立 ext4 檔案系統時,系統會保留部分 block 給 root,因此一般使用者遭拒絕後,root 仍能繼續寫入。此時 sudo 看似可以解決問題,但磁碟會繼續填滿剩餘空間,問題也會以更嚴重的形式再次出現。

nano 會先截斷檔案,再寫入新內容。因此,寫入途中耗盡空間時,檔案可能會比原本短。在接近滿載的檔案系統上編輯重要設定檔前,請先複製一份。sudo cp -a /etc/nginx/nginx.conf /root/nginx.conf.bak 會保留複本的擁有者、群組與權限。

原因 4:你正在容器中編輯 bind mount

檔案擁有權是數值。核心儲存的是使用者 ID,而你看到的名稱來自執行查詢的 /etc/passwd,因此同一個檔案在主機上可能顯示一個名稱,在容器內則顯示不同名稱,或只顯示數字。請比較數值,不要比較名稱:在容器內執行 id -u,並對該檔案執行 ls -ln

以 bind mount 掛載的檔案會保留主機上的擁有權。當主機檔案屬於你的使用者,而容器程序以不同使用者身分執行時,容器內的寫入會遭拒絕;在容器內執行 sudo 也不會變更主機上的擁有者。請從主機修正,將擁有者設為容器執行時使用的 ID,或讓容器以目前擁有檔案的 ID 執行。linuxserver.io 和類似專案的映像會提供 設定程序執行使用者的 PUID 和 PGID 變數

另外還有兩種容器情況值得注意。使用 :ro 設為唯讀的掛載,或使用 --read-only 啟動的容器,不論擁有權為何都會拒絕寫入;在容器內執行 cat /proc/mounts 可查看該旗標。使用 rootless Podman 時,user namespace 會將容器使用者 ID 對映到主機 ID 的一段範圍,因此在容器內看似屬於 root 的檔案,在容器外實際上屬於你的非特權帳號。

還有一種情況是編輯成功,但之後變更消失。你在容器內變更、且位於非掛載路徑上的檔案,會儲存在該容器的可寫入層中;容器重新建立時,這個層會被捨棄。如果變更需要持久保留,請在主機端的掛載路徑修改檔案,或在映像建置過程中修改檔案。

逃生方案:將檔案儲存至您擁有的路徑

不要嘗試從編輯器內取得權限。按下 Ctrl-O,在提示字元清除路徑,輸入主目錄下的路徑,例如 /home/you/nginx.conf.new,再按 Enter。接著按 Ctrl-X 離開。現在檔案已寫入磁碟,由您擁有;接下來只是一般的檔案複製作業。

sudo cp /home/you/nginx.conf.new /etc/nginx/nginx.conf
sudo nginx -t

這裡請使用 cp,不要使用 mvcp 會透過已存在的檔案寫入,因此該檔案會保留原本的擁有者、群組與權限。mv 在相同檔案系統上以您的檔案取代原檔,會使 /etc 中的設定檔改由您的使用者帳號擁有,這就成為下一個需要處理的權限問題。

重新載入任何服務前,先使用負責該檔案的工具檢查結果。sudo nginx -t 會解析 nginx 設定,sudo sshd -t 會解析 SSH 伺服器設定。有兩類檔案提供專用編輯器,可替您完成整個流程:sudo visudo 用於 /etc/sudoerscrontab -e 用於您自己的 cron 工作。這些工具會編輯暫存副本、檢查語法,只有在解析成功時才會安裝檔案。

FAQ

應使用 sudo nano 還是 sudoedit 編輯系統檔案?

使用 sudoedit。它會將檔案複製到由你擁有的暫存副本,以你自己的使用者身分執行編輯器,並在編輯器結束時以 root 身分寫回結果。因此,編輯器本身不會取得 root 權限。將 SUDO_EDITORVISUALEDITOR 設為 nano,即可選用 nano。sudo nano 也能運作,但它會在工作階段期間,讓互動式編輯器以 root 權限存取系統中的所有路徑。如此一來,在儲存提示中輸入錯誤檔名,就可能使系統檔案損毀。

使用 nano 儲存檔案時,需要對目錄具備寫入權限嗎?

如果檔案已存在,則不需要。nano 會直接寫入檔案本身,因此核心會檢查檔案的寫入位元,以及路徑中每個目錄的執行位元。當檔案尚不存在時,目錄的寫入位元才會影響結果,因為此時必須建立新的名稱。啟用備份或檔案鎖定時也會受到影響,因為這兩者都會在原始檔案旁建立第二個檔案。

擁有者看起來正確,磁碟也未滿。還有什麼原因會阻止寫入?

有 4 種原因。檔案系統可能以唯讀方式掛載,可使用 findmnt -no OPTIONS -T /etc/nginx/nginx.conf 查看。檔案可能具有 immutable 屬性,可使用 lsattr 查看,並以 sudo chattr -i 移除。設定此屬性時,即使是 root 也無法寫入檔案。inode pool 可能已耗盡,即使仍有可用空間;可使用 df -i 查看。即使權限位元允許寫入,SELinux 或 AppArmor 仍可能拒絕操作。稽核日誌會記錄針對你嘗試存取之路徑的拒絕事件。

檔案完全無法儲存時,應將變更放在哪裡?

按下 Ctrl-O,並指定你擁有的路徑,例如 home directory 下,或其他使用者可寫入的位置。緩衝區仍在記憶體中,因此你輸入的內容不會遺失。之後使用 sudo cp 將已儲存的檔案複製到正確位置。此指令會保留原始檔案的擁有者與權限。接著使用該服務自己的測試指令檢查檔案,再重新載入服務。

為什麼我在 Docker container 中的編輯內容會消失?

如果該路徑不是 mount,編輯內容會寫入該 container 的可寫入層;container 被替換時,這一層也會被捨棄。請在 bind mount 或 volume 的主機端編輯檔案,或將檔案建置到 image 中。如果該路徑是 bind mount,但儲存操作改為遭拒,請比較 container 內的 id -uls -ln 顯示的數字擁有者。檔案會保留主機端的擁有權,而 container process 必須符合該擁有者。