回显在 Bash 中运行的最后一个命令? [英] Echoing the last command run in 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屋!