Bash:当子脚本捕获SIGINT时,为什么父脚本没有在SIGINT上终止? [英] Bash: Why does parent script not terminate on SIGINT when child script traps SIGINT?

查看:46
本文介绍了Bash:当子脚本捕获SIGINT时,为什么父脚本没有在SIGINT上终止?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

script1.sh:

script1.sh:

 #!/bin/bash    

./script2.sh
 echo after-script

script2.sh:

script2.sh:

#!/bin/bash

function handler {
  exit 130
}

trap handler SIGINT

while true; do true; done

当我从终端启动script1.sh,然后使用 Ctrl + C 将SIGINT发送到其进程组时,该信号被script2.sh和当script2.sh终止时,script1.sh打印脚本后".但是,我希望script1.sh在调用script2.sh的行之后立即终止.为什么在此示例中不是这种情况?

When I start script1.sh from a terminal, and then use Ctrl+C to send SIGINT to its process group, the signal is trapped by script2.sh and when script2.sh terminates, script1.sh prints "after-script". However, I would have expected script1.sh to immediately terminate after the line that invokes script2.sh. Why is this not the case in this example?

其他说明(编辑):

  • 由于script1.sh和script2.sh在同一个进程组中,因此当 Ctrl + C 时,SIGINT会同时发送到两个脚本中在命令行上按kbd>.这就是为什么我不希望script2.sh退出时继续script1.sh的原因.

  • As script1.sh and script2.sh are in the same process group, SIGINT gets sent to both scripts when Ctrl+C is pressed on the command line. That's why I wouldn't expect script1.sh to continue when script2.sh exits.

当script2.sh中的陷阱处理程序SIGINT"行被注释掉时,script1.sh确实在存在script2.sh之后立即退出.我想知道为什么它的行为会有所不同,因为script2.sh会生成与之相同的退出代码(130).

When the line "trap handler SIGINT" in script2.sh is commented out, script1.sh does exit immediately after script2.sh exists. I want to know why it behaves differently then, as script2.sh produces just the same exit code (130) then.

推荐答案

新答案:

这个问题比我最初怀疑的要有趣得多.答案基本上是在这里给出的:

This question is far more interesting than I originally suspected. The answer is essentially given here:

什么发送到包含子代的perl脚本时,SIGINT(^ C)发生了什么?

这是相关的花絮.我知道您没有使用Perl,但是我认为Bash使用的是C的约定.

Here's the relevant tidbit. I realize you're not using Perl, but I assume Bash is using C's convention.

Perl的内置系统功能与C系统一样工作(3)就信号而言,它来自标准C库的函数.如果您使用的是Perl版本的system()或管道打开或反引号,然后是父级-一种调用系统,而不是被调用者调用的系统它-在孩子们都在的时候会忽略任何SIGINT和SIGQUIT运行中.

Perl’s builtin system function works just like the C system(3) function from the standard C library as far as signals are concerned. If you are using Perl’s version of system() or pipe open or backticks, then the parent — the one calling system rather than the one called by it — will IGNORE any SIGINT and SIGQUIT while the children are running.

此解释是我所见过的关于可以选择的各种选择的最好方法被制造.它还说Bash采用了WCE方法.也就是说,当父进程接收到SIGINT时,它将等待直到其子进程返回.如果该处理从SIGINT退出,则它也以SIGINT退出.如果孩子退出任何其他方式,它将忽略SIGINT.

This explanation is the best I've seen about the various choices that can be made. It also says that Bash does the WCE approach. That is, when a parent process receives SIGINT, it waits until its child process returns. If that process handled exited from a SIGINT, it also exits with SIGINT. If the child exited any other way it ignores SIGINT.

还有一种方法可以使调用程序的shell可以判断是否被调用了.程序在SIGINT上退出,并且如果它忽略了SIGINT(或将其用于其他目的).就像WUE一样,shell等待孩子完全的.它可以判断程序是否在SIGINT上终止,以及是否因此,它将终止脚本.如果程序执行了其他任何退出操作,脚本将继续.我将做事的方式称为本文的其余部分为"WCE"(用于等待和合作出口").

There is also a way that the calling shell can tell whether the called program exited on SIGINT and if it ignored SIGINT (or used it for other purposes). As in the WUE way, the shell waits for the child to complete. It figures whether the program was ended on SIGINT and if so, it discontinue the script. If the program did any other exit, the script will be continued. I will call the way of doing things the "WCE" (for "wait and cooperative exit") for the rest of this document.

我在Bash手册页中找不到对此的引用,但是我将继续在信息文档中查找.但是我99%的人相信这是正确的答案.

I can't find a reference to this in the Bash man page, but I'll keep looking in the info docs. But I'm 99% confident this is the correct answer.

旧答案:

Bash脚本中命令的非零退出状态不会终止程序.如果在 ./script2.sh 之后执行 echo $?,它将显示130.您可以使用 set -e 作为终止脚本.phs建议.

A nonzero exit status from a command in a Bash script does not terminate the program. If you do an echo $? after ./script2.sh it will show 130. You can terminate the script by using set -e as phs suggests.

$ help set
...
-e  Exit immediately if a command exits with a non-zero status.

这篇关于Bash:当子脚本捕获SIGINT时,为什么父脚本没有在SIGINT上终止?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆