You need to enable JavaScript to run this app. 远程SSH命令中变量无法生效?本地执行脚本远程创建目录失败无报错
优惠活动
大模型
产品
解决方案
定价
更多

远程SSH命令中变量无法生效?本地执行脚本远程创建目录失败无报错

核心问题根因

你的here-document写法存在展开逻辑错位,最终执行的操作和预期完全脱节:

  • 脚本中ssh ... << 'EOT'的定界符被单引号包裹,会强制本地shell完全不对here-doc块内的内容做任何变量展开、转义解析,所有内容原封不动传到远程服务器
  • 你在块内写的mkdir -p \$dir_to_create,传到远程的原始内容就是带反斜杠的mkdir -p \$dir_to_create,远程shell解析时反斜杠转义了$符号,最终执行的是创建名字为字面字符串$dir_to_create的目录,根本不会识别你本地定义的/home/rocket/DjangoDir路径
  • 你之前尝试的"\$dir_to_create"、\"$dir_to_create"这类写法,因为本地展开被单引号定界符完全禁用,最终传到远程的还是带转义符的原始字符串,远程环境根本不存在dir_to_create这个变量,路径自然不对
  • 因为ssh加了-q静默参数、-tt强制分配伪终端,连实际创建错目录的输出、权限提示都被完全吞掉,所以你看不到任何报错,只会觉得预期路径没生成。
    本质上你的脚本不是没创建目录,是在远程登录用户的默认工作目录(一般是用户家目录)下,建了个名字带$符号的无效目录,和你要找的目标路径根本不是同一个。

可行的修正方案

方案1:调整here-doc展开规则,正确传递本地变量

去掉here-doc定界符的单引号,让本地shell能正常替换块内的变量值,这是和你现有代码最接近的改法:
修改后的核心代码:

sshpass -p ${password} ssh -q -tt user@${remote_ip} << EOT
    mkdir -p "${dir_to_create}"
  exit
EOT

这种写法下,本地shell会先把块内的${dir_to_create}替换成你定义的实际路径/home/rocket/DjangoDir,再把替换后的内容传给远程执行;加双引号包裹路径参数,也能避免路径包含空格时被shell错误拆分。

方案2:跳过here-doc,直接传递执行命令

如果觉得here-doc的转义规则容易踩坑,可以直接把要执行的命令作为ssh的参数传入,逻辑更直观,转义歧义更少:

sshpass -p ${password} ssh -q -tt user@${remote_ip} "mkdir -p ${dir_to_create}; exit"

本地shell会先完成变量替换,再把整条命令传给远程执行,不存在here-doc的展开规则冲突问题。

方案3:保留单引号定界符的纯传递模式,手动注入变量

如果确实需要保留<< 'EOT'的纯传递特性(避免块内其他内容被本地shell误解析),可以先把本地变量值通过ssh命令传入远程环境,再在here-doc块内调用远程的变量:

sshpass -p ${password} ssh -q -tt user@${remote_ip} "export TARGET_DIR='${dir_to_create}'; bash -s" << 'EOT'
mkdir -p "${TARGET_DIR}"
exit
EOT

这种写法下,here-doc块内的内容完全不做本地展开,所有执行逻辑都在远程完成,不会被本地shell的转义规则干扰。

排查小技巧

测试脚本时可以先临时去掉ssh的-q参数,显示完整的ssh输出和远程命令的执行报错,避免因为静默模式吞掉排查线索。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.04 17:54:01