shell中catch使用

# 语法

  • { } && { }这种情况下,只有左边成功执行了,右边的shell才会执行。
  • { } || { }这种情况,左边shell脚本执行失败,右边才会执行,刚好可以实现try catch的功能。

# 背景

Bash并没有像许多编程语言中那样多的奢侈品。bash中没有try/catch;但是,可以使用&&||实现类似的行为。

使用||:如果command1失败,则command2运行如下

command1 || command2
1

同样,使用&&,如果command1成功,command2将运行

try/catch的最接近的近似如下

{ # try
    command1 &&
    #save your output
} || { # catch
    # save log for exception 
}
1
2
3
4
5
6

bash也包含一些错误处理机制

set -e
1

如果简单命令失败,它将立即停止您的脚本。 我认为这应该是默认行为。 由于这些错误几乎总是意味着意外的事情,因此继续执行以下命令并不是“理智”。

# 模版

try-catch.sh

#!/bin/bash
function try(){
    [[ $- = *e* ]]; SAVED_OPT_E=$?
    set +e
}
function throw(){
    exit $1
}
function catch(){
    export ex_code=$?
    (( $SAVED_OPT_E )) && set +e
    return $ex_code
}
function throwErrors(){
    set -e
}
function ignoreErrors(){
    set +e
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

使用: sample.sh

#!/bin/bash
function try(){
    [[ $- = *e* ]]; SAVED_OPT_E=$?
    set +e
}
function throw(){
    exit $1
}
function catch(){
    export ex_code=$?
    (( $SAVED_OPT_E )) && set +e
    return $ex_code
}
function throwErrors(){
    set -e
}
function ignoreErrors(){
    set +e
}

export AnException=100
export AnotherException=101

# start with a try
try
(   # open a subshell !!!
    echo "do something"
    [ someErrorCondition ] && throw $AnException

    echo "do something more"
    executeCommandThatMightFail || throw $AnotherException

    throwErrors # automaticatly end the try block, if command-result is non-null
    echo "now on to something completely different"
    executeCommandThatMightFail

    echo "it's a wonder we came so far"
    executeCommandThatFailsForSure || true # ignore a single failing command

    ignoreErrors # ignore failures of commands until further notice
    executeCommand1ThatFailsForSure
    local result = $(executeCommand2ThatFailsForSure)
    [ result != "expected error" ] && throw $AnException # ok, if it's not an expected error, we want to bail out!
    executeCommand3ThatFailsForSure

    echo "finished"
)
# directly after closing the subshell you need to connect a group to the catch using ||
catch || {
    # now you can handle
    case $ex_code in
        $AnException)
            echo "AnException was thrown"
        ;;
        $AnotherException)
            echo "AnotherException was thrown"
        ;;
        *)
            echo "An unexpected exception was thrown"
            throw $ex_code # you can rethrow the "exception" causing the script to exit if not caught
        ;;
    esac
}
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

# 参考链接

  • https://gist.github.com/e7d/e43e6586c1c2ecb67ae2
  • https://www.xmodulo.com/catch-handle-errors-bash.html
上次更新: 2022/04/15, 05:41:30
×