Cor*_*ein 73 kill signals exit exit-status
当一个进程被一个可处理的信号杀死时,例如SIGINTorSIGTERM但它不处理该信号,该进程的退出代码是什么?
对于无法处理的信号,例如SIGKILL?
据我所知,杀死进程SIGINT可能会导致退出代码130,但这会因内核或外壳实现而异吗?
$ cat myScript
#!/bin/bash
sleep 5
$ ./myScript
<ctrl-c here>
$ echo $?
130
Run Code Online (Sandbox Code Playgroud)
我不确定如何测试其他信号...
$ ./myScript &
$ killall myScript
$ echo $?
0 # duh, that's the exit code of killall
$ killall -9 myScript
$ echo $?
0 # same problem
Run Code Online (Sandbox Code Playgroud)
Sté*_*las 74
进程可以使用整数参数调用_exit()系统调用(在 Linux 上,另请参阅 参考资料exit_group())以向其父进程报告退出代码。虽然它是一个整数,但只有 8 个最低有效位可供父级使用(例外情况是在父级中的 SIGCHLD 上使用waitid()或 处理程序来检索该代码,但在 Linux 上则不然)。
父级通常会执行 await()或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
Run Code Online (Sandbox Code Playgroud)
类似 Bourne 的 shell 也会在自己的$?变量中设置上次运行命令的退出状态。但是,它不直接包含由 返回的数字waitpid(),而是对其进行了转换,并且在不同的shell 之间有所不同。
如果进程正常终止,所有 shell 之间的共同点是$?包含退出代码的最低 8 位(传递给 的数字exit())。
不同之处在于进程何时被信号终止。在所有情况下,这是 POSIX 所要求的,该数字将大于 128。POSIX 未指定该值可能是什么。但实际上,在我知道的所有 Bourne-like shell 中,最低 7 位$?将包含信号编号。但是,n信号号在哪里,
在 ash、zsh、pdksh、bash 中,Bourne shell$?是128 + n. 这意味着在这些 shell 中,如果你得到 a $?of 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
Run Code Online (Sandbox Code Playgroud)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.
Run Code Online (Sandbox Code Playgroud)
你甚至可以说有一个错误,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
Run Code Online (Sandbox Code Playgroud)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
Run Code Online (Sandbox Code Playgroud)要从 的值中获取信号$?,可移植的方法是使用kill -l:
$ /bin/kill 0
Terminated
$ kill -l "$?"
TERM
Run Code Online (Sandbox Code Playgroud)
(为了可移植性,你不应该使用信号编号,只使用信号名称)
在非伯恩战线上:
csh/tcsh并且fish与 Bourne shell 相同,除了状态是 in$status而不是$?(请注意,zsh还设置$status了与csh(除了$?)的兼容性)。rc:退出状态也是 in $status,但是当被信号杀死时,该变量包含信号的名称(例如sigterm或sigill+core如果生成了一个核心)而不是数字,这是该 shell 良好设计的又一个证明.es. 退出状态不是一个变量。如果你关心它,你可以运行命令:
status = <={cmd}
Run Code Online (Sandbox Code Playgroud)
这将返回一个数字sigterm或sigsegv+core类似的rc.
也许为了完整性,我们应该提到包含最后一个管道组件退出状态的zsh's$pipestatus和bash's$PIPESTATUS数组。
并且为了完整性,当涉及到 shell 函数和源文件时,默认情况下,函数返回上次命令运行的退出状态,但也可以使用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 的任何正整数,并为其中的任何数字返回错误。ksh93forreturn 0按原样return 320设置$?,但对于其他任何内容,请截断为 8 位。请注意,如前所述,返回 256 到 320 之间的数字可能会导致ksh退出时自杀。rc并es允许返回任何甚至列表。另请注意,某些 shell 还使用$?/ 的特殊值$status来报告一些不是进程退出状态的错误条件,例如127or 126for command not found或不可执行(或源文件中的语法错误)...
Gil*_*il' 34
当进程退出时,它会向操作系统返回一个整数值。在大多数 unix 变体上,该值取模 256:除低位之外的所有内容都被忽略。子进程的状态通过一个 16 位整数返回给它的父进程,其中
状态由wait系统调用或其同级之一返回。POSIX 没有指定退出状态和信号编号的确切编码;它只提供
严格来说,当进程被信号杀死时没有退出代码:取而代之的是退出状态。
在 shell 脚本中,命令的退出状态通过特殊变量 报告$?。此变量以一种模棱两可的方式对退出状态进行编码:
$?是其退出状态。$?在大多数系统上是 128 加上信号编号。$?在这种情况下,POSIX 只要求大于 128;ksh93 增加了 256 而不是 128。我从来没有见过一个 unix 变体除了向信号编号添加一个常数之外还做任何事情。因此,在 shell 脚本中,除了 ksh93 之外,您无法确切地判断命令是被信号杀死还是以大于 128 的状态代码退出。程序以大于 128 的状态代码退出的情况非常罕见,部分原因是程序员由于$?歧义而避免这种情况。
SIGINT 在大多数 unix 变体上是信号 2,因此$?对于被 SIGINT 杀死的进程来说是 128+2=130。你会看到 129 表示 SIGHUP,137 表示 SIGKILL,等等。
Ign*_*ams 12
这取决于你的外壳。从bash(1)手册页,SHELL GRAMMAR部分,Simple Commands小节:
一个的返回值简单的命令是[...] 128+ Ñ如果命令是通过信号终止Ñ。
由于SIGINT在您的系统上是 2 号信号,因此在 Bash 下运行时返回值为 130。
| 归档时间: |
|
| 查看次数: |
80803 次 |
| 最近记录: |