为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

米脂 2019-12-20 10:52:56
我试图回显在bash脚本中运行的最后一个命令。history,tail,head,sed从解析器的角度来看,当命令代表脚本中的特定行时,我找到了一种可以很好用的方法。但是在某些情况下,例如在将命令插入case语句内时,我得不到预期的输出:剧本:#!/bin/bashset -o historydatelast=$(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 2011last command is [date]Tue May 24 12:36:04 CEST 2011last command is [echo "last command is [$last]"][Q]有人可以帮助我找到一种方法来回显上次运行的命令,而不管该命令在bash脚本中的调用方式/位置如何?我的答案尽管我的SO同事们做出了令人赞赏的贡献,我还是选择编写了一个run函数-该函数将所有参数作为一个命令运行,并在失败时显示该命令及其错误代码-具有以下好处:-我只需要将要检查的命令run放在一行的前面,并且不会影响脚本的简洁性-每当脚本在这些命令之一中失败时,脚本的最后输出行就是一条消息,清楚地显示了哪个命令失败及其退出代码,这使调试更加容易示例脚本:#!/bin/bashdie() { 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.shapacheds  google  iptablesls: cannot access /wrong-dir: No such file or directoryERROR: command [ls /wrong-dir] failed with error code 2我测试了带有多个参数,bash变量作为参数,带引号的参数...的各种命令,但该run函数并未破坏它们。到目前为止,我发现的唯一问题是运行回声,但该回声中断了,但我仍然不打算检查回声。
查看完整描述

3 回答

?
暮色呼如

TA贡献1853条经验 获得超9个赞

命令历史记录是一种交互式功能。历史记录中仅输入完整的命令。例如,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 -e

trap 'echo "exit $? due to $previous_command"' EXIT

请注意,如果您试图跟踪脚本以查看其作用,请忘记所有这些内容并使用set -x。


查看完整回答
反对 回复 2019-12-20
?
慕勒3428872

TA贡献1848条经验 获得超6个赞

Bash具有内置功能来访问最后执行的命令。但这是最后一个完整的命令(例如整个case命令),而不是您最初请求的单个简单命令。


!:0 =执行命令的名称。


!:1 =上一个命令的第一个参数


!:* =上一条命令的所有参数


!:-1 =上一条命令的最终参数


!! =前一个命令行


等等


因此,最简单的答案是:


echo !!

...或者:


echo "Last command run was ["!:0"] with arguments ["!:*"]"

自己尝试!


echo this is a test

echo !!

在脚本中,历史记录扩展默认情况下处于关闭状态,您需要使用以下命令启用它


set -o history -o histexpand


查看完整回答
反对 回复 2019-12-20
?
杨魅力

TA贡献1811条经验 获得超6个赞

看看var是否在陷阱中也可用(以及所需的值)-的确如此!$BASH_COMMANDEXIT


因此,以下bash脚本按预期工作:


#!/bin/bash


exit_trap () {

  local lc="$BASH_COMMAND" rc=$?

  echo "Command [$lc] exited with code [$rc]"

}


trap exit_trap EXIT

set -e


echo "foo"

false 12345

echo "bar"

输出是


foo

Command [false 12345] exited with code [1]

bar永远不会打印出来,因为set -e导致bash在命令失败并且false命令总是失败时(根据定义)退出脚本。该12345传递给false在这里只用来表明该参数传递给失败的命令被捕获,以及(在false命令忽略传递给它的任何参数)


查看完整回答
反对 回复 2019-12-20
  • 3 回答
  • 0 关注
  • 484 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信