你最喜欢在Bash中处理错误的方法是什么? 我在网上找到的处理错误的最好的例子是William Shotts, Jr在http://www.linuxcommand.org上写的。

他建议在Bash中使用以下函数进行错误处理:

#!/bin/bash

# A slicker error handling routine

# I put a variable in my scripts named PROGNAME which
# holds the name of the program being run.  You can get this
# value from the first item on the command line ($0).

# Reference: This was copied from <http://www.linuxcommand.org/wss0150.php>

PROGNAME=$(basename $0)

function error_exit
{

#   ----------------------------------------------------------------
#   Function for exit due to fatal program error
#       Accepts 1 argument:
#           string containing descriptive error message
#   ---------------------------------------------------------------- 

    echo "${PROGNAME}: ${1:-"Unknown Error"}" 1>&2
    exit 1
}

# Example call of the error_exit function.  Note the inclusion
# of the LINENO environment variable.  It contains the current
# line number.

echo "Example of error with line number and message"
error_exit "$LINENO: An error has occurred."

在Bash脚本中是否有更好的错误处理例程?


当前回答

这是一个很好的解决方案。我只是想补充一点

set -e

作为一个基本的错误机制。如果一个简单的命令失败,它将立即停止脚本。我认为这应该是默认的行为:因为这样的错误几乎总是意味着一些意想不到的事情,所以继续执行下面的命令是不明智的。

其他回答

这是一个很好的解决方案。我只是想补充一点

set -e

作为一个基本的错误机制。如果一个简单的命令失败,它将立即停止脚本。我认为这应该是默认的行为:因为这样的错误几乎总是意味着一些意想不到的事情,所以继续执行下面的命令是不明智的。

我使用以下陷阱代码,它还允许通过管道和“时间”命令跟踪错误

#!/bin/bash
set -o pipefail  # trace ERR through pipes
set -o errtrace  # trace ERR through 'time command' and other functions
function error() {
    JOB="$0"              # job name
    LASTLINE="$1"         # line of error occurrence
    LASTERR="$2"          # error code
    echo "ERROR in ${JOB} : line ${LASTLINE} with exit code ${LASTERR}"
    exit 1
}
trap 'error ${LINENO} ${?}' ERR

有时set -e, trap ERR,set -o,set -o pipefail和set -o errtrace不能正常工作,因为它们试图在shell中添加自动错误检测。这在实践中并不奏效。

在我看来,你应该编写自己的错误检查代码,而不是使用set -e和其他东西。如果您明智地使用set -e,请注意潜在的陷阱。

为了避免在运行代码时出现错误,您可以使用exec 1>/dev/null或exec 2>/dev/null Linux中的/dev/null是一个空设备文件。这将丢弃写入它的任何内容,并在读取时返回EOF。您可以在命令末尾使用此命令

对于try/catch,您可以使用&&或||来实现类似的行为 Use可以像这样使用&&

{ # try

    command &&
    # your command 

} || { 
    # catch exception 
}

或者你可以用if else:

if [[ Condition ]]; then
    # if true
else
    # if false
fi

$ ?显示最后一个命令的输出,它返回1或0

这对我很有帮助。它以红色打印错误或警告消息,每个参数一行,并允许可选的退出代码。

# Custom errors
EX_UNKNOWN=1

warning()
{
    # Output warning messages
    # Color the output red if it's an interactive terminal
    # @param $1...: Messages

    test -t 1 && tput setf 4

    printf '%s\n' "$@" >&2

    test -t 1 && tput sgr0 # Reset terminal
    true
}

error()
{
    # Output error messages with optional exit code
    # @param $1...: Messages
    # @param $N: Exit code (optional)

    messages=( "$@" )

    # If the last parameter is a number, it's not part of the messages
    last_parameter="${messages[@]: -1}"
    if [[ "$last_parameter" =~ ^[0-9]*$ ]]
    then
        exit_code=$last_parameter
        unset messages[$((${#messages[@]} - 1))]
    fi

    warning "${messages[@]}"

    exit ${exit_code:-$EX_UNKNOWN}
}

不确定这是否对您有帮助,但我修改了这里的一些建议函数,以便在其中包括错误检查(先前命令的退出代码)。 在每次“检查”中,我还将错误的“消息”作为参数传递给日志记录。

#!/bin/bash

error_exit()
{
    if [ "$?" != "0" ]; then
        log.sh "$1"
        exit 1
    fi
}

现在要在同一个脚本中调用它(或者在另一个脚本中,如果我使用export -f error_exit),我只需写函数名并传递一个消息作为参数,如下所示:

#!/bin/bash

cd /home/myuser/afolder
error_exit "Unable to switch to folder"

rm *
error_exit "Unable to delete all files"

使用这个,我能够为一些自动化进程创建一个真正健壮的bash文件,它将在错误的情况下停止并通知我(log.sh将这样做)