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

Bash重定向标准输入至SSH时的变量替代问题

解决SSH脚本中动态切换非交互/交互模式的问题

你遇到的这个坑其实是shell重定向语法的特性导致的——<&0属于shell层面的特殊语法结构,不是普通的文件名,所以直接把它存在变量里当作<的参数时,shell会傻乎乎地去寻找名为&0的文件,自然就报错找不到了。

为什么原来的方法行不通?

shell在解析命令的时候,会先识别重定向、管道这类特殊语法,再处理变量替换。当你写ssh ... <$SSH_SCRIPT时,如果SSH_SCRIPT的值是&0,shell会先把变量替换成&0,然后把<&0当成“打开名为&0的文件作为输入”,而不是识别成“把标准输入(文件描述符0)重定向过来”。这俩完全是两回事!

推荐的解决方案

最稳妥的方式是用条件分支分开处理两种场景,逻辑清晰还不容易踩坑:

if [ -n "$SSH_SCRIPT" ]; then
  # 非交互式场景:从指定的脚本源读取输入
  ssh $SSH_IGNORE_STDIN $SSH_TTY $noKeyCheck -i $AWS_KEY $USER_@$HOST_ "$COMMAND_SSH" < "$SSH_SCRIPT"
else
  # 交互式场景:直接继承当前shell的标准输入(默认就是这个行为,不用额外写<&0)
  ssh $SSH_IGNORE_STDIN $SSH_TTY $noKeyCheck -i $AWS_KEY $USER_@$HOST_ "$COMMAND_SSH"
fi

这里要注意:交互式场景下不要设置SSH_IGNORE_STDIN为-n,这个参数会强制SSH忽略标准输入,直接切断交互能力。

如果你非要用变量的方式统一命令格式,可以借助eval让shell重新解析包含重定向的命令(但要注意变量转义,避免注入风险):

# 根据SSH_SCRIPT的值构造重定向字符串
if [ -z "$SSH_SCRIPT" ]; then
  REDIRECT="<&0"
else
  # 给文件名加引号,防止包含空格或特殊字符
  REDIRECT="<\"$SSH_SCRIPT\""
fi

# 用eval强制shell解析重定向语法
eval "ssh $SSH_IGNORE_STDIN $SSH_TTY $noKeyCheck -i $AWS_KEY $USER_@$HOST_ \"\$COMMAND_SSH\" $REDIRECT"

额外小技巧

如果你的非交互式场景是要传递一段脚本代码给远程执行,用Here Document会更直观:

# 传递脚本内容,EOF加单引号可以避免本地变量替换
ssh $SSH_IGNORE_STDIN $noKeyCheck -i $AWS_KEY $USER_@$HOST_ << 'EOF'
echo "正在执行远程脚本..."
ls -l /home
EOF

内容的提问来源于stack exchange,提问作者Ondra Žižka

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:05:51