bash中最后一个失败的命令


Answers:


6

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

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


这个可悲的是我没有料到是否有使用用途或功能的大case语句并不完全正常工作... :(我结束了使用caller和bash的阵列BASH_LINENOBASH_SOURCE以及FUNCNAME做一种堆栈跟踪。
phyatt

6

如果执行的最后一条命令没有参数,则将其保存在$_变量中。它通常包含一个命令的最后一个参数 -因此,如果没有参数,则值$_是最后一个命令本身。

另一个选择是了解上一个后台命令的详细信息。正如l0b0所写,$!保持其PID- 因此您可以解析输出ps $!(可能带有的其他格式选项ps)。


2

不,但是您可以在执行期间获取它以存储其他命令:

  • $0:当前shell脚本的路径。
  • $FUNCNAME:“当前函数的名称。”
  • "$@":当前命令的所有参数,单独引用。
  • $!:“最后一个作业的PID(进程ID)在后台运行。”
  • $$:“脚本本身的进程ID(PID)。”

因此,当前脚本的完整命令应为"$0" "$@"。如果是函数,则应该为"$FUNCNAME" "$@"。您可能希望将其存储在数组中以备将来处理。例如,将其存储在test.sh

#!/usr/bin/env bash
foo()
{
    declare -a command=("$0")
    for param in "$@"
    do
        command+=("$(printf %q "$param")")
    done
    echo "${command[@]}"
}
foo "$@"

运行时./test.sh "first argument" "second argument",它应返回:

./test.sh first\ argument second\ argument

等效呼叫。


在bash中有一个BASH_COMMAND变量,但除了在陷阱中使用以外,似乎没有任何用处。
enzotib

感谢您的输入。如果我some-command在shell脚本中运行怎么办,但失败了。我在中将具有非零状态$?,对于变量保持的存在,“否”仍然成立some-command吗?
Eimantas 2011年

据我所知,命令失败的唯一事实不会更改您的shell存储的有关该信息的集合。所以我会说“ 是”
rozcietrzewiacz 2011年

2

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打印脚本执行的跟踪并检查跟踪的最后几行。


0

我发现在具有set -eset -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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.