如何为任意bash命令编写包装器?

时间:2015-10-01 07:09:33

标签: bash eval

我希望在整个脚本中多次使用以下构造:

tries=0
while ! resposta=$(ssh ${nodes[$k]} 'nproc && uptime'); do
    let tries+=1
    if ((tries > max_tries)); then
        printf "Can't connect to %s !!!" "${nodes[$k]}"
        exit 1
    fi
    printf "Failed! Trying again after %d seconds...\n" "$sleep_time"
    sleep $sleep_time
done

此代码多次运行resposta=$(ssh ${nodes[$k]} 'nproc && uptime')命令,直到它运行,或者直到达到最大尝试次数。

但是,我想在一个块中包含很多命令,如上所述。我现在正在做的是:每次我想要的时候重复整个块,改变构成while循环条件的命令。

这当然是嘘声和愚蠢。我想避免使用基于eval的解决方案 - 因为除了破坏语法突出显示之外,eval是邪恶的甚至是愚蠢的原因:)

1 个答案:

答案 0 :(得分:2)

您可以编写一个函数,将您想要运行的命令作为带引号的参数运行:

function repeat() {
    tries=0
    while ! resposta=$($1); do
        let tries+=1
        if ((tries > max_tries)); then
            printf "Command %s failed" "$1"
            exit 1
        fi
        printf "Failed! Trying again after %d seconds...\n" "$sleep_time"
        sleep $sleep_time
    done
}

repeat "ssh ${nodes[$k]} ''nproc && uptime''"

请注意,传入时会引用字符串,以避免对其进行解释,但在将其扩展为$1时不会引用该字符串,以便实际调用该命令。

另外,请注意加倍的单引号。这告诉bash在传递给函数的字符串中使用实际的单引号字符。否则,单引号将被剥离,您将从服务器收到以下错误:

bash: nproc & uptime: command not found