嵌套SSH会话中设置变量的方法及脚本错误排查
咱们来一步步拆解你这个脚本里的问题,然后看看怎么解决嵌套SSH会话中的变量传递问题。
1. 变量作用域的隔离
你在host2的SSH会话里设置的myvar,只在host2的临时shell会话里有效。当ssh host2命令执行完毕,host2的会话就会终止,这个变量不会被带回host1的环境中。所以当你在host1里执行echo $myvar时,这个变量根本不存在,自然输出空值。
2. Here-doc的转义与解析问题
外层的ssh host1 << EOF使用了未转义的here-doc标记,本地shell会先解析里面的变量。比如你写的echo=\$myvar,本地shell会把\$解析成$,最终传到host1的命令其实是echo=$myvar——但就算没有这个转义问题,host1里的myvar也从未被设置,结果还是空的。
另外,内层的ssh host2 << EOF1在host1执行时,host1的shell会处理这个here-doc,直到遇到EOF1才结束,这部分逻辑本身没问题,但变量的作用域依然被严格限制在host2的会话里。
3. 变量传递的方向错误
你的脚本试图在host2设置变量,然后在host1读取,但SSH会话是独立的进程,环境变量不会自动在不同会话间传递,跨会话的变量必须通过显式的输出捕获或其他方式传递。
根据你的需求,分两种场景给出解决方案:
场景1:在host2设置变量并直接在host2使用
如果你的目标是在host2的会话里使用这个变量,直接把echo命令放到host2的here-doc里即可:
ssh host1 << EOF ssh host2 << EOF1 myvar="Hello" echo \$myvar # 这里的转义是为了让host2的shell解析变量,而非host1的shell EOF1 EOF
这样执行后,myvar会在host2的会话里被直接输出。
场景2:把host2里的变量值传回host1甚至本地
如果需要把host2里的变量值带回host1或者本地,可以通过输出捕获的方式实现:
# 把host2的变量值直接传回本地 myvar_local=$(ssh host1 << EOF # 在host1里捕获host2的输出 ssh host2 << EOF1 myvar="Hello" echo \$myvar EOF1 EOF ) echo "从host2带回的变量值:$myvar_local"
额外提示:用单引号简化转义
如果你不想处理复杂的转义逻辑,可以给here-doc标记加上单引号,这样本地和中间层的shell都不会解析里面的变量,直接把内容原封不动传给下一层:
ssh host1 << 'EOF' ssh host2 << 'EOF1' myvar="Hello" echo $myvar EOF1 EOF
内容的提问来源于stack exchange,提问作者Pankaj Jatav

