进程可以使用整数参数调用_exit()
系统调用(在Linux上,另请参见exit_group()
),以向其父项报告退出代码。尽管是整数,但父级仅可使用8个最低有效位(这是在父级中对SIGCHLD 使用waitid()
或处理程序以检索该代码时的例外,但在Linux上则除外)。
父级通常会做一个wait()
或waitpid()
以获得其孩子的状态为整数(尽管waitid()
也可以使用略有不同的语义)。
在Linux和大多数Unices上,如果进程正常终止,则该状态编号的8至15位将包含传递给的退出代码exit()
。如果不是,则7个最低有效位(0至6)将包含信号编号,如果转储内核,则将设置7位。
perl
的$?
例如含有如通过设置数字waitpid()
:
$ perl -e 'system q(kill $$); printf "%04x\n", $?'
000f # killed by signal 15
$ perl -e 'system q(kill -ILL $$); printf "%04x\n", $?'
0084 # killed by signal 4 and core dumped
$ perl -e 'system q(exit $((0xabc))); printf "%04x\n", $?'
bc00 # terminated normally, 0xbc the lowest 8 bits of the status
类似Bourne的shell也会在其自己的$?
变量中使最后一个运行命令的退出状态。但是,它不直接包含所返回的数字waitpid()
,而是对其的转换,并且外壳之间的区别是不同的。
所有shell之间的共同点是,如果进程正常终止,则$?
包含退出代码的最低8位(传递给的数字exit()
)。
不同之处在于该过程由信号终止。在所有情况下,POSIX都需要该数字,该数字将大于128。POSIX没有指定该值可能是多少。但实际上,在我所知道的所有类似Bourne的外壳中,最低的7位$?
将包含信号编号。但是,n
信号号在哪里
在ash,zsh,pdksh,bash,Bourne shell中$?
是128 + n
。这意味着在这些shell中,如果获得$?
的129
,则您不知道是因为进程退出了exit(129)
还是被信号杀死1
(HUP
在大多数系统上)。但是基本原理是,当shell退出自身时,它们默认情况下会返回最后退出的命令的退出状态。通过确保$?
绝对不大于255,可以保持一致的退出状态:
$ bash -c 'sh -c "kill \$\$"; printf "%x\n" "$?"'
bash: line 1: 16720 Terminated sh -c "kill \$\$"
8f # 128 + 15
$ bash -c 'sh -c "kill \$\$"; exit'; printf '%x\n' "$?"
bash: line 1: 16726 Terminated sh -c "kill \$\$"
8f # here that 0x8f is from a exit(143) done by bash. Though it's
# not from a killed process, that does tell us that probably
# something was killed by a SIGTERM
ksh93
,$?
是256 + n
。这意味着从$?
您的价值可以区分已终止和未终止的过程。较新版本的ksh
,如果退出$?
时大于255 ,则会使用相同的信号杀死自己,以便能够向其父节点报告相同的退出状态。虽然这听起来像是一个好主意,但这意味着ksh
如果该进程被产生核心的信号杀死,则会产生一个额外的核心转储(可能会覆盖另一个):
$ ksh -c 'sh -c "kill \$\$"; printf "%x\n" "$?"'
ksh: 16828: Terminated
10f # 256 + 15
$ ksh -c 'sh -c "kill -ILL \$\$"; exit'; printf '%x\n' "$?"
ksh: 16816: Illegal instruction(coredump)
Illegal instruction(coredump)
104 # 256 + 15, ksh did indeed kill itself so as to report the same
# exit status as sh. Older versions of `ksh93` would have returned
# 4 instead.
您甚至可以说存在一个错误,ksh93
即使$?
它来自return 257
某个函数的完成,也会杀死自己:
$ ksh -c 'f() { return "$1"; }; f 257; exit'
zsh: hangup ksh -c 'f() { return "$1"; }; f 257; exit'
# ksh kills itself with a SIGHUP so as to report a 257 exit status
# to its parent
yash
。yash
提供一个折衷方案。它返回256 + 128 + n
。这意味着我们还可以区分被终止的进程和正确终止的进程。并且在退出时,它将报告128 + n
而不必自杀本身及其可能产生的副作用。
$ yash -c 'sh -c "kill \$\$"; printf "%x\n" "$?"'
18f # 256 + 128 + 15
$ yash -c 'sh -c "kill \$\$"; exit'; printf '%x\n' "$?"
8f # that's from a exit(143), yash was not killed
要从的值获取信号$?
,可移植的方法是使用kill -l
:
$ /bin/kill 0
Terminated
$ kill -l "$?"
TERM
(出于可移植性,您永远不要使用信号编号,而只能使用信号名称)
在非伯恩方面:
也许对于完整性,我们应该提到zsh
的$pipestatus
和bash
的$PIPESTATUS
包含最后一个流水线的组件的退出状态阵列。
而且为了完整性,在涉及外壳函数和源文件时,默认情况下,函数以上次运行命令的退出状态返回,但也可以使用return
内置函数显式设置返回状态。我们在这里看到一些区别:
bash
和mksh
(因为R41,回归^ Wchange显然有意引入的)将截断号(正或负),以8位。例如,return 1234
将设置$?
为210
,return -- -1
将设置$?
为255。
zsh
和pdksh
(以及以外的派生mksh
)允许任何有符号的32位十进制整数(-2 31至2 31 -1)(并将数字截断为32位)。
ash
并yash
允许使用0到2 31 -1之间的任何正整数,并返回一个错误。
ksh93
用于return 0
按原样return 320
设置$?
,但对于其他任何内容,请截断为8位。如前所述,请注意,返回256到320之间的数字可能会导致ksh
退出时自杀。
rc
并es
允许返回任何东西甚至列表。
还要注意,某些外壳程序还使用$?
/的特殊值$status
来报告不是进程退出状态的某些错误情况,例如127
或126
对于未找到或无法执行的命令(或源文件中的语法错误)...
killall myScript
作品,因此killall(而不是脚本!)的返回值为0。您可以放置kill -x $$
[x是信号编号,而$$通常由外壳扩展为该脚本的PID(在sh,bash, ...)] 在脚本中,然后测试其退出核心是什么。