回显命令,然后运行它 - 管道命令失败?

时间:2013-09-10 05:12:10

标签: bash shell command-line command

我有一个环境设置脚本,我想提醒用户我正在执行哪些命令(即正在安装的是什么)。使用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

1 个答案:

答案 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.