我正在尝试使用 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"