当前位置:首页>Linux>Linux 下使用 Expect 实现自动化文件传输

Linux 下使用 Expect 实现自动化文件传输

  • 2026-10-11 06:45:41
Linux 下使用 Expect 实现自动化文件传输

Linux 下使用 Expect 实现自动化文件传输

现状背景

生产环境的业务应用机器因日志文件持续积累(gz 压缩格式,总量超过 100G,按策略需保留最近 2 年),触发了磁盘空间告警。经排查,同一局域网内存在闲置机器且磁盘空间充裕,因此计划将历史日志迁移到闲置机器上以释放生产机器的磁盘压力。

(注:所有机器资源均为按月付费的云服务器。)

补充说明:

  • • 局域网内机器之间通过 SSH + 账密方式登录(未配置免密认证)
  • • 存在多台业务生产机器需要同时迁移
  • • 日志文件路径格式为 /mnt/logs/app/yyyy-MM/yyyy-MM-dd-i.gz,单个文件约 300M,每天产生 5-6 个文件

核心诉求:在多台机器之间批量传输大量文件,需要自动化手段替代手动逐台操作。

需求

在目标闲置机器上执行一条命令,传入年月参数(如 2024-06),脚本自动遍历所有生产机器,批量复制对应月份的日志文件到本地。

关键核心 — Expect 命令

当 SSH/SCP 等命令需要输入密码时,标准的 shell 脚本无法自动响应交互提示。Expect 正是解决这类问题的工具——它能监听进程的交互提示(如密码输入框),并自动发送预设的应答内容,将原本需要人工干预的操作编排成可自动执行的脚本。

安装方式:

yum -y install expect

Expect 四大核心指令

  • • spawn:启动一个新的子进程,后续的命令交互都在该进程中进行
  • • expect:等待并匹配子进程输出的特定字符串(如密码提示符)
  • • send:向子进程发送字符串(模拟用户输入),通常需要以 \r 结尾表示回车确认
  • • interact:将控制权交还给用户,允许手动交互(自动化场景中通常不使用)

关键机制: 只有 spawn 启动的进程所产生的输出才会被 expect 捕获。spawn 会 fork 出一个子进程,Expect 仅监听该子进程的三类信息:标准输出中的提示文本、进程结束信号(eof)、以及超时事件(timeout)。

实例

#!/usr/bin/expect# 设置全局超时时间,单位秒set timeout 1800# 获取命令行参数if {$argc < 1} {puts "Usage: $argv0 <date>"exit 1}# 解析参数set date_param [lindex $argv 0]set username "myusername"set password "mypassword"# 定义服务器IP列表set ips {"192.168.1.10" "192.168.1.11" "192.168.1.12"}# 远程目录路径set remote_base_dir "/mnt/logs/xxx"# 基础本地备份目录set base_local_dir "/mnt/backup"# 遍历每台服务器foreach ip $ips {# 为每台服务器创建独立的本地目录 /mnt/backup/ip/date_paramset local_dir "$base_local_dir/$ip/$date_param"    # 检查并创建本地目录(如果不存在)    if {![file exists $local_dir]} {        if {[catch {exec mkdir -p $local_dir} result]} {            puts "创建目录 $local_dir 失败: $result"            continue        } else {            puts "创建目录: $local_dir"        }    }    puts "正在从 $ip 复制文件到 $local_dir ..."    # 构造远程目录路径    set remote_dir "$remote_base_dir/$date_param"    # 执行 scp 命令    spawn scp -r $username@$ip:$remote_dir/* $local_dir    # 等待并响应密码提示    expect {        "*yes/no*" {            send "yes\r"            exp_continue        }        "*password:*" {            send "$password\r"        }        timeout {            puts "连接 $ip 超时"            continue        }    }    # 等待命令执行完成    expect {        eof {            puts "从 $ip 复制完成"        }        timeout {            puts "从 $ip 复制超时"        }    }}puts "所有文件复制完成。"

最新文章

随机文章