bash 中最后一个失败的命令

bash 中最后一个失败的命令

$?变量保存上次运行命令的退出状态。是否有一个变量保存上次运行命令本身?

答案1

用于fc获取上一个命令行。它通常用于在您喜欢的编辑器中编辑上一个命令行,但它也有“列表”模式:

last_command="$(fc -nl -1)"

答案2

如果最后一个命令是在没有参数的情况下执行的,它将保存在$_变量中。这通常包含最后一个论点上一个命令的值 - 因此如果没有参数,则 的值$_就是最后一个命令本身。

另一种选择是了解最后的详细信息背景命令。正如 l0b0 所写,$!保存其 PID - 因此您可以解析 的输出ps $!(可能带有附加格式化选项ps)。

答案3

DEBUG陷阱允许您在执行任何简单命令之前执行命令。要执行的命令的字符串版本(单词之间用空格分隔)可在BASH_COMMAND多变的。

trap 'previous_command=$this_command; this_command=$BASH_COMMAND' DEBUG
echo "last command is $previous_command"

请注意,previous_command每次运行命令时都会发生变化,因此将其保存到变量中以便使用它。如果您还想知道前一个命令的返回状态,请将两者保存在一个命令中。

cmd=$previous_command ret=$?
if [ $ret -ne 0 ]; then echo "$cmd failed with error code $ret"; fi

如果您只想在命令失败时中止,请使用set -e使脚本在第一个失败的命令时退出。您可以显示最后一条命令EXIT陷阱

set -e
trap 'echo "exit $? due to $previous_command"' EXIT

可能适用于某些用途的另一种方法是使用set -x打印脚本执行的跟踪并检查跟踪的最后几行。

答案4

set -e我发现在有和选项时找到最后一个失败的命令至关重要set -o pipefail,否则 bash 会简单地中止而没有任何反馈原因,所以这就是我发现运行良好的方法:

#!/usr/bin/env bash
set -eu
set -o pipefail

cur_command=
first_err_command=
first_err_lineno=
# This trap is executed in exactly the same conditions in which the `set -e` results in an exit.
trap 'cur_command=$BASH_COMMAND;
      if [[ -z "$first_err_command" ]]; then
          first_err_command=$cur_command;
          first_err_lineno=$LINENO;
      fi' ERR
trap 'if [[ ! -z "$first_err_command" ]]; then
          echo "ERROR: Aborting at line: $first_err_lineno on command: $first_err_command";
      fi' EXIT

echo "The following command causes bash to abort, but it should also result in a nice message"
false
echo "This message is not expected"

如果运行上面的命令,您最终将看到以下输出:

The following command causes bash to abort, but it should also result in a nice message
ERROR: Aborting at line: 22 on command: false

行号可能并不总是准确的,但它应该给您足够接近的有用信息。

相关内容