bash: error handling and functions
我尝试在循环中调用一个函数,并在函数抛出时优雅地处理并继续。
如果我省略了
如果我把
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #!/bin/bash set -e things=(foo bar) function do_something { echo"param: $1" # just throw on first loop run # this statement is just a way to selectively throw # not part of a real use case scenario where the command(s) # may or may not throw if [[ $1 =="foo" ]]; then throw_error fi # this line should not be executed when $1 is"foo" echo"$1 is fine." } function handle_error { echo"$1 failed." } for thing in ${things[@]}; do do_something $thing || handle_error $thing done echo"done" |
产量
1 2 3 4 5 6 | param: foo ./test.sh: line 12: throw_error: command not found foo is fine. param: bar bar is fine. done |
我想要的是
1 2 3 4 5 6 | param: foo ./test.sh: line 12: throw_error: command not found foo failed. param: bar bar is fine. done |
编辑:
编辑:
不允许触摸
我找到的解决方案是将函数保存在单独的文件中,并在子shell中执行它。缺点是我们失去了所有的本地人。
做某事
1 2 3 4 5 6 7 8 9 10 11 | #!/bin/bash set -e echo"param: $1" if [[ $1 =="foo" ]]; then throw_error fi echo"$1 is fine." |
MSY脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #!/bin/bash set -e things=(foo bar) function handle_error { echo"$1 failed." } for thing in"${things[@]}"; do ./do-something.sh"$thing" || handle_error"$thing" done echo"done" |
产量
1 2 3 4 5 6 | param: foo ./do-something.sh: line 8: throw_error: command not found foo failed. param: bar bar is fine. done |
如果有更优雅的方式,我会把它标为正确答案。将在48小时后再次登记。
编辑
多亏了@petercordes的评论和这个其他答案,我找到了另一个不需要单独文件的解决方案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #!/bin/bash set -e things=(foo bar) function do_something { echo"param: $1" if [[ $1 =="foo" ]]; then throw_error fi echo"$1 is fine." } function handle_error { echo"$1 failed with code: $2" } for thing in"${things[@]}"; do set +e; (set -e; do_something"$thing"); error=$?; set -e ((error)) && handle_error"$thing" $error done echo"done" |
正确的产量
1 2 3 4 5 6 | param: foo ./test.sh: line 11: throw_error: command not found foo failed with code: 127 param: bar bar is fine. done |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #!/bin/bash set -e things=(foo bar) function do_something() { echo"param: $1" ret_value=0 if [[ $1 =="foo" ]]; then ret_value=1 elif [[ $1 =="fred" ]]; then ret_value=2 fi echo"$1 is fine." return $ret_value } function handle_error() { echo"$1 failed." } for thing in ${things[@]}; do do_something $thing || handle_error $thing done echo"done" |
解释见我上面的评论。如果不创建返回值,就不能测试返回值,这应该是比较明显的。和测试返回值,基本上是一个大于0的值。类似于0的测试。我认为这或多或少是对的。我相信bash返回值限制是254?我想说。必须是0到254之间的整数。不能是字符串、浮点数等。
http://tldp.org/ldp/abs/html/complexfunct.html
Functions return a value, called an exit status. This is analogous to
the exit status returned by a command. The exit status may be
explicitly specified by a return statement, otherwise it is the exit
status of the last command in the function (0 if successful, and a
non-zero error code if not). This exit status may be used in the
script by referencing it as $?. This mechanism effectively permits
script functions to have a"return value" similar to C functions.
所以实际上,foo会返回一个127命令未找到错误。我想。我得测试一下才能确定。
[更新]不,echo是最后一个命令,从输出中可以看到。最后一个回声的结果是0,所以函数返回0。所以你想抛弃这个概念,去做类似陷阱的事情,那是假设你不能触及函数的内部,这很奇怪。
1 2 3 | echo fred; echo reval: $? fred reval: 0 |
在bash脚本中set-e是什么意思?
1 | -e Exit immediately if a command exits with a non-zero status. |
But it's not very reliable and considered as a bad practice, better use :
1 | trap 'do_something' ERR |
http://tldp.org/ldp/bash-beginners-guide/html/sect_12_02.html请参阅trap,这可以满足您的需要。但不是,除非添加退货。
尝试
1 2 3 | if [["$1" =="foo" ]]; then foo fi |
我想知道它是否试图在条件测试中执行命令
从bash引用:
-e
Exit immediately if a pipeline (see Pipelines), which may consist of a single simple command (see Simple Commands), a list (see Lists),
or a compound command (see Compound Commands) returns a non-zero
status. The shell does not exit if the command that fails is part of
the command list immediately following a while or until keyword, part
of the test in an if statement, part of any command executed in a &&
or || list except the command following the final && or ||, any
command in a pipeline but the last, or if the command’s return status
is being inverted with !.
如您所见,如果错误发生在测试条件中,那么脚本将继续忽略并返回0。
——
编辑因此,作为回应,我注意到文档继续:
If a compound command other than a subshell returns a non-zero status
because a command failed while -e was being ignored, the shell does
not exit.
好吧,因为你的