使用Expect结合SFTP时含特殊字符的密码报错问题
SFTP特殊字符密码的Expect脚本问题解决
你的问题出在两个核心点:shell变量传递时特殊字符被解析,以及Expect匹配逻辑重复导致的流程异常,以下是具体解决方法和修正后的脚本:
问题分析
- 原脚本中
<<EOF会让shell提前解析Expect代码里的变量,密码中的&、单引号等特殊字符会被shell当作语法符号处理,导致实际传递给Expect的密码已经变形。 - 重复的
expect "password:"和后续的expect块会打乱匹配流程,可能导致密码发送时机错误。
修正后的脚本
echo "begin" port="22" host_name="test.com" sftp_username='user1' sftp_password="?AFR'-rx]p[HL5G;'&ZM" SOURCE_PATH='data' DEST_PATH='out' FILE_NAME='Export.csv' echo "sftp connection begin" /usr/bin/expect <<'EOF' # 从shell环境变量读取参数,避免特殊字符被提前解析 set port $env(port) set host_name $env(host_name) set sftp_username $env(sftp_username) set sftp_password $env(sftp_password) set SOURCE_PATH $env(SOURCE_PATH) set DEST_PATH $env(DEST_PATH) set FILE_NAME $env(FILE_NAME) spawn sftp -C -oPort=$port $sftp_username@$host_name expect { "yes/no" { send "yes\r" exp_continue } "password:" } send "$sftp_password\r" expect "sftp>" send "mget ${SOURCE_PATH}/${FILE_NAME} ${DEST_PATH}/${FILE_NAME}\r" expect "sftp>" send "quit\r" EOF echo "Above file(s) transferred from SFTP to Oracle Server" echo "ftp connection end" echo "end"
关键修改说明
- 使用
<<'EOF'替代<<EOF:让shell不对Expect代码块内的变量做解析,特殊字符会原封不动传递给Expect。 - 通过
$env(var)读取环境变量:在Expect中直接获取shell定义的变量,避免变量替换时的字符转义问题。 - 合并匹配逻辑:去掉多余的
expect "password:",统一在一个expect块中处理主机密钥确认和密码输入提示,确保流程正确。 - send时用双引号包裹变量:Expect会正确解析变量内容,保证密码完整发送。
内容的提问来源于stack exchange,提问作者Mahesh Ayyalasomayajula
相关产品推荐
相关产品推荐

