哪里退出状态圈套/回来后去了? [英] Where does the exit status go after trap/return?

查看:172
本文介绍了哪里退出状态圈套/回来后去了?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是用一个函数中陷阱 这个问题,并想出了这个问题,二次。鉴于以下code:

I was playing around with using trap inside a function because of this question, and came up with this secondary question. Given the following code:

d() {
    trap 'return' ERR
    false
    echo hi
}

如果我跑 D 陷阱导致shell从功能,无需打印'HI'回来。到现在为止还挺好。但是,如果我跑了第二遍,我从外壳得到一个消息:

If I run d, the trap causes the shell to return from the function without printing 'hi'. So far so good. But if I run it a second time, I get a message from the shell:

-bash:回报:可以从一个函数只'回报'或执行的脚本

-bash: return: can only `return' from a function or sourced script

起初,我以为这意味着ERR SIG发生了两次:一次,给了一个非零退出状态(在函数内),并再次当函数本身返回非零退出状态(函数之外的)。但这个假设不成立起来反对这个测试:

At first, I assumed this meant the ERR sig was happening twice: Once when false gave a nonzero exit status (inside the function) and again when the function itself returned with a nonzero exit status (outside the function). But that hypothesis doesn't hold up against this test:

e() {
    trap 'echo +;return' ERR
    false
    echo hi
}

如果我运行上面的,无论我怎么经常运行它,我不再获得的只能收益从函数或者执行的脚本从bash的警告。为什么外壳对待来自于陷阱一个简单的命令 ARG?

If I run the above, no matter how often I run it, I no longer get the can only return from a function or sourced script warning from bash. Why does the shell treat a compound command different from a simple command in a trap arg?

我的目标是保持引起函数退出命令的实际退出状态,但我认为无论是造成上述行为也使得捕捉退出状态复杂的:

My goal was to maintain the actual exit status of the command that caused the function to exit, but I think whatever is causing the above behavior also makes capturing the exit status complicated:

f() {
    trap '
        local s=$?
        echo $s
        return $s' ERR
    false
    echo hi
}

bash> f; echo $?
1
0

笏?是否有人可以解释为什么 $ S 扩展到这里两个不同的值,如果它原来是同一病因,之间的上述差异返回 +呼应;返回

Wat? Can someone please explain why $s expands to two different values here and, if it turns out to be the same cause, the above differentiation between return and echo +; return?

推荐答案

您第一个结论是正确的:在SIG ERR发生了两次

Your first conclusion was right: the ERR sig was happening twice.

D的第一个执行过程中,全局定义一个陷阱。这是否会影响下一个命令(D的当前呼叫不受影响)。
在D的第二次执行,你再定义一个陷阱(不是很有用),'假'的调用失败,所以我们执行由陷阱所定义的处理程序。然后我们回到在D也失败了父shell,所以我们再次执行的陷阱。

During the first execution of 'd', you define a trap globally. This affect next commands (the current call of d is not affected). During the second execution of 'd', you define a trap again (not very useful), the call of 'false' fails, so we execute the handler defined by the trap. Then we return in the parent shell where 'd' fails too, so we execute the trap again.

只是一个句话。 ERR可以作为'SIGSPEC的说法,但ERR不是一个信号;-)从BASH的手册:

Just a remark. ERR can be given as 'sigspec' argument, but ERR is not a signal ;-) From the manual of BASH:

If a sigspec is ERR, the command arg is executed whenever a sim‐
ple command has a non-zero exit status, subject to the following
conditions. [...]
These are  the  same  conditions obeyed by the errexit option.

随着功能的E,则ERR处理程序会执行成功的回响命令。这就是为什么E功能不会失败,这就是为什么在这种情况下,ERR处理程序未调用两次。

With the function 'e', the ERR handler executes the 'echo' command that succeeds. That's why the 'e' function doesn't fail, that's why the ERR handler is not called twice in this case.

如果您尝试E;回声$你会读0。

If you try "e; echo $?" you will read "0".

然后我想你'F'功能。我观察到同样的行为(我很惊讶)。原因是不会$ S的312104不好。如果你着急code的值,则应该遵守给予回报语句的参数时,它是由陷阱处理程序执行中被忽略。

Then I tried your 'f' function. I observed the same behavior (and I was surprised). The cause is NOT a bad expension of "$s". If you try to hardcode a value, you should observe the argument given to the 'return' statement is ignored when it is executed in by the trap handler.

我不知道这是否是一个正常的行为,或者如果它是BASH的一个bug ......或者,也许一招,以避免跨preTER一个无限循环: - )

I don't know if it is a normal behavior or if it's a bug of BASH... Or maybe a trick to avoid an infinite loop in the interpreter :-)

顺便说一句,这不是在我看来,一个良好的使用陷阱。我们可以通过创建一个子shell避免陷阱的副作用。在这种情况下,我们避免在父shell的错误,我们保持内部函数的退出code:

By the way, it's not a good use of trap in my opinion. We can avoid side effect of trap by creating a sub-shell. In this case we avoid the error in the parent shell and we keep the exitcode of the inner function:

g() {(
    trap 'return' ERR
    false
    echo hi
)}

这篇关于哪里退出状态圈套/回来后去了?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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