You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

跳板机场景下SSH远程执行脚本的嵌套引号问题求助

嵌套SSH执行带单引号的awk命令解决方案

问题背景

现有基础设施:ServerA ---> ServerB ---> ServerC,需在ServerA运行脚本,从ServerC获取大文件(先过滤)并保存到ServerA。已成功通过以下命令获取匹配文件名存入$myfiles:

myfiles=$(ssh root@$serverB -C $"
          ssh -o StrictHostKeyChecking=no root@$serverC -C $'
          (find . -name "mypattern" | sort)' </dev/null")

需用以下命令过滤数据:

grep mypattern $myfile | awk -F '[| =]+' '{print $1 "/" $2 "/" $3, $4}' OFS=';'

但嵌套执行时,因awk命令的单引号导致嵌套引号冲突,现有代码如下:

while read myfile
do
   output=$( ssh root@$serverB -C $"
             ssh -o StrictHostKeyChecking=no root@$serverC -C $'
             (grep mypattern $myfile | awk -F '[| =]+' '{print $1 "/" $2 "/" $3, $4}' OFS=';')'
             </dev/null")
   # do something with $output
done <<< "$myfiles"

注:无法使用SSH跳板机标志,因为ServerC仅能通过ServerB带StrictHostKeyChecking=no参数的SSH访问。尝试过单双引号互换、将命令存为字符串/函数/单独文件均无效,需可行的嵌套执行方案。


可行解决方案

方案1:转义嵌套单引号

在最内层的$'...'(bash ANSI-C引号)中,将awk命令里的单引号用'\''转义(即关闭当前单引号→插入单引号→重新打开单引号),确保远程能正确解析命令:

while read myfile
do
   output=$( ssh root@$serverB -C $"
             ssh -o StrictHostKeyChecking=no root@$serverC -C $'
             (grep mypattern '$myfile' | awk -F '\''[| =]+'\'' '\''{print $1 "/" $2 "/" $3, $4}'\'' OFS='\'';'\'' )'
             </dev/null")
   # 处理$output
done <<< "$myfiles"

方案2:用Here文档隔离命令

通过Here文档定义要在ServerC执行的命令,避免多层引号嵌套,再替换文件名占位符后传递:

while read myfile
do
   # 定义远程执行的命令模板(用占位符避免本地变量解析)
   remote_cmd=$(cat <<'EOF'
grep mypattern FILE_PLACEHOLDER | awk -F '[| =]+' '{print $1 "/" $2 "/" $3, $4}' OFS=';'
EOF
   )
   # 替换占位符为实际文件名
   remote_cmd=${remote_cmd//FILE_PLACEHOLDER/"$myfile"}
   
   # 嵌套SSH执行
   output=$(ssh root@$serverB -C "ssh -o StrictHostKeyChecking=no root@$serverC -C '$remote_cmd'" </dev/null)
   # 处理$output
done <<< "$myfiles"

方案3:SSH代理转发简化连接

通过ServerB建立本地代理,让ServerA直接连接ServerC,从根源上消除嵌套SSH的引号问题:

  1. 先建立代理(后台运行):
ssh -fN -o StrictHostKeyChecking=no root@$serverB -L 2222:$serverC:22
  1. 直接从ServerA连接ServerC(通过本地2222端口转发):
while read myfile
do
   output=$(ssh -p 2222 root@localhost -C "grep mypattern $myfile | awk -F '[| =]+' '{print $1 "/" $2 "/" $3, $4}' OFS=';'" </dev/null)
   # 处理$output
done <<< "$myfiles"

脚本结束后可通过pkill -f "ssh -fN -L 2222:$serverC:22"关闭代理。


内容的提问来源于stack exchange,提问作者xard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 09:02:45