解决Expect脚本误将SFTP密码中的$符号识别为变量的问题
解决Bash嵌套Expect脚本时密码含$的问题
核心问题原因
当你在Bash变量里嵌套Expect脚本时,如果密码包含$,Bash会先展开变量,把密码里的$直接暴露给Expect,而Expect会将$视为变量引用,尝试查找对应变量,从而抛出can't read "[xxx]": no such variable错误。你之前尝试的三种send写法,本质都是让Bash先展开了密码变量,所以都无法解决问题。
两种可行解决方案
方案1:在Bash中对密码的$进行转义
先把密码里的$替换成\$,这样Expect拿到的字符串里,$会被当作普通字符处理。示例代码:
test_sftp_connection() { # 转义密码中的$为\$ ESCAPED_PASSWORD=$(echo "$SFTP_SERVER_PASSWORD" | sed 's/\$/\\$/g') expect << EOF spawn sftp user@$SFTP_SERVER expect "password:" send "$ESCAPED_PASSWORD\r" expect { "sftp>" { puts "连接成功"; exit 0 } timeout { puts "超时"; exit 1 } eof { puts "连接失败"; exit 1 } } EOF }
方案2:让Expect直接读取环境变量
利用Expect的$env()语法直接读取Bash的环境变量,跳过Bash对变量的展开步骤,这样密码里的$不会被Expect误解析。示例代码:
test_sftp_connection() { expect << EOF spawn sftp user@$SFTP_SERVER expect "password:" # 直接读取环境变量SFTP_SERVER_PASSWORD send "\$env(SFTP_SERVER_PASSWORD)\r" expect { "sftp>" { puts "连接成功"; exit 0 } timeout { puts "超时"; exit 1 } eof { puts "连接失败"; exit 1 } } EOF }
注意这里的\$env需要加反斜杠,防止Bash把$env当作自己的变量展开。
额外注意事项
- 如果密码里还有其他特殊字符(比如
!、\),方案2的鲁棒性更强,因为它不需要额外转义,直接读取原始环境变量。 - 方案1需要确保
sed替换正确,比如如果密码里有斜杠,可能需要调整分隔符,比如用sed 's|\$|\\\$|g'。
内容的提问来源于stack exchange,提问作者MaestroMaus
相关产品推荐
相关产品推荐

