远程执行命令,使用 “<<EOF” 的方式叫做 Heredoc,如果内部使用了变量,实际上是在本地shell做了替换,再提交到远程shell执行!
关于HereDoc:https://linuxize.com/post/bash-heredoc/#using-heredoc-with-ssh
使用无引号分隔符时,请确保转义所有变量、命令和特殊字符,否则将在本地进行插值!
$变量,默认是提前在本地shell替换。$(命令),默认是提前在本地shell执行。
比如,在 node1(192.168.0.1) 执行如下命令:
ssh -q root@node2 <<EOF
echo $HOSTNAME
log=$(hostname -I)
echo $log
EOF
实际上 node2(192.168.0.2) 执行的命令为:
echo node1
log=192.168.0.1 #如果命令返回带有空格,这里还会报错“命令不存在”,让人摸不着头脑
echo
可以看到,node2执行的命令都是被提前执行。
解决:避免替换变量和执行命令,进行转义。
方式一:将 ‘$’ 改成 ‘\$’
上述代码改成:
ssh -q root@node2 <<EOF
echo $HOSTNAME
log=\$(hostname -I) #注意前缀
echo \$log #注意前缀
EOF
实际node2执行的命令为:
echo node1
log=$(hostname -I) #在node2才执行 hostname -I
echo $log #在node2才打印变量
方式二:将 EOF 改成 ‘EOF’,相当于全局禁用变量替换和命令执行!
ssh -q root@node2 <<'EOF'
echo $HOSTNAME
log=$(hostname -I)
echo $log
EOF
实际node2执行的命令为:
echo $HOSTNAME #打印node2
log=$(hostname -I) #在node2执行
echo $log #打印192.168.0.2
end