0

我有一个环境设置脚本,我想提醒用户我正在执行什么命令(即正在安装什么)。使用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我的脚本,如果它失败了,用户就会知道它在哪个命令上失败并且脚本会停止。

但是,当我尝试安装 Ruby/RVM时,我的脚本失败了:

successfully "curl -L https://get.rvm.io | bash -s stable --ruby"

当我从命令行调用 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
4

1 回答 1

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.
于 2013-09-10T05:24:16.950 回答