script1.sh:
#!/bin/bash ./script2.sh echo after-script
script2.sh:
#!/bin/bash function handler { exit 130 } trap handler SIGINT while true; do true; done
当我从terminal启动script1.sh,然后使用Ctrl + C向其进程组发送SIGINT时,信号被script2.sh捕获,当script2.sh终止时,script1.sh打印“after-script”。 不过,我希望script1.sh在调用script2.sh的行之后立即终止。 为什么在这个例子中不是这种情况?
补充说明(编辑):
在Python中检测64位操作系统(Windows)
如何从.NET应用程序启动`powercfg.exe -energy`?
fork()的function
从32位wix脚本注册64位com组件
由于script1.sh和script2.sh在同一个进程组中,因此在命令行上按Ctrl + C时,SIGINT将发送到两个脚本。 这就是为什么当script2.sh退出时,我不希望script1.sh继续。
当script2.sh中的“trap handler SIGINT”行被注释掉时,script2.sh会在script2.sh存在后立即退出。 我想知道为什么它的行为有所不同,因为script2.sh然后生成相同的退出代码(130)。
如何将字节数组发送到C ++中的另一个进程
我可以等待一个不是当前shellterminal的subprocess的进程终止吗?
debuggingLinux进程挂起问题的实用程序?
将一个长整型投射到void *
想学习大会,困惑从哪里开始
新答案:
这个问题比我原先怀疑的要有趣得多。 答案基本上是在这里给出的:
发送给包含子项的perl脚本时,SIGINT(^ C)会发生什么情况?
这里有相关的珍闻。 我意识到你不使用Perl,但我认为Bash使用C的约定。
对于信号而言,Perl的内置系统函数就像标准C库中的C系统(3)函数一样工作。 如果你正在使用Perl的system()版本或者管道打开或反引号,那么父 – 一个调用系统而不是它所调用的那个 – 会在孩子运行时忽略任何SIGINT和SIGQUIT。
这个解释是我见过的关于可以做出的各种选择的最好的解释 。 它也说Bash是WCE的方法。 也就是说,当一个父进程收到SIGINT时,它会等到它的子进程返回。 如果该进程处理从SIGINT退出,它也退出与SIGINT。 如果孩子以任何其他方式退出,则忽略SIGINT。
调用shell还可以判断被调用的程序是否在SIGINT上退出,以及是否忽略了SIGINT(或用于其他目的)。 正如在WUE的方式,壳等待孩子完成。 它计算出程序是否以SIGINT结束,如果是,则停止脚本。 如果该程序做了其他任何退出,脚本将继续。 我将为本文的其余部分打电话做“WCE”(“等待合作退出”)的方式。
我在Bash手册页找不到对此的引用,但我会继续查看信息文档。 但我99%相信这是正确的答案。
老答案:
来自Bash脚本命令的非零退出状态不会终止程序。 如果你做一个echo $? 在./script2.sh之后它将显示130.你可以通过使用set -e来终止脚本。
$ help set ... -e Exit immediately if a command exits with a non-zero status.
@ seanmcl的更新回答的第二部分是正确的,并且http://www.cons.org/cracauer/sigint.html的链接是一个非常好的通过仔细阅读。
从这个链接中, 即使你查到你的系统的数值 , 你也不能通过一个具有特殊数值的退出(3)来“伪造”正确的退出状态 。 实际上,这就是@Hermann Speiche的script2.sh中的尝试。
一个答案是修改script2.sh中的函数处理程序,如下所示:
function handler { # ... do stuff ... trap INT kill -2 $$ }
这有效地消除了信号处理程序,并“重新引发”了SIGINT,导致bash进程退出并显示相应的标志,使得其父进程正确处理最初发送给它的SIGINT。 这样,使用set -e或任何其他黑客实际上是不需要的。
还值得一提的是,如果你发送一个SIGINT(不符合“如何成为一个正确的程序”在上面的链接,例如它退出一个正常的返回代码)的行为不正确的可执行文件,单向解决这个问题的方法是使用如下脚本来封装对该进程的调用:
#!/bin/bash function handler { trap INT kill -2 $$ } trap handler INT badprocess "$@"
原因是你的script1.sh不会终止是script2.sh在一个子shell中运行。 要使前脚本退出,您可以按照phs和seanmcl的建议设置-e ,或者强制script2.sh在同一个shell中运行:
. ./script2.sh
在你的第一个脚本。 如果您在执行脚本之前先set -x ,那么您正在观察的内容会很明显。 help set讲述:
-x Print commands and their arguments as they are executed.
您也可以让第二个脚本通过SIGHUP或其他安全可用的信号(如父脚本可能考虑或陷入的SIGQUIT)发送终止信号(发送SIGINT不起作用)。
script1.sh:
#!/bin/bash trap 'exit 0' SIQUIT ## We Could also just accept SIGHUP if we like without traps but that sends a message to the screen. ./script2.sh ## or "bash script.sh" or "( . ./script.sh; ) which would run it on another process echo after-script
script2.sh:
#!/bin/bash SLEEPPID='' PID=$BASHPID read PPID_ < <(exec ps -p "$PID" -o "$ppid=") function handler { [[ -n $SLEEPPID ]] && kill -s SIGTERM "$SLEEPPID" &>/dev/null kill -s SIGQUIT "$PPID_" exit 130 } trap handler SIGINT # better do some sleeping: for (( ;; )); do [[ -n $SLEEPPID ]] && kill -s 0 "$SLEEPPID" &>/dev/null || { sleep 20 & SLEEPPID=$! } wait done
你脚本中原来的最后一行也可以像这样,取决于你的脚本实现。
./script2.sh || exit ...
要么
./script2.sh [[ $? -eq 130 ]] && exit ...
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。