【发布时间】:2011-08-31 20:10:55
【问题描述】:
我正在尝试回显在 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'ers 同事做出了非常感谢的贡献,但我还是选择编写 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 函数没有破坏它们。到目前为止我发现的唯一问题是运行一个中断的回声,但我不打算检查我的回声。
【问题讨论】:
-
+1,好主意!但是请注意,
run()在使用引号时无法正常工作,例如失败:run ssh-keygen -t rsa -C info@example.org -f ./id_rsa -N ""。 -
@johndodo:可以修复:只需将参数中的
"something"更改为'"something"'(或者,更确切地说,"'something'",以允许解释something(例如:变量)/如果需要,在第一级进行评估) -
我已将错误的
run() { $*; … }更改为更接近正确的run() { "$@"; … },因为错误的答案最终产生了问题cpexits with a 64 error status,问题在于$*破坏了命令名称中空格处的参数,但"$@"不会这样做。 -
Unix StackExchange 上的相关问题:unix.stackexchange.com/questions/21930/…
-
last=$(history | tail -n1 | sed 's/^[[:space:]][0-9]*[[:space:]]*//g')效果更好,至少对于 zsh 和 macOS 10.11