如何通过expect命令下载目录全量文件 解决scp仅下载部分文件问题
问题根因
脚本仅下载16个文件就中断,核心是3个配置漏项:
- scp默认输出的动态进度条是主要诱因:spawn分配的伪终端会触发scp输出实时刷新的进度条(靠回车
\r反复覆盖同一行),但expect默认给spawn进程开的接收缓冲区match_max只有2000字节,大量进度输出瞬间就把缓冲区打满,scp往标准输出写不动内容就会被阻塞挂起,直接中断传输。 - expect默认超时仅10秒,哪怕没有缓冲区阻塞,多文件、大文件传输时间超过10秒也会被expect强制终止,本次中断是缓冲区阻塞先触发。
- 远程路径的通配符写法没问题,会由远程端shell自动展开,和你ssh手动ls统计的41个文件结果一致,这部分没有错误。
修改方案
直接替换expect.dat的全部内容即可,全程无交互,完全适配无人值守运行场景:
#!/usr/bin/expect # 把缓冲区调大到2MB,彻底避免输出阻塞 match_max 2097152 # 设置为永不超时,不管传多久都等scp正常结束 set timeout -1 # scp加-q参数关闭所有进度输出,从根源砍掉无效的刷屏内容 spawn scp -q -r user@107.65.57.10:/data/dcrm_int/ftp/out/20220407/*REP_ACCOUNT_20220407* /process/filesW/. expect "*?assword*" send "pps0\r" # 等待传输完成,处理异常场景 expect eof { exit 0 } timeout { puts "[clock format [clock seconds]] 传输超时异常" exit 1 }
效果说明
- 加
-q参数后scp不会输出任何进度刷新内容,不会产生无效输出占缓冲区,这一步能解决90%以上同类scp+expect中途断传的问题 - 2MB缓冲区足够兼容所有剩余的scp正常输出,不会再出现写阻塞挂死的情况
- 关闭默认超时后,不会因为总传输时长过长被expect强制杀掉进程
- 改完重新执行就能拉全41个文件,不需要加
interact指令。
内容的提问来源于stack exchange,提问作者Jeniffer Lorena Guillen Castro
相关产品推荐
相关产品推荐

