Ant*_*gan 19 bash shell-script exit
我最近从高级 Bash 脚本指南中看到了这个具有特殊含义的退出代码列表。他们将这些代码称为保留代码,并建议:
根据上表,退出代码 1-2、126-165 和 255 具有特殊含义,因此应避免用于用户指定的退出参数。
不久前,我写了一个脚本,它使用了以下退出状态代码:
当我编写脚本时,我不知道任何特殊的退出代码,所以我只是从第一个错误条件的 1 开始,并为每个连续的错误类型增加退出状态。
我编写脚本的目的是在稍后阶段它可以被其他脚本调用(可以检查非零退出代码)。我实际上还没有这样做;到目前为止,我只从我的交互式 shell (Bash) 运行脚本,我想知道使用我的自定义退出代码会导致什么/是否有任何问题。Advanced Bash-Scripting Guide 中的建议的相关性/重要性如何?
我在 Bash 文档中找不到任何确凿的建议;它关于退出状态的部分只列出了 Bash 使用的退出代码,但没有说明任何这些都是保留的或警告不要将它们用于您自己的脚本/程序。
sch*_*ily 13
没有退出代码具有特殊含义,但 in 值$?可能具有特殊含义。
Bourne Shell 和 ksh93 处理和转发退出代码和错误情况到 shell 变量的方式$?是问题所在。与您列出的相反,只有以下值$?具有特殊含义:
此外,还有一个未指定的 shell 和特定于平台的$?代码范围> 128,为被信号中断的程序保留:
其他值不会产生问题,因为它们可能与 shell 特殊$?值不同。
特别是,值 1 和 2 不用于特殊条件,而只是内置命令使用的退出代码,当它们不是内置命令时,它们的作用相同。因此,您提供的bash 脚本指南的指针似乎不是一本好的手册,因为它只列出了 bash 使用的代码,而没有评论特定代码是否是应避免用于自己的脚本的特殊值。
较新版本的 Bourne Shell 使用waitid()而不是waitpid()等待程序退出,并且waitid()(1989 年为 SVr4 引入)使用更好的系统调用接口(类似于 UNOS 在 1980 年使用的接口)。
当较新的Bourne Shell的版本编码退出原因在一个单独的变量${.sh.code}/${.sh.codename}比退出代码即在${.sh.status}/ ${.sh.termsig},请参阅http://schillix.sourceforge.net/man/man1/bosh.1.html,退出代码没有过载具有特殊状态,并且由于使用了`waitid(),Bourne Shell 现在支持返回退出代码的所有 32 位——而不仅仅是低 8 位。
顺便说一句:注意不要在exit(256)C 程序或 shell 脚本中使用或类似,因为这会导致在$?经典 shell中被解释为 0。
zwo*_*wol 12
已经多次尝试标准化进程退出代码的含义。除了你提到的那个,我还知道:
BSDsysexits.h定义了从 64 开始的值的含义。
grep退出代码 0 表示至少找到一个匹配项的GNU文档,1 表示没有找到匹配项,2 表示发生了 I/O 错误;这个约定显然对其他程序也很有用,因为“没有出错,但我什么也没找到”和“发生 I/O 错误”之间的区别是有意义的。
C 库函数的许多实现system使用退出代码 127 来指示程序不存在或无法启动。
在 Windows 上,NTSTATUS代码(不方便地分散在 32 位数字空间中)可用作退出代码,特别是那些表明进程因灾难性不当行为(例如STATUS_STACK_OVERFLOW)而终止的代码。
您不能指望任何给定的程序遵守这些约定中的任何特定约定。唯一可靠的规则是退出代码 0 是成功,其他任何事情都是某种失败。(需要注意的是C89的EXIT_SUCCESS是没有保证的值为零;但是,exit(0)需要相同的行为来exit(EXIT_SUCCESS)。即使值是不一样的)
对于 shell 脚本,我有时会在源代码中sysexist.h使用 shell 保留的退出代码(以 为前缀S_EX_),我将其命名为exit.sh
它基本上是:
EX_OK=0 # successful termination
EX__BASE=64 # base value for error messages
EX_USAGE=64 # command line usage error
EX_DATAERR=65 # data format error
EX_NOINPUT=66 # cannot open input
EX_NOUSER=67 # addressee unknown
EX_NOHOST=68 # host name unknown
EX_UNAVAILABLE=69 # service unavailable
EX_SOFTWARE=70 # internal software error
EX_OSERR=71 # system error (e.g., can't fork)
EX_OSFILE=72 # critical OS file missing
EX_CANTCREAT=73 # can't create (user) output file
EX_IOERR=74 # input/output error
EX_TEMPFAIL=75 # temp failure; user is invited to retry
EX_PROTOCOL=76 # remote error in protocol
EX_NOPERM=77 # permission denied
EX_CONFIG=78 # configuration error
EX__MAX=78 # maximum listed value
#System errors
S_EX_ANY=1 #Catchall for general errors
S_EX_SH=2 #Misuse of shell builtins (according to Bash documentation); seldom seen
S_EX_EXEC=126 #Command invoked cannot execute Permission problem or command is not an executable
S_EX_NOENT=127 #"command not found" illegal_command Possible problem with $PATH or a typo
S_EX_INVAL=128 #Invalid argument to exit exit 3.14159 exit takes only integer args in the range 0 - 255 (see first footnote)
#128+n Fatal error signal "n" kill -9 $PPID of script $? returns 137 (128 + 9)
#255* Exit status out of range exit -1 exit takes only integer args in the range 0 - 255
S_EX_HUP=129
S_EX_INT=130
#...
Run Code Online (Sandbox Code Playgroud)
并且可以通过以下方式生成:
#!/bin/sh
src=/usr/include/sysexits.h
echo "# Generated from \"$src\""
echo "# Please inspect the source file for more detailed descriptions"
echo
< "$src" sed -rn 's/^#define *(\w+)\s*(\d*)/\1=\2/p'| sed 's:/\*:#:; s:\*/::'
cat<<'EOF'
#System errors
S_EX_ANY=1 #Catchall for general errors
S_EX_SH=2 #Misuse of shell builtins (according to Bash documentation); seldom seen
S_EX_EXEC=126 #Command invoked cannot execute Permission problem or command is not an executable
S_EX_NOENT=127 #"command not found" illegal_command Possible problem with $PATH or a typo
S_EX_INVAL=128 #Invalid argument to exit exit 3.14159 exit takes only integer args in the range 0 - 255 (see first footnote)
#128+n Fatal error signal "n" kill -9 $PPID of script $? returns 137 (128 + 9)
#255* Exit status out of range exit -1 exit takes only integer args in the range 0 - 255
EOF
$(which kill) -l |tr ' ' '\n'| awk '{ printf "S_EX_%s=%s\n", $0, 128+NR; }'
Run Code Online (Sandbox Code Playgroud)
不过,我并不经常使用它,但我确实使用了一个 shell 函数,它将错误代码转换为它们的字符串格式。我给它起了名字exit2str。假设您已命名上述exit.shgenerator exit.sh.sh,则exit2str可以使用 ( exit2str.sh.sh)生成代码:
#!/bin/sh
echo '
exit2str(){
case "$1" in'
./exit.sh.sh | sed -nEe's|^(S_)?EX_(([^_=]+_?)+)=([0-9]+).*|\4) echo "\1\2";;|p'
echo "
esac
}"
Run Code Online (Sandbox Code Playgroud)
我在PS1我的交互式 shell 中使用它,以便在我运行每个命令之后,我可以看到它的退出状态和它的字符串形式(如果它确实有一个已知的字符串形式):
[15:58] pjump@laptop:~
(0=OK)$
[15:59] pjump@laptop:~
(0=OK)$ fdsaf
fdsaf: command not found
[15:59] pjump@laptop:~
(127=S_NOENT)$ sleep
sleep: missing operand
Try 'sleep --help' for more information.
[15:59] pjump@laptop:~
(1=S_ANY)$ sleep 100
^C
[15:59] pjump@laptop:~
(130=S_INT)$ sleep 100
^Z
[1]+ Stopped sleep 100
[15:59] pjump@laptop:~
(148=S_TSTP)$
Run Code Online (Sandbox Code Playgroud)
要获得这些,您需要为 exit2str 函数提供一个资源:
$ ./exit2str.sh.sh > exit2str.sh #Place this somewhere in your PATH
Run Code Online (Sandbox Code Playgroud)
然后在您的~/.bashrc每个命令提示符中使用它来保存和翻译退出代码,并将其显示在您的提示符 ( PS1) 中:
# ...
. exit2str.sh
PROMPT_COMMAND='lastStatus=$(st="$?"; echo -n "$st"; str=$(exit2str "$st") && echo "=$str"); # ...'
PS1="$PS1"'\n($lastStatus)\$'
# ...
Run Code Online (Sandbox Code Playgroud)
这对于观察一些程序如何遵循退出代码约定而有些不遵循、了解退出代码约定或只是为了能够更容易地看到正在发生的事情非常方便。使用它一段时间后,我可以说许多面向系统的 shell 脚本确实遵循约定。EX_USAGE特别是比较常见,虽然其他代码不多。我不时尝试遵循惯例,尽管总是有$S_EX_ANY(1) 适合懒惰的人(我就是其中之一)。
我能找到的最好的参考是这样的:http : //tldp.org/LDP/abs/html/exitcodes.html
根据这个:
1 是一个通用的错误集合,我一直看到它用于用户定义的错误。
2 用于滥用 shell 内置函数,例如语法错误
要直接回答您的问题,您的脚本可以使用保留的错误代码正常运行,假设您根据错误代码 = 1/2/3 处理错误,它将按预期运行。
但是,如果您遇到任何知道并使用保留错误代码的人,这可能会令人困惑,这似乎很少见。
另一个可用的选项是如果有错误则回显错误然后退出,假设您的脚本遵循 Linux 约定“没有消息就是好消息”并且回显成功则无。
if [ $? -ne 0 ];then
echo "Error type"
exit 1
fi
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6623 次 |
| 最近记录: |