远程 SSH 命令有效,但在 bash 脚本中使用时无效

远程 SSH 命令有效,但在 bash 脚本中使用时无效

我正在尝试使用 bash 脚本停止远程服务器上的 tomcat。以下是函数:

function stop_remote_tomcat () {
    CURRENT_SERVER=$1
    CURRENT_USER=$2
    CURRENT_PEM_FILE=$3

    COMMAND="ssh -i $CURRENT_PEM_FILE $CURRENT_USER@$CURRENT_SERVER \"/bin/sh sudo /etc/init.d/tomcat stop\""
    echo $COMMAND
    $COMMAND
}

然后在 case 语句中调用此函数。

我的问题是,如果我只是复制输出语句echo $COMMAND并将其作为独立命令运行,它就可以完美运行。但是当它在脚本中运行时,它会出现错误:

sudo /etc/init.d/tomcat stop: No such file or directory

有人可以解释一下如何在 bash 脚本中实现这一点吗?

答案1

简短回答:参见BashFAQ #50:我尝试将命令放入变量中,但复杂的情况总是失败!

长答案:将命令放入变量中无法正常工作,这是因为 shell 解析事物的顺序。具体来说,它在扩展变量之前解析引号、转义符等,因此将引号嵌入变量中不起作用——当它们出现在命令行中时,它们已经来不及做任何有用的事情了。

可以将命令存储在数组而不是普通变量中,然后用来printf %q引用需要打印的任何部分:

[...]
COMMAND=(ssh -i $CURRENT_PEM_FILE $CURRENT_USER@$CURRENT_SERVER "/bin/sh sudo /etc/init.d/tomcat stop")
printf "%q " "${COMMAND[@]}"
echo    # Because printf won't add a linefeed
"${COMMAND[@]}"

问题在于,有很多方法可以用空格引用/转义变量,您%q可能无法选择一种您喜欢的方法。另一种选择是跳过存储命令,而只是“手动”打印它:

[...]
echo "ssh -i $CURRENT_PEM_FILE $CURRENT_USER@$CURRENT_SERVER \"/bin/sh sudo /etc/init.d/tomcat stop\""
ssh -i $CURRENT_PEM_FILE $CURRENT_USER@$CURRENT_SERVER "/bin/sh sudo /etc/init.d/tomcat stop"

相关内容