我有一个环境设置脚本,我想提醒用户我正在执行哪些命令(即正在安装的是什么)。使用set -x
会使输出过于混乱,所以我有一个函数successfully
,它会调用重要的命令:
#!/bin/bash
trap "exit 1" TERM
export TOP_PID=$$
real_exit() {
echo -e "Goodbye :'("
kill -s TERM $TOP_PID
}
successfully() {
echo -e "$*"
$* || (echo -e "\nFailed. Check output and then retry, please." 1>&2 && real_exit)
}
例如,我可以在我的脚本中调用successfully brew update
,如果失败,用户就会知道它失败了什么命令并且脚本停止了。
但是,当我尝试install Ruby/RVM时,我的脚本失败了:
successfully "curl -L https://get.rvm.io | bash -s stable --ruby"
当我从命令行调用curl命令时,curl命令工作正常,但是当脚本调用它时出现错误:
curl -L https://get.rvm.io | bash -s stable --ruby
curl: option --ruby: is unknown
curl: try 'curl --help' or 'curl --manual' for more information
答案 0 :(得分:1)
您需要使用eval,但不建议使用。
successfully() {
echo -e "$1"
eval "$1" || (echo -e "\nFailed. Check output and then retry, please." 1>&2 && real_exit)
}
同时发送SIGHUP而不是SIGTERM:
kill -s SIGHUP "$TOP_PID"
您也可以使用这样的安全版本:
successfully() {
local __A=() __I
for (( __I = 1; __I <= $#; ++__I )); do
if [[ "${!__I}" == '|' ]]; then
__A+=('|')
else
__A+=("\"\$$__I\"")
fi
done
echo "$@"
eval "${__A[@]}" || (echo -e "\nFailed. Check output and then retry, please." 1>&2 && real_exit)
}
示例:
successfully curl -L https://get.rvm.io \| bash -s stable --ruby ## You just have to quote pipe.