如何将嵌套引号变量传入远程SSH命令?脚本变量未填充问题
解决远程SSH脚本中变量传递的问题
嘿,我来帮你搞定这个变量没被正确填充的问题!咱们先看看你的脚本哪里出了问题,再一步步修正它。
问题根源
你写的脚本里用了<< \EOF1这种here-doc写法——这个反斜杠是关键!它会告诉本地shell:“把EOF1之间的内容原封不动传给远程,别展开任何变量”。所以远程执行时的$1根本拿不到本地脚本的参数,自然是空的。另外,你的本地脚本里$1已经被用来指定远程主机地址了,要是想传递要设置的hostname,得用另一个参数(比如$2)才行。
解决方案1:去掉here-doc分界符的反斜杠(最常用)
把<< \EOF1改成<< EOF1,这样本地shell会先展开变量,再把内容传给远程。同时调整变量的使用,区分远程主机和hostname参数:
#!/bin/bash # 第一个参数是远程主机地址,第二个是要设置的新hostname REMOTE_HOST="$1" NEW_HOSTNAME="$2" ssh -T user@"$REMOTE_HOST" << EOF1 sudo sh -c "echo \"hostname=$NEW_HOSTNAME\" >> /etc/rc.conf" sudo /etc/rc.d/hostname start EOF1
执行的时候用:./filename.sh your_remote_host new_hostname
解释一下:这里本地shell会先把$NEW_HOSTNAME替换成你传入的实际hostname,然后把完整的命令传给远程执行。里面的\"是为了在远程的sh -c命令里保留双引号,避免空格等特殊字符出问题。
解决方案2:用环境变量传递(适合保留here-doc字面量的场景)
如果你不想让本地shell展开here-doc里的内容,可以通过环境变量把值传给远程。不过需要远程的sshd配置允许接收这个环境变量:
#!/bin/bash REMOTE_HOST="$1" NEW_HOSTNAME="$2" # 把NEW_HOSTNAME作为环境变量发送给远程 ssh -T -o SendEnv=NEW_HOSTNAME user@"$REMOTE_HOST" << \EOF1 sudo sh -c "echo \"hostname=$NEW_HOSTNAME\" >> /etc/rc.conf" sudo /etc/rc.d/hostname start EOF1
注意事项:
- 远程主机的
/etc/ssh/sshd_config里需要添加AcceptEnv NEW_HOSTNAME(或者AcceptEnv *,但后者安全性稍差) - 重启远程的sshd服务(比如
sudo service sshd restart)
解决方案3:直接在SSH命令行拼接(适合短命令)
如果你的命令不算复杂,也可以不用here-doc,直接把命令写在ssh的参数里:
#!/bin/bash REMOTE_HOST="$1" NEW_HOSTNAME="$2" ssh -T user@"$REMOTE_HOST" "sudo sh -c 'echo \"hostname=$NEW_HOSTNAME\" >> /etc/rc.conf' && sudo /etc/rc.d/hostname start"
这里外层用双引号让本地展开$NEW_HOSTNAME,内层用单引号包裹远程的命令,确保语法正确。
小提示
不管用哪种方式,都建议给变量加上双引号(比如"$REMOTE_HOST"),避免变量里有空格或者特殊字符时出现意外错误。
内容的提问来源于stack exchange,提问作者pdna
相关产品推荐
相关产品推荐

