Bash陷阱未在from循环调用的函数中调用

时间:2019-04-11 17:30:39

标签: bash function trap

在循环内部调用的函数中调用的陷阱不会被调用。如果直接在循环体内调用陷阱,则按预期方式工作。如果在循环外调用相同的函数,则会调用陷阱。

#!/bin/bash

function error_handler() #---------------------
{
    echo "ERROR STATUS: $?"
    echo "ERROR COMMAND: $BASH_COMMAND"
    echo "ERROR STACK:"
    caller
    echo "---------- end of stack dump ----------"
    exit 1
}

function func()
{
    echo "..inside func( $1)"
    if false
    then
        true
        rv=0
    else
        false
        rv=1
    fi
    echo "..returning from func( $1), rv=$rv"
    return $rv
}

set -o errtrace -o errexit
trap error_handler ERR

for N in 1 2 ; do

    echo -e "\nbegin loop $N"
    if func $N
    then
        echo "result of func($N): success"
    else
        echo "result of func($N): failed"
    fi
    echo "loop $N is done"
    false

done

func 1
func 2

上面的实际结果运行脚本:

begin loop 1
..inside func( 1)
..returning from func( 1), rv=1
result of func(1): failed
loop 1 is done
ERROR STATUS: 1
ERROR COMMAND: false
ERROR STACK:
41 ./a.sh
---------- end of stack dump ----------

但是我希望在程序结束时从false内的func()行捕获陷阱,而不是false。 让我们在最后注释掉false。结果是:

begin loop 1
..inside func( 1)
..returning from func( 1), rv=1
result of func(1): failed
loop 1 is done

begin loop 2
..inside func( 2)
..returning from func( 2), rv=1
result of func(2): failed
loop 2 is done
..inside func( 1)
ERROR STATUS: 1
ERROR COMMAND: false
ERROR STACK:
21 ./a.sh
---------- end of stack dump ----------

现在在func()内部调用了陷阱,但没有在循环1中调用!循环1和循环2均完成而没有陷阱。函数返回后是func 1,它调用了陷阱。为时已晚。

为什么?

1 个答案:

答案 0 :(得分:2)

罪魁祸首不是循环,而是这里的if语句:

if func $N

当您在func语句的测试中使用if时,ERR陷阱将在测试的整个过程中被挂起。在func()内部发生的错误不会触发ERR陷阱,也不会在启用errexit的情况下导致外壳退出。

引用bash man page

  

如果失败的命令是紧随ERRwhile关键字之后的命令列表的一部分,则不执行until陷阱,{{ 1}}语句,是在if&&列表中执行的命令的一部分,但最后一个||&&之后的命令除外,除了最后一个管道之外,或者使用||反转命令的返回值。这些是!errexit)选项所遵循的相同条件。