是否在Bash中运行最后一条命令?

我试图回显在bash脚本中运行的最后一个命令。history,tail,head,sed从解析器的角度来看,当命令代表脚本中的特定行时,我找到了一种可以很好用的方法。但是在某些情况下,例如在将命令插入case语句内时,我得不到预期的输出:


剧本:


#!/bin/bash

set -o history

date

last=$(echo `history |tail -n2 |head -n1` | sed 's/[0-9]* //')

echo "last command is [$last]"


case "1" in

  "1")

  date

  last=$(echo `history |tail -n2 |head -n1` | sed 's/[0-9]* //')

  echo "last command is [$last]"

  ;;

esac

输出:


Tue May 24 12:36:04 CEST 2011

last command is [date]

Tue May 24 12:36:04 CEST 2011

last command is [echo "last command is [$last]"]

[Q]有人可以帮助我找到一种方法来回显上次运行的命令,而不管该命令在bash脚本中的调用方式/位置如何?


我的答案


尽管我的SO同事们做出了令人赞赏的贡献,我还是选择编写了一个run函数-该函数将所有参数作为一个命令运行,并在失败时显示该命令及其错误代码-具有以下好处:

-我只需要将要检查的命令run放在一行的前面,并且不会影响脚本的简洁性-

每当脚本在这些命令之一中失败时,脚本的最后输出行就是一条消息,清楚地显示了哪个命令失败及其退出代码,这使调试更加容易


示例脚本:


#!/bin/bash

die() { echo >&2 -e "\nERROR: $@\n"; exit 1; }

run() { "$@"; code=$?; [ $code -ne 0 ] && die "command [$*] failed with error code $code"; }


case "1" in

  "1")

  run ls /opt

  run ls /wrong-dir

  ;;

esac

输出:


$ ./test.sh

apacheds  google  iptables

ls: cannot access /wrong-dir: No such file or directory


ERROR: command [ls /wrong-dir] failed with error code 2

我测试了带有多个参数,bash变量作为参数,带引号的参数...的各种命令,但该run函数并未破坏它们。到目前为止,我发现的唯一问题是运行回声,但该回声中断了,但我仍然不打算检查回声。


米脂
浏览 485回答 3
3回答

暮色呼如

命令历史记录是一种交互式功能。历史记录中仅输入完整的命令。例如,case当外壳解析完该结构后,将其作为一个整体输入。既不使用history内置查询历史记录(也不通过外壳扩展(!:p)打印历史记录),这似乎并没有达到您想要的目的,即打印简单命令的调用。该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 -etrap 'echo "exit $? due to $previous_command"' EXIT请注意,如果您试图跟踪脚本以查看其作用,请忘记所有这些内容并使用set -x。

慕勒3428872

Bash具有内置功能来访问最后执行的命令。但这是最后一个完整的命令(例如整个case命令),而不是您最初请求的单个简单命令。!:0 =执行命令的名称。!:1 =上一个命令的第一个参数!:* =上一条命令的所有参数!:-1 =上一条命令的最终参数!! =前一个命令行等等因此,最简单的答案是:echo !!...或者:echo "Last command run was ["!:0"] with arguments ["!:*"]"自己尝试!echo this is a testecho !!在脚本中,历史记录扩展默认情况下处于关闭状态,您需要使用以下命令启用它set -o history -o histexpand

杨魅力

看看var是否在陷阱中也可用(以及所需的值)-的确如此!$BASH_COMMANDEXIT因此,以下bash脚本按预期工作:#!/bin/bashexit_trap () {  local lc="$BASH_COMMAND" rc=$?  echo "Command [$lc] exited with code [$rc]"}trap exit_trap EXITset -eecho "foo"false 12345echo "bar"输出是fooCommand [false 12345] exited with code [1]bar永远不会打印出来,因为set -e导致bash在命令失败并且false命令总是失败时(根据定义)退出脚本。该12345传递给false在这里只用来表明该参数传递给失败的命令被捕获,以及(在false命令忽略传递给它的任何参数)
打开App,查看更多内容
随时随地看视频慕课网APP