2 bash shell-script function exit exit-status
我知道在 shell 脚本中,“退出”通常意味着自愿或至少成功终止会话(或会话中的进程),并且有几种不同的退出模式;以下是我所知道的:
exit
命令如果我在第一个 shell 会话(shell-session 0)中,它通常会导致 shell CLI窗口关闭,但如果我在某个子会话(如 shell-session 1 或更高版本)中,执行通常只会将我的用户移回上一个会话(例如1 ? 0
)。
exit SOME_EXIT-CODE
命令我发现在这种退出中使用的三个主要退出代码:
exit 0
(成功)。exit 1
(一般错误,例如“除以零”和其他不允许的操作)。exit 2
(如在 Bash 4.xx 中 - 滥用 shell 内置函数,一个例子是空函数;myFunc() {}
)。我经常发现这些添加到命令序列的末尾作为其执行结果的指标;有时作为单元测试的一部分,例如:
domain="$1" && test -z "$domain" && exit 2
# Test if a user passes only one domain as a parameter, when executing this script
Run Code Online (Sandbox Code Playgroud)
如果我没记错的话,当 Bash 脚本结束运行时,它的“结束”实际上是常见的 *nix 术语中的“退出”——脚本本身是一个会话,用户从中退出回到 CLI 会话。这里也可能给出一些退出代码。
通常在 shell 脚本中,尤其是在 Bash 中,是否还有其他“退出模式”?
“退出”通常意味着自愿或至少成功终止
至少 POSIX 文本似乎仅将exit用于进程的自愿终止,而不是因外部原因而被终止。(参见例如wait()
)被信号杀死的进程几乎不算成功,因此任何成功的终止在这个意义上都必须是“退出”。尽管我希望这些术语在非正式使用中的使用不那么严格。
通常在 shell 脚本中,尤其是在 Bash 中,是否还有其他“退出模式”?
模式在某些上下文中具有特定的技术含义(例如chmod()
),但我在这里想不出一个含义,所以我不确定您要问的是什么。
在任何情况下,至少由于以下原因,shell 脚本可能会退出终止:
exit
内置命令。同样,退出状态是执行的最后一个命令的状态。exit
带有参数的命令。退出状态是参数的值。set -u
/set -o nounset
生效时,脚本引用了一个未设置的变量。退出状态取决于 shell,但不为零。(Bash 似乎使用127
.) (*)set -e
/set -o errexit
生效时失败。退出状态是失败命令的退出状态。(但有关. 的问题,请参阅BashFAQ 105。set -e
)1
.) (*)trap
内置命令在脚本中设置处理程序。这也适用于Ctrl-C发送SIGINT
信号的eq hit 。(*)从技术意义上讲,在情况 1 到 6 中,运行脚本的shell 进程自愿退出(即进程调用exit()
)。在另一方面,从该点脚本本身,终止因set -e
,set -u
或语法错误很可能被称为是非自愿的。但是shell脚本与shell解释器不同。
在 1 到 3 中,习惯是使用零退出状态表示成功完成,使用非零值表示失败。非零值的确切含义取决于效用。有些可能仅使用零和一,有些可能针对不同情况使用不同的非零状态。例如,grep
uses1
表示未找到匹配项,而值大于则1
表示错误。Bash 的内置函数还用于2
指示无效选项等错误。使用类似的自定义可能很有用,但您需要记录脚本的退出状态意味着什么。请注意,退出状态通常限制为 8 位,因此范围是从0
到255
。
在 4 到 6 中,情况通常被认为是某种失败,因此退出状态为非零。7、没有退出状态。相反,当进程因信号而终止时,wait()
系统调用会指示相关信号。如果父进程是一个shell,它通常用一个退出状态来表示它128 + <signal number>
,例如,143
对于一个以 终止的子进程SIGTERM
。
(* 与脚本不同,交互式 shell 不会因语法错误或set -u
或而退出SIGINT
。)
如果我在第一个 shell 会话中,它通常会导致 shell CLI 窗口关闭
如果它启动的进程退出,终端模拟器通常会关闭。但这取决于终端模拟器,而不是外壳的功能。终端仿真器可能会决定保持窗口打开以告诉用户他们的程序已终止,并且您也可以在终端仿真器中运行除 shell 之外的其他程序。
如果我在某个子会话中,执行通常只会将我的用户移回上一个会话。
如果您使用交互式 shell 启动另一个 shell,则父 shell 会在子 shell 终止时继续。但同样,这与 shell 无关,如果您启动编辑器或仅从交互式 shell 运行任何命令,也会发生同样的情况。当子进程终止时,父 shell 继续接受来自用户的命令。
Bash 确实保留了一个变量SHLVL
,每次 Bash 启动时都会增加一个,因此从某种意义上说,它确实具有嵌套 shell 的内部概念。但我不认为“子会话”这个词很常见,更不用说任何类型的编号了。(我认为SHLVL
初始化在1
.)