Linux 中退出碼的含義
退出碼(退出狀態(tài))可以告訴我們最后一次執(zhí)行的命令的狀態(tài)。在命令結(jié)束以后,我們可以知道命令是成功完成的還是以錯(cuò)誤結(jié)束的。
其基本思想是,程序返回退出代碼 0
時(shí)表示執(zhí)行成功,沒(méi)有問(wèn)題。代碼 1
或 0
以外的任何代碼都被視為不成功。
退出碼除了 0 和 1 外還有很多值,我將在本文介紹它們。
Linux Shell 中的各種退出碼
我們來(lái)快速了解一下 Linux Shell 中的主要退出碼:
退出碼 | 解釋 |
| 命令成功執(zhí)行 |
| 通用錯(cuò)誤代碼 |
| 命令(或參數(shù))使用不當(dāng) |
| 權(quán)限被拒絕(或)無(wú)法執(zhí)行 |
| 未找到命令,或 |
| 命令被信號(hào)從外部終止,或遇到致命錯(cuò)誤 |
| 通過(guò) |
| 通過(guò) |
| 退出碼超過(guò)了 0-255 的范圍,因此重新計(jì)算(LCTT 譯注:超過(guò) 255 后,用退出碼對(duì) 256 取模) |
??
130
(SIGINT
或^C
)和143
(SIGTERM
)等終止信號(hào)是非常典型的,它們屬于128+n
信號(hào),其中n
代表終止碼。
在簡(jiǎn)單了解了退出碼之后,我們來(lái)看看它們的用法。
獲取退出碼
前一個(gè)命令執(zhí)行的退出碼存儲(chǔ)在 特殊變量 $?
中。你可以通過(guò)運(yùn)行以下命令來(lái)獲取:
echo $?
我們?cè)谒醒菔局卸紝⑹褂盟鼇?lái)獲取退出代碼。
請(qǐng)注意,exit
命令支持以帶著前一條命令相同的退出碼退出。
退出碼 0
退出碼 0
表示命令執(zhí)行無(wú)誤,這是完成命令的理想狀態(tài)。
例如,我們運(yùn)行這樣一條基本命令
neofetch
echo $?
這個(gè)退出碼 0
表示特定命令已成功執(zhí)行,僅此而已。讓我們?cè)傺菔編讉€(gè)例子。
你可以嘗試 終止一個(gè)進(jìn)程;它也會(huì)返回代碼 0
。
pkill lxappearance
查看文件內(nèi)容也會(huì)返回退出碼 0,這僅意味著 cat
命令執(zhí)行成功。
退出碼 1
退出碼 1
也很常見(jiàn)。它通常表示命令以一般錯(cuò)誤結(jié)束。
例如,在沒(méi)有 sudo 權(quán)限的情況下使用 軟件包管理器,就會(huì)返回代碼 1
。在 Arch Linux 中,如果我運(yùn)行下面的命令:
pacman -Sy
它會(huì)返回 1
, 表示上一條命令運(yùn)行出錯(cuò)。
exit code 1 (impermissible operation resulted in this code)
?? 如果你在基于 Ubuntu 的發(fā)行版中嘗試這樣做(不使用
sudo
執(zhí)行apt update
),運(yùn)行后會(huì)得到錯(cuò)誤碼100
,表示你是在沒(méi)有權(quán)限的情況下運(yùn)行apt
。100
不是標(biāo)準(zhǔn)錯(cuò)誤碼,而是apt
特有的錯(cuò)誤碼。
雖然這是一般的理解,但我們也可以將其解釋為 “不被允許的操作”。
除以 0
等操作也會(huì)返回錯(cuò)誤碼 1
。
Division by zero results in code 1
退出碼 2
這個(gè)退出碼出現(xiàn)在當(dāng)執(zhí)行的命令有語(yǔ)法錯(cuò)誤時(shí)。濫用命令參數(shù)也會(huì)導(dǎo)致此錯(cuò)誤。
一般來(lái)說(shuō),它表示由于使用不當(dāng),命令無(wú)法執(zhí)行。
例如,我在一個(gè)本應(yīng)只有一個(gè)連字符的選項(xiàng)上添加了兩個(gè)連字符,那么此時(shí)會(huì)出現(xiàn)退出碼 2。
grep --z file.txt
Invalid argument resulted in exit code 2
當(dāng)權(quán)限被拒絕時(shí),比如訪問(wèn) /root
文件夾,就會(huì)出現(xiàn)錯(cuò)誤碼 2
。
Permission denied gives out code 2
退出碼 126
126 是一個(gè)特殊的退出碼,它用于表示命令或腳本因權(quán)限錯(cuò)誤而未被執(zhí)行。
當(dāng)你嘗試執(zhí)行沒(méi)有執(zhí)行權(quán)限的 Shell 腳本時(shí),就會(huì)出現(xiàn)這個(gè)錯(cuò)誤。
請(qǐng)注意,該退出碼只出現(xiàn)在沒(méi)有足夠權(quán)限的腳本或命令的“執(zhí)行”中,這與一般的權(quán)限被拒絕錯(cuò)誤不同。
因此,不要把它與你之前看到的退出碼為 2
的示例混淆。在那個(gè)示例中,運(yùn)行的是 ls
命令,權(quán)限問(wèn)題出自它試圖執(zhí)行的目錄。而本例中權(quán)限問(wèn)題來(lái)自腳本本身。
退出碼 127
這是另一個(gè)常見(jiàn)的退出碼。退出碼 127
指的是“未找到命令”。它通常發(fā)生在執(zhí)行的命令有錯(cuò)別字或所需的可執(zhí)行文件不在 $PATH
變量中時(shí)。
例如,當(dāng)我嘗試執(zhí)行一個(gè)不帶路徑的腳本時(shí),經(jīng)常會(huì)看到這個(gè)錯(cuò)誤。
Script executed without the path gives "command not found" or code 127
當(dāng)你想運(yùn)行的可執(zhí)行文件不在 $PATH
變量中時(shí),也會(huì)出現(xiàn)退出碼 127
。你可以通過(guò) 在 PATH 變量中添加命令的目錄 來(lái)糾正這種情況。
當(dāng)你輸入不存在的命令時(shí),也會(huì)得到這樣的退出碼。
Unmount is not a command, and Screenfetch is not installed, which resulted in code 127
退出碼 128+n 系列
當(dāng)應(yīng)用程序或命令因致命錯(cuò)誤而終止或執(zhí)行失敗時(shí),將產(chǎn)生 128 系列退出碼(128+n
),其中 n
為信號(hào)編號(hào)。
n
包括所有類(lèi)型的終止代碼,如 SIGTERM
、SIGKILL
等。
退出碼 130 或 SIGINT
在通過(guò)終止信號(hào) 2
或按下 Ctrl+C
中斷進(jìn)程時(shí),會(huì)發(fā)出 SIGINT
(鍵盤(pán)中斷信號(hào))。
因?yàn)榻K止信號(hào)是 2
,所以我們得到的退出碼是 130
(128+2)。下面的視頻演示了 lxappearance
的中斷信號(hào)。
退出碼 137 或 SIGKILL
SIGKILL
(立即終止信號(hào))表示終止信號(hào) 9
。這是終止應(yīng)用程序時(shí)最不應(yīng)該使用的方法。
因?yàn)榻K止信號(hào)為 9
,因此我們得到的退出代碼為 137
(128+9)。
退出碼 143 或 SIGTERM
SIGTERM
是進(jìn)程在未指定參數(shù)的情況下被殺死時(shí)的默認(rèn)行為。
SIGTERM
的終止信號(hào)為 15
,因此該信號(hào)的退出碼為 143
(128+15)。
還有一些你以前可能不知道的終止信號(hào),它們也有自己類(lèi)似的退出碼。你可以在這里查看它們:
?? 請(qǐng)注意,如果進(jìn)程在啟動(dòng)它的同一會(huì)話中終止,這些信號(hào)可能不會(huì)出現(xiàn)。如果要重現(xiàn)這些信號(hào),請(qǐng)從不同的 shell 終止。
就個(gè)人而言,信號(hào)
128
是無(wú)法重現(xiàn)的。
當(dāng)退出碼超過(guò)了 255 會(huì)怎樣?
最新版本的 Bash 甚至保留了超過(guò) 255 的原始退出碼的值,但一般來(lái)說(shuō),如果代碼超過(guò) 255,就會(huì)被重新計(jì)算。
也就是說(shuō),代碼 256
會(huì)變成 0
,257
會(huì)變成 1
,383
會(huì)變成 127
,以此類(lèi)推。為確保更好的兼容性,請(qǐng)將退出碼保持在 0
至 255
之間。
結(jié)語(yǔ)
希望你對(duì) Linux Shell 中的退出碼有所了解。在排查各種問(wèn)題時(shí),使用它們會(huì)非常方便。
如果你要在 Shell 腳本中使用這些代碼,請(qǐng)確保你了解每個(gè)代碼的含義,以便更容易地排除故障。
這就是本文的全部?jī)?nèi)容。