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

带ProxyCommand的SFTP结合Expect脚本运行失败,求助排查

带代理的SFTP脚本执行报错排查与解决

问题场景

尝试执行带HTTP代理的SFTP命令,用expect脚本实现自动化交互,但运行后报错。原脚本代码如下:

sftpCommand="sftp -o ConnectTimeout=3 -o "ProxyCommand=/usr/bin/nc --proxy-type http --proxy 192.168.20.98:3128 --proxy-auth pxuser:Password@1 %h %p" -oPort=22 user-sftp2@202.89.99.20"

/usr/bin/expect << EOD
                set timeout -1
                
                spawn /bin/sh -c $sftpCommand
                expect {
                        "*?assword:*" { 
                            send "$sftpPassword\r"
                        }
                        "*>*" {  
                            send "put $datewise_dir $remoteDir\r"
                        }
                        "*>*" {
                            send "bye\r"
                        }
                    }
EOD

报错信息

运行后出现以下错误:

line 6: {--proxy-type}: command not found
spawn /bin/sh -c
/bin/sh: -c: option requires an argument

问题原因

  1. 引号嵌套冲突:sftpCommand变量中,ProxyCommand部分使用的双引号和外层变量的双引号未做处理,导致shell解析时提前截断命令,把--proxy-type当成了独立命令执行。
  2. expect变量未转义:spawn /bin/sh -c $sftpCommand中直接使用未加引号的变量,shell会对变量内容分词,破坏了命令的完整性,导致/bin/sh -c没有获取到有效参数。
  3. expect匹配逻辑冗余:两个*>*匹配规则会导致逻辑混乱,只会触发第一个匹配到的动作,无法完成后续的上传和退出操作。

解决步骤

1. 修复变量引号嵌套

将ProxyCommand内部的双引号转义,或者改用单引号包裹整个变量,确保shell能正确解析完整命令:

# 方案1:转义内部双引号
sftpCommand="sftp -o ConnectTimeout=3 -o \"ProxyCommand=/usr/bin/nc --proxy-type http --proxy 192.168.20.98:3128 --proxy-auth pxuser:Password@1 %h %p\" -oPort=22 user-sftp2@202.89.99.20"

# 方案2:用单引号包裹整个变量
sftpCommand='sftp -o ConnectTimeout=3 -o "ProxyCommand=/usr/bin/nc --proxy-type http --proxy 192.168.20.98:3128 --proxy-auth pxuser:Password@1 %h %p" -oPort=22 user-sftp2@202.89.99.20'

2. 修复expect的spawn命令

在expect中引用$sftpCommand时,用双引号包裹,避免shell分词:

spawn /bin/sh -c "$sftpCommand"

3. 优化expect匹配逻辑

调整匹配规则,使用exp_continue实现顺序匹配,确保完成密码输入、文件上传、退出的完整流程:

/usr/bin/expect << EOD
set timeout -1

spawn /bin/sh -c "$sftpCommand"
expect {
    "*?assword:*" { 
        send "$sftpPassword\r"
        exp_continue  # 输入密码后继续等待SFTP提示符
    }
    "*>*" {  
        send "put $datewise_dir $remoteDir\r"
        expect "*>*" { send "bye\r" }  # 上传完成后执行退出
    }
}
EOD

完整修复后的脚本

sftpCommand="sftp -o ConnectTimeout=3 -o \"ProxyCommand=/usr/bin/nc --proxy-type http --proxy 192.168.20.98:3128 --proxy-auth pxuser:Password@1 %h %p\" -oPort=22 user-sftp2@202.89.99.20"

/usr/bin/expect << EOD
set timeout -1

spawn /bin/sh -c "$sftpCommand"
expect {
    "*?assword:*" { 
        send "$sftpPassword\r"
        exp_continue
    }
    "*>*" {  
        send "put $datewise_dir $remoteDir\r"
        expect "*>*" { send "bye\r" }
    }
}
EOD

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 12:39:50