回显在 Bash 中运行的最后一个命令? [英] Echoing the last command run in Bash?

查看:25
本文介绍了回显在 Bash 中运行的最后一个命令?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试回显在 bash 脚本中运行的最后一个命令.我找到了一种使用一些 history,tail,head,sed 的方法,当命令从解析器的角度代表我脚本中的特定行时,它可以正常工作.但是在某些情况下我没有得到预期的输出,例如当命令插入到 case 语句中时:

I am trying to echo the last command run inside a bash script. I found a way to do it with some history,tail,head,sed which works fine when commands represent a specific line in my script from a parser standpoint. However under some circumstances I don't get the expected output, for instance when the command is inserted inside a case statement:

脚本:

#!/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'ers 同事非常感谢他们的贡献,我还是选择编写一个 run 函数 - 它将所有参数作为单个命令运行,并在失败时显示命令及其错误代码- 具有以下好处:
-我只需要在 run 前面加上我想检查的命令,这样就可以将它们保持在一行上,并且不会影响我的脚本的简洁性
- 每当脚本在这些命令之一上失败时,我的脚本的最后输出行是一条消息,清楚地显示哪个命令失败及其退出代码,这使调试更容易

Despite the much appreciated contributions from my fellow SO'ers, I opted for writing a run function - which runs all its parameters as a single command and display the command and its error code when it fails - with the following benefits:
-I only need to prepend the commands I want to check with run which keeps them on one line and doesn't affect the conciseness of my script
-Whenever the script fails on one of these commands, the last output line of my script is a message that clearly displays which command fails along with its exit code, which makes debugging easier

示例脚本:

#!/bin/bash
die() { echo >&2 -e "
ERROR: $@
"; 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 函数没有破坏它们.到目前为止,我发现的唯一问题是运行一个中断的回声,但我不打算检查我的回声.

I tested various commands with multiple arguments, bash variables as arguments, quoted arguments... and the run function didn't break them. The only issue I found so far is to run an echo which breaks but I do not plan to check my echos anyway.

推荐答案

命令历史是一种交互式功能.历史中只输入完整的命令.例如,case 构造作为一个整体输入,当 shell 完成解析它时.使用内置的 history 查找历史记录(也不通过 shell 扩展 (!:p) 打印)都不会做您似乎想要的,即打印调用简单的命令.

The command history is an interactive feature. Only complete commands are entered in the history. For example, the case construct is entered as a whole, when the shell has finished parsing it. Neither looking up the history with the history built-in (nor printing it through shell expansion (!:p)) does what you seem to want, which is to print invocations of simple commands.

DEBUG 陷阱 允许您在任何简单命令执行之前执行命令.BASH_COMMAND 变量.

The DEBUG trap lets you execute a command right before any simple command execution. A string version of the command to execute (with words separated by spaces) is available in the BASH_COMMAND variable.

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

注意 previous_command 每次运行命令都会改变,所以将它保存到一个变量中以便使用它.如果您还想知道上一个命令的返回状态,请将两者保存在一个命令中.

Note that previous_command will change every time you run a command, so save it to a variable in order to use it. If you want to know the previous command's return status as well, save both in a single command.

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

此外,如果您只想中止失败的命令,请使用 set -e 使您的脚本在第一个失败的命令上退出.您可以显示 EXIT 陷阱.

Furthermore, if you only want to abort on a failed commands, use set -e to make your script exit on the first failed command. You can display the last command from the EXIT trap.

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

请注意,如果您试图跟踪脚本以查看它在做什么,请忘记所有这些并使用 set -x.

Note that if you're trying to trace your script to see what it's doing, forget all this and use set -x.

这篇关于回显在 Bash 中运行的最后一个命令?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆