208 個代碼(共 208 個)
該操作需要處理序所沒有的特殊權限,例如變更檔案的擁有者、傳送訊號給其他使用者的處理序,或修改不可變更的檔案(chattr +i)。與 EACCES 不同,變更檔案權限無法解決:需要 root 或對應的 capability。
檔案或目錄不存在。當路徑中缺少某個中間目錄、符號連結指向不存在的目標,或指令碼 #! 行中的直譯器沒有安裝時,也會出現此錯誤。
不存在具有該識別碼的處理序、處理序群組或執行緒;例如對已經結束的 PID 執行 kill。
系統呼叫在完成之前被訊號中斷。這不是真正的錯誤:程式應重試該呼叫,或以 SA_RESTART 安裝訊號處理常式。
低階輸入/輸出錯誤,通常發生在讀寫裝置時。就磁碟而言,通常表示有損壞的磁區或纜線故障:請檢查 dmesg 與 SMART 狀態。寫入已關閉的終端機時也會出現。
裝置或位址不存在:裝置檔案存在,但背後沒有硬體;或以 O_NONBLOCK 開啟一個沒有讀取端的 FIFO 進行寫入。
傳給 exec 的引數與環境變數清單過大。這就是使用會展開成數千個檔案的萬用字元時典型的「Argument list too long」;請改用 find -exec 或 xargs。
檔案不是可辨識的執行檔格式:它是其他架構的二進位檔、已損壞,或是沒有 #! 行的指令碼。
檔案描述子無效、已關閉,或其開啟模式不允許該操作,例如寫入以唯讀方式開啟的描述子。
該處理序沒有可用 wait 或 waitpid 等待的子處理序,通常是因為 SIGCHLD 被忽略,子處理序會自動被回收。
資源暫時無法使用,應稍後重試。在非阻塞操作中,表示還沒有資料或空間;在 fork 中,表示已達到處理序或執行緒數量上限(ulimit -u 或 cgroup 的 pids.max)。
相同值:EWOULDBLOCK
記憶體不足以完成該操作,或超出了處理序的某項記憶體限制。在 fork 或 mmap 中,可能是 overcommit 原則、cgroup 限制或位址空間不足所致。
權限遭拒,原因可能是檔案或路徑中某個目錄的權限(每個目錄都需要執行權限)、ACL、SELinux 或 AppArmor,或是以 noexec 掛載。沒有特殊權限時使用小於 1024 的連接埠,bind 也會傳回此錯誤。
傳給系統呼叫的指標指向無效的記憶體位址。這表示程式有 bug。
該操作需要區塊裝置(如磁碟),收到的卻是其他類型的檔案;例如不加 -o loop 掛載一般檔案。
裝置或資源正在使用中。常見於卸載仍有開啟的檔案或有終端機位於其中的檔案系統;lsof 或 fuser 可以顯示哪些處理序正在使用它。
已存在同名的檔案、目錄或其他物件,例如以 O_EXCL 建立、不加 -p 使用 mkdir,或建立連結時目標已存在。
無法在不同的檔案系統之間建立硬連結或重新命名檔案。mv 會改用先複製再刪除的方式處理;使用 rename() 的程式也必須這麼做。
裝置不存在或不支援該操作;例如掛載某種檔案系統類型時,其核心模組尚未載入。
路徑中本應是目錄的某個部分是檔案,或要求的是目錄(O_DIRECTORY),但對象並不是目錄。
對目錄執行了檔案操作,例如以寫入模式開啟它。
某個引數對該呼叫無效:值超出範圍、選項組合不相容,或物件不支援該操作。這是一個通用錯誤:該呼叫的 man 說明頁會列出具體情況。
整個系統的開啟檔案表已用盡。可以透過 sysctl 中的 fs.file-max 調整這項限制。
處理序已達到開啟描述子數量的上限(「Too many open files」)。可以用 ulimit -n 或 systemd 中的 LimitNOFILE 提高限制,並檢查程式是否有未關閉的檔案或通訊端。
對不是終端機的對象要求了終端機操作(ioctl),例如互動式程式的輸出被重新導向到檔案或管線時。
執行檔正在使用中:無法寫入正在執行的二進位檔,也無法執行仍以寫入模式開啟的檔案。要更新它,最好寫入新檔案後再重新命名。
檔案超出了檔案系統支援的最大大小(FAT32 為 4 GB)或處理序的 RLIMIT_FSIZE 限制。
裝置上沒有剩餘空間。如果 df 顯示還有可用空間,請用 df -i 檢查 inode。inotify 在 fs.inotify.max_user_watches 用盡時也會傳回此錯誤。
無法對管線、FIFO 或通訊端執行 lseek,因為它們沒有位置。
檔案系統是以唯讀方式掛載的。如果在沒人要求的情況下變成唯讀,那是核心偵測到錯誤所致:請檢查 dmesg 並執行 fsck。
超過了一個檔案的硬連結數量上限;在某些檔案系統中,則是一個目錄的子目錄數量上限。
寫入另一端已關閉的管線或通訊端(「Broken pipe」)。除了這個錯誤,處理序還會收到 SIGPIPE;當讀取端提早結束時這是正常的,例如 cmd | head。
數學函式的引數超出其定義域,例如負數的平方根。
函式的結果太大或太小而無法表示,或緩衝區不足以容納結果,例如以過短的緩衝區呼叫 getcwd。
避免了一次死結:所要求的鎖定(如 fcntl 檔案鎖定,或具錯誤檢查的互斥鎖)將會永遠等待下去。
相同值:EDEADLOCK
路徑或其中某一部分超過了最大長度:在 Linux 中,一般是每個名稱 255 位元組,整個路徑 4096 位元組。
沒有可用的鎖定。在 NFS 中,通常表示鎖定服務(lockd 或 rpc.statd)沒有在執行。
該系統呼叫在此核心中不存在或尚未實作。常見於為較新核心編譯的二進位檔,或不認識新系統呼叫的容器 seccomp 設定檔。
目錄不是空的,例如使用 rmdir,或重新命名以覆蓋現有目錄時。若要連同內容一起刪除,請使用 rm -r。
解析路徑時遇到過多串連的符號連結,通常是因為形成了迴圈;或對符號連結使用了 O_NOFOLLOW。
System V 訊息佇列中沒有所要求類型的訊息。
System V IPC 識別碼(訊息佇列、號誌或共用記憶體)在處理序使用期間被移除。
通道編號超出範圍。這是舊有代碼,在 Linux 中沒有實際用途。
第 2 層未同步。這是 System V 的舊有代碼,在 Linux 中沒有實際用途。
第 3 層已停止。這是 System V 的舊有代碼,在 Linux 中沒有實際用途。
第 3 層已重設。這是 System V 的舊有代碼,在 Linux 中沒有實際用途。
連結編號超出範圍。這是舊有代碼,在 Linux 中沒有實際用途。
協定驅動程式未連接。只有少數子系統使用它,例如某些藍牙驅動程式。
沒有可用的 CSI 結構。這是舊有代碼,在 Linux 中沒有實際用途。
第 2 層已停止。這是 System V 的舊有代碼,在 Linux 中沒有實際用途。
無效的交換。這是舊有代碼,某些驅動程式與檔案系統會賦予它自己的意義重新使用。
無效的要求描述子。這是舊有代碼,某些驅動程式會賦予它自己的意義重新使用。
交換已滿。這是舊有代碼,在 Linux 中沒有實際用途。
沒有「anode」。這是舊有代碼,在 Linux 中沒有實際用途。
無效的要求代碼。這是舊有代碼;某些驅動程式用它表示不支援的命令。
無效的槽位(slot)。這是舊有代碼,在 Linux 中沒有實際用途。
字型檔案格式錯誤。這是舊有代碼,在 Linux 中沒有實際用途。
裝置不是 STREAM。它屬於 System V 的 STREAMS 介面,Linux 並未實作該介面。
沒有可用的資料。在 Linux 中,延伸屬性不存在時 getxattr 會傳回它;在 macOS 中,這種情況對應的是 ENOATTR。
計時器逾時。它源自 STREAMS;在 Linux 中,某些驅動程式與 io_uring 會將它用於有時間限制的操作。
STREAMS 資源已用盡,而 Linux 並未實作該介面。
電腦不在網路上。這是很少使用的舊有代碼。
套件未安裝。這是舊有代碼;某些子系統在缺少模組(例如加密模組)時會使用它。
物件位於遠端。在 NFS 中,表示該路徑是從另一台伺服器匯出的。
連結已中斷。這是舊有代碼;某些驅動程式在與裝置失去連線時會使用它。
「advertise」錯誤。這是 RFS 的舊有代碼,在 Linux 中未使用。
「srmount」錯誤。這是 RFS 的舊有代碼,在 Linux 中未使用。
傳送時發生通訊錯誤。這是舊有代碼;某些網路與 USB 驅動程式會使用它。
協定錯誤:對方或裝置回應了非預期的內容。會出現在 USB 裝置上,以及在交換過程中中斷的連線中。
嘗試了多重躍點(multihop)。這是 RFS 的舊有代碼。
RFS 特有的錯誤。在 Linux 中未使用。
訊息格式錯誤或已損毀。中繼資料的總和檢查碼驗證失敗時,ext4、XFS 與 Btrfs 會傳回它,別名為 EFSBADCRC。
相同值:EFSBADCRC
值無法放入目標資料型別;例如,編譯時未啟用大型檔案支援的 32 位元程式開啟超過 2 GB 的檔案。
名稱在網路上不是唯一的。這是舊有代碼。
檔案描述子處於錯誤的狀態。ALSA 與某些驅動程式在裝置尚未就緒時會使用它。
遠端位址已變更。這是舊有代碼。
無法存取所需的共用程式庫。這是 a.out 二進位檔的舊有代碼。
共用程式庫已損毀。這是 a.out 二進位檔的舊有代碼。
a.out 二進位檔的 .lib 區段已損毀。這是舊有代碼。
嘗試連結過多的共用程式庫。這是 a.out 的舊有代碼。
共用程式庫無法直接執行。這是 a.out 的舊有代碼。
位元組序列對該字元編碼無效,例如以 iconv 或多位元組函式轉換不是有效 UTF-8 的文字時。
被中斷的呼叫應重新啟動。它僅供核心內部使用,不應傳到程式中。
STREAMS 管線錯誤。音訊裝置處於暫停狀態時,ALSA 會傳回它。
使用者過多。磁碟配額系統在其表格已滿時會傳回它,這種情況很少見。
對不是通訊端的描述子執行了通訊端操作。
缺少目的地位址:透過非連線導向的通訊端傳送時沒有指定要送往哪裡。
訊息對該通訊端而言太大,例如 UDP 資料包超過最大值,或在不允許分段時超過 MTU。
協定與通訊端類型不符。
所要求的通訊端選項或協定無法使用,例如核心不認識的 setsockopt 選項。
不支援該協定,例如因為其核心模組尚未載入。
該位址家族不支援此通訊端類型。
通訊端或物件不支援該操作。在 Linux 中它與 ENOTSUP 的值相同,許多檔案系統對未實作的功能(如 fallocate 或延伸屬性)會傳回它。
不支援該操作。在 Linux 中它與 EOPNOTSUPP 的值相同(95);在 macOS 中則是不同的代碼。
不支援該協定家族。
不支援該位址家族;常見於在停用 IPv6 的系統或容器中使用 IPv6。
位址與連接埠已在使用中:另一個處理序正在接聽該連接埠,或先前的連線仍處於 TIME_WAIT 狀態。可用 ss -ltnp 或 lsof -i :連接埠 找出該處理序,或使用 SO_REUSEADDR。
無法指派所要求的位址:該 IP 不屬於本機的任何介面,或用於連出連線的暫時連接埠已用盡。
網路介面已停止運作。
無法連線到目的地網路,因為沒有通往它的路由。請檢查路由表與閘道;在沒有 IPv6 連線能力時透過 IPv6 連線也會發生。
網路重設了連線,例如 keepalive 失敗時。
連線在本機端被中止,例如用戶端在伺服器以 accept 接受連線之前就關閉了它。
對方以 RST 突然切斷了連線(「Connection reset by peer」):遠端處理序已關閉、防火牆或負載平衡器切斷了閒置的連線,或傳送了對方未預期的資料。
核心中沒有可供該網路操作使用的緩衝區空間;通常出現在流量很大或通訊端佇列已滿時。
通訊端已經連線。
通訊端未連線:在連線之前嘗試傳送或接收,或連線已經關閉。在 FUSE 掛載中,當其處理序已終止時會顯示為「Transport endpoint is not connected」;以 fusermount -u 卸載即可解決。
以 shutdown 關閉通訊端的該方向後,就無法再傳送。
參考過多;在 Linux 中,是透過 Unix 通訊端傳遞了過多巢狀的描述子。
連線逾時,因為目的地沒有回應。通常是防火牆默默丟棄了封包、主機已關機,或路由無法到達。
目的地拒絕了連線:主機有回應,但沒有程式在該連接埠上接聽,或防火牆回覆了拒絕。請確認服務正在執行,並在正確的介面上接聽,而不只是 127.0.0.1。
目的地主機已停止運作。
沒有通往主機的路由:它在區域網路中沒有回應 ARP,或路由器或防火牆回報它無法連線。
通訊端上已有操作正在進行,例如尚未完成的非阻塞 connect。
操作正在進行中:非阻塞 connect 已經開始,稍後才會完成。這不是錯誤;需要以 poll 或 select 等待。
檔案控制代碼已失效:在 NFS 中,該檔案或目錄已在伺服器上被刪除或取代。重新開啟路徑或重新掛載即可解決。
結構需要清理:檔案系統偵測到損毀(在 ext4 與 XFS 中,別名為 EFSCORRUPTED)。請將它卸載並執行 fsck 或 xfs_repair。
相同值:EFSCORRUPTED
不是 XENIX 具名類型檔案。這是已不再使用的舊有代碼。
沒有可用的 XENIX 號誌。這是已不再使用的舊有代碼。
是 XENIX 具名類型檔案。這是已不再使用的舊有代碼。
遠端 I/O 錯誤,例如 I2C 裝置或遠端磁碟沒有回應。
超出了使用者或群組的磁碟配額。
裝置中沒有媒體,例如光碟機中沒有光碟,或讀卡機中沒有卡片。
媒體類型不正確。
操作已取消,例如非同步 I/O 或 io_uring 的等待。
所需的金鑰不在核心的金鑰環(keyring)中。出現在加密檔案系統(如 fscrypt 或 eCryptfs)的金鑰尚未載入時。
金鑰已過期。PAM 與 Kerberos 在密碼或票證過期時也會使用它。
金鑰已被撤銷。
服務拒絕了該金鑰。
強固互斥鎖(robust mutex)的擁有者在未釋放它的情況下終止了。新的擁有者必須讓受保護的狀態恢復一致,並呼叫 pthread_mutex_consistent。
受強固互斥鎖保護的狀態無法復原,因為先前的擁有者已終止,且沒有人將其標記為一致。
無法執行該操作,因為 Wi-Fi 或藍牙無線電被 RF-kill 封鎖。請檢查 rfkill list、實體開關或飛航模式按鍵。
該記憶體分頁有硬體錯誤,核心已將其標記為中毒(poisoned)。
檔案類型不適合該操作。它在 macOS 與 BSD 中早已存在;在 Linux 中則是最近才加入。
處理序過多。BSD 定義它用於處理序數量限制,但實際上 fork 傳回的是 EAGAIN。
RPC 結構錯誤(Sun RPC,NFS 使用它)。
RPC 版本不符(Sun RPC,NFS 使用它)。
伺服器上的 RPC 程式無法使用。
RPC 程式版本不符。
RPC 程式中不存在該程序。
驗證錯誤,例如掛載 NFS 資源時。
該操作需要驗證器。
裝置電源已關閉。
裝置錯誤,例如印表機缺紙。
執行檔無效。
執行檔適用於其他類型的 CPU,例如在未安裝 Rosetta 2 的 Apple Silicon Mac 上執行僅支援 x86_64 的二進位檔,或在 Intel Mac 上執行 ARM 二進位檔。
共用程式庫的版本不符。
Mach-O 檔案格式錯誤或已損毀。
延伸屬性不存在;相當於 Linux 的 ENODATA。使用 xattr 時會出現,例如從沒有 com.apple.quarantine 屬性的檔案移除該屬性。
MAC Framework 中沒有以該名稱註冊的原則。
網路介面的輸出佇列已滿。
能力不足:受沙箱限制的呼叫會傳回它。
控制該處理序的終端機已關閉,或 SSH 工作階段已中斷。許多常駐程式(如 nginx、sshd 或 rsyslog)會將它視為重新讀取設定的要求;nohup、tmux 與 screen 可避免它在離開時關閉處理序。
從鍵盤按 Ctrl+C 發出的中斷。程式可以攔截它以便有條理地結束。結束碼 130。
從鍵盤按 Ctrl+\ 發出的結束要求。它會終止處理序並產生核心傾印;而 JVM 則用它來列印執行緒的狀態。
處理器遇到了不合法的指令:為較新 CPU 編譯的二進位檔(例如在不支援 AVX2 或 AVX-512 的處理器上使用了這些指令)、損毀的程式碼,或跳到了資料區。
偵錯陷阱:偵錯工具用它來實作中斷點。如果在沒有偵錯工具時收到,通常是程式本身偵測到的錯誤,例如 macOS 上 Swift 的檢查。
處理序呼叫了 abort():斷言失敗、未攔截的 C++ 例外,或 C 程式庫偵測到堆積損毀(「double free or corruption」)。結束碼 134。
相同值:SIGIOT
匯流排錯誤:在某些架構上存取未對齊的記憶體,或存取以 mmap 對應的檔案中因檔案被截斷而已不存在的部分。/dev/shm 寫滿時也會發生。
算術例外。雖然名稱如此,最常見的原因是整數除以零。
立即終止處理序:無法攔截、封鎖或忽略。會發送它的有 kill -9、記憶體耗盡時核心的 OOM killer,以及容器超出記憶體限制(OOMKilled)或在 SIGTERM 之後未及時結束時的 Docker 或 Kubernetes。結束碼 137。
保留給各應用程式自訂用途的訊號;例如 dd 會回報進度,nginx 會重新開啟記錄檔。
區段錯誤(「Segmentation fault」):存取了無效的記憶體,例如對空指標取值、陣列越界,或因無限遞迴造成堆疊溢位。結束碼 139。
第二個保留給各應用程式自訂用途的訊號。
寫入沒有讀取端的管線或通訊端。在 cmd | head 中這是正常的,因為讀取端會先結束;伺服器通常會忽略它並處理 EPIPE 錯誤。結束碼 141。
以 alarm 或 setitimer 設定的計時器已到期。
要求有條理地終止。它是 kill、systemctl stop、docker stop 以及 Kubernetes 刪除 Pod 時的預設訊號;處理序應關閉其連線並結束。結束碼 143。
輔助處理器堆疊錯誤。目前的 Linux 已不再使用。
子處理序已終止、暫停或繼續執行。父處理序必須以 wait 回收它;否則子處理序會變成殭屍處理序。
相同值:SIGCLD
讓已暫停的處理序繼續執行,就像 shell 中的 fg 與 bg 所做的那樣。
暫停處理序;無法攔截或忽略。以 SIGCONT 繼續執行。
在終端機按 Ctrl+Z 發出的暫停。與 SIGSTOP 不同,程式可以攔截它。
背景處理序嘗試從終端機讀取。
背景處理序在啟用 stty tostop 時嘗試寫入終端機,或嘗試變更終端機的設定。
通訊端收到了緊急(頻外)資料。Go 在內部用它來中斷 goroutine。
超出了處理序的 CPU 時間限制(ulimit -t)。
超出了處理序允許的最大檔案大小(ulimit -f)。
虛擬計時器已到期,該計時器只計算處理序的 CPU 時間。
效能分析計時器已到期,供效能分析工具(profiler)使用。
終端機視窗的大小已變更;全螢幕程式用它來重新繪製畫面。
設定了 O_ASYNC 的描述子上有可用的 I/O。在 Linux 中,SIGPOLL 是同一個訊號。
相同值:SIGPOLL
電源故障,由不斷電系統(UPS)軟體通知 init 系統。
錯誤的系統呼叫。現今常見的原因是 seccomp 篩選器封鎖了該呼叫,例如在容器中。
模擬陷阱(EMT)。它存在於 macOS 與 BSD 中,但在 x86 或 ARM 上的 Linux 中不存在。
在 macOS 與 BSD 的終端機按 Ctrl+T 發出的資訊要求;許多命令會以顯示進度作為回應。
命令已順利完成。這是唯一代表成功的代碼:其他任何值都表示錯誤。
一般錯誤;其意義由各程式自行決定。詳細資訊通常在命令寫入 stderr 的內容中。grep 與 diff 賦予它另一種意義:「找不到相符的項目」或「檔案不同」。
shell 內建命令的用法錯誤,或指令碼有語法錯誤。許多程式也用它表示無效的選項,而 grep 則用它表示真正的錯誤。
命令的用法錯誤:缺少引數、引數過多或某個選項不正確。
輸入資料的格式不正確。
某個輸入檔案不存在或無法讀取。
指定的使用者不存在;主要由郵件程式使用。
主機名稱不存在。
所需的服務無法使用,或發生了無法歸入其他類別的錯誤。
程式內部錯誤。
作業系統錯誤,例如無法 fork 或建立管線。
缺少某個系統檔案(如 /etc/passwd),或該檔案有錯誤。
無法建立輸出檔案。
讀寫檔案時發生輸入/輸出錯誤。
暫時性失敗:建議稍後再試。郵件伺服器用它將郵件留在佇列中。
遠端系統的回應不符合協定。
權限不足,無法執行該操作。
設定有錯誤。
命令因超出指定的時間而被 timeout 命令終止。
docker run 本身在執行容器之前就失敗了,例如選項錯誤或常駐程式(daemon)發生錯誤。GNU timeout 在本身失敗時也會傳回此值。
檔案存在,但無法執行:缺少執行權限、是一個目錄,或是其他架構的二進位檔。在 Docker 中,表示容器的命令無法執行。
找不到命令:沒有安裝、不在 PATH 中,或名稱拼錯了。在指令碼中,缺少 #! 行的直譯器時也會出現;在 Docker 中,表示容器的命令不存在於映像檔中。
大於 128 的代碼表示處理序被訊號終止,但 128 不對應任何訊號。Git 將它用於所有嚴重錯誤(「fatal: …」),例如儲存庫不存在,或複製時驗證失敗。
結束碼超出範圍:exit -1 會變成 255,因為只保留 8 個位元。ssh 在連線或驗證失敗時也會傳回它,以便與遠端命令的結束碼區分。
Linux 的值是 x86、x86-64 與 ARM 上的值;Alpha、MIPS、SPARC 與 PA-RISC 對部分 errno 與訊號的編號不同。英文訊息是 glibc 中 strerror 與 strsignal 顯示的內容,macOS 的訊息不同時也會一併列出。大於 128 的結束碼會解讀為 128 加上訊號編號,這是 bash、Docker 與 Kubernetes 的慣例。
運作方式
在 Linux 中,系統呼叫失敗時會傳回 -1,並在 errno 變數中留下一個說明原因的數字:2 是 ENOENT,檔案不存在;13 是 EACCES,權限遭拒。strerror 會把這個數字轉換成畫面上看到的文字,例如「No such file or directory」。Python 會顯示為 [Errno 13],Node.js 顯示為 code: 'ECONNREFUSED',Go、Rust 或 Java 則顯示相同的文字。1 到 34 的編號來自最初的 Unix,在所有系統中都相同;之後的編號由各系統自行分配,因此 ECONNREFUSED 在 Linux 中是 111,在 macOS 中是 61。名稱可以跨平台,數字則不行。
訊號是核心或其他處理序傳送給某個處理序的通知:按下 Ctrl+C 時傳送 SIGINT,SIGTERM 要求它結束,SIGKILL 不經詢問直接終止它,存取無效記憶體時則會收到 SIGSEGV。每個訊號都有預設動作,而且幾乎都可以攔截以執行其他動作。當訊號終止處理序時,shell 會將結束碼回報為 128 加上訊號編號:137 是 SIGKILL(9),139 是 SIGSEGV(11),143 是 SIGTERM(15)。Docker 與 Kubernetes 也採用相同的慣例。
結束碼是程式結束時留下的數字:0 代表成功,其他任何值都代表錯誤。只保留 8 個位元,因此範圍是 0 到 255。慣例很少:126 與 127 由 shell 在無法執行或找不到命令時使用,64 到 78 由 BSD 的 sysexits.h 定義,其餘由各程式自行決定,例如 grep 在找不到任何內容時會傳回 1。
範例
Last State: Terminated · Reason: OOMKilled · Exit Code: 137137 = 128 + 9 · SIGKILL容器超出了記憶體限制,核心以 SIGKILL 將它終止。需要提高 resources.limits.memory 中的限制,或找出處理序為何耗用這麼多記憶體;重新啟動並不能解決問題。Error: connect ECONNREFUSED 127.0.0.1:5432ECONNREFUSED · Linux 111 · macOS 61 · Connection refusedNode.js 無法連線到 PostgreSQL,因為沒有程式在 5432 連接埠上接聽。如果應用程式在容器中執行,127.0.0.1 指的是容器本身而不是主機:應使用資料庫服務的名稱。OSError: [Errno 48] Address already in useEADDRINUSE · Linux 98 · macOS 4848 透露出程式是在 macOS 上執行:在 Linux 中同一個錯誤是 98。兩種情況都是另一個處理序已在使用該連接埠;lsof -i :連接埠 可以顯示是哪一個。使用情境
- 理解 Python、Node.js、Go 或 C 應用程式中只顯示 errno 編號或名稱的錯誤。
- 從結束碼找出 Docker 容器為何結束,或 Kubernetes Pod 為何重新啟動。
- 將 macOS 的 errno 編號轉換成正確的名稱,因為從 35 開始它與 Linux 的不一致。
- 解讀失敗的指令碼、cron 排程或 CI 工作的結束碼。
- 選擇要以 kill 傳送哪個訊號,並了解處理序不攔截它時會發生什麼事。
- 撰寫可跨平台的錯誤處理程式碼,以名稱而非數字進行比較。
常見問題
exit code 137(結束碼 137)代表什麼?
代表處理序被訊號 9,也就是 SIGKILL 終止(128 + 9)。最常見的原因是記憶體:容器超出了記憶體限制,Kubernetes 會將其回報為 OOMKilled;或是核心的 OOM killer 選中了該處理序,dmesg 中會留下「Out of memory: Killed process」。使用 docker kill,或處理序在收到 SIGTERM 後未在期限內結束時也會發生:docker stop 為 10 秒,Kubernetes 為 30 秒。
SIGTERM 與 SIGKILL 有什麼差別?
SIGTERM 要求處理序結束,處理序可以攔截它,以便關閉連線、儲存資料後再結束。SIGKILL 則由核心立即終止處理序,處理序完全無法因應。正確的做法是先傳送 SIGTERM,等待幾秒鐘,只有在處理序仍在執行時才使用 SIGKILL,systemd、docker stop 與 Kubernetes 正是這麼做的。
為什麼同一個 errno 在 macOS 中的編號不同?
因為 POSIX 只定義了名稱,沒有定義編號。1 到 34 的編號所有系統都沿襲自最初的 Unix;之後,BSD(macOS 源自它)與 System V(Linux 依循它)各自進行了編號。因此最好一律以名稱比較:在 Python 中用 errno.ECONNREFUSED,在 Node.js 中用 err.code,在 C 中用常數,而不是用數字。
EACCES 與 EPERM 有什麼差別?
EACCES(「Permission denied」)表示檔案或路徑中某個目錄的權限不允許,或被 ACL 或 SELinux 阻擋:可透過 chmod、chown 或對應的原則解決。EPERM(「Operation not permitted」)表示操作本身需要特殊權限,與檔案權限無關,例如變更檔案的擁有者或終止其他使用者的處理序:需要 root、某項 capability,或移除不可變更之類的屬性。
如何查看命令或容器的結束碼?
在 bash 與 zsh 中,echo $? 會顯示上一個命令的結束碼;在 PowerShell 中則是 $LASTEXITCODE。在 Docker 中,docker ps -a 會在 STATUS 欄顯示它,例如「Exited (137)」。在 Kubernetes 中,kubectl describe pod 會在「Last State: Terminated」中顯示它及原因,例如 OOMKilled 或 Error。