当前位置: 首页 > news >正文

Linux Shell: 使用 Expect 自动化 SCP 和 SSH 连接的 Shell 脚本详解

文章目录

    • 0. 引言
    • 2. 解决方案
    • 3. 脚本详解
      • 脚本1:使用 SSH 和 Expect 自动化登录远端机器
        • 脚本说明
      • 脚本2:使用 SCP 和 Expect 自动化文件上传
        • 脚本说明
      • 脚本3:使用 SCP 和 Expect 自动化文件下载
        • 脚本说明
    • 4. 脚本的使用方法
    • 5. 关键技术点
      • 5.1. Expect 脚本的引号处理
      • 5.2. 处理密码中的特殊字符
      • 5.3. 自动接受主机密钥
    • 6. 参考资料

0. 引言

在日常的开发过程中,我们经常需要在不同的服务器之间传输文件或者远程登录。Expect 工具是常用的自动登录工具之一,但是在处理包含特殊字符的密码(例如 &$ 等)时,需要特别注意。这些字符在 Shell 和 Expect 中有特殊的含义,可能导致脚本执行出错。

2. 解决方案

通过以下方法,我们可以编写健壮的脚本:

  • 使用 Expect 自动化交互式命令:Expect 是一个基于 Tcl 的工具,专门用于自动化交互式程序。
  • 正确处理特殊字符:在 Expect 脚本中,使用单引号和双引号的组合,确保密码中的特殊字符被正确处理。
  • 增加超时时间:防止由于网络延迟导致的超时错误。

3. 脚本详解

脚本1:使用 SSH 和 Expect 自动化登录远端机器

#!/bin/bash# 设置终端类型以确保兼容性
export TERM=xterm-256color# IP 地址和密码
ip='192.168.1.10'
password='your_password_here'# 从 known_hosts 文件中删除目标主机,防止 SSH 警告
ssh-keygen -f "/home/$(whoami)/.ssh/known_hosts" -R "${ip}"# 使用 Expect 自动化 SSH 连接过程
expect -c 'set timeout 10set password "'"$password"'"spawn ssh -o StrictHostKeyChecking=no root@'"$ip"'expect {# 自动回复 "yes" 以接受主机的真实性"*yes/no*" { send "yes\r"; exp_continue }# 当出现密码提示时,发送实际的密码"*password:*" { send "$password\r"; exp_continue }eof}interact
'
脚本说明
  • 清理 known_hosts:使用 ssh-keygen -R 命令从 known_hosts 文件中删除目标主机,防止因主机密钥变化导致的 SSH 警告。
  • 自动化 SSH 登录:使用 Expect 自动化输入密码,实现无人工干预的 SSH 登录。
  • 动态主目录:使用 $(whoami) 获取当前用户名,避免硬编码用户路径。

脚本2:使用 SCP 和 Expect 自动化文件上传

#!/bin/bash# 设置终端类型以确保兼容性
export TERM=xterm-256color# 目标文件和 IP 地址
file=$1
ip='192.168.1.10'# 密码(此处已做修改,实际使用时请替换为你的密码)
password='your_password_here'# 本地目标目录
destination_dir=$2
if [[ -z $destination_dir ]]; thendestination_dir='~/'
fi# 使用 Expect 自动化 SCP 过程
expect -c 'set timeout 10set password "'"$password"'"spawn scp -o StrictHostKeyChecking=no '"$file"' root@'"$ip"':'"$destination_dir"'expect {# 自动回复 "yes" 以接受主机的真实性"*yes/no*" { send "yes\r"; exp_continue }# 当出现密码提示时,发送实际的密码"*password:*" { send "$password\r"; exp_continue }eof}
'
脚本说明
  • 参数处理:接受两个参数,$1 为要传输的文件,$2 为目标目录。
  • 特殊字符处理
    • 使用单引号 ' 包裹整个 Expect 脚本,防止 Bash 提前解析其中的内容。
    • 在单引号内,使用 '"$variable"' 的方式正确嵌入 Bash 变量。
  • Expect 模式匹配
    • 使用 "*yes/no*""*password:*" 进行模式匹配,确保自动回复正确的内容。
  • 超时时间:将超时时间设置为 10 秒,防止网络延迟导致的超时。

脚本3:使用 SCP 和 Expect 自动化文件下载

#!/bin/bash# 设置终端类型以确保兼容性
export TERM=xterm-256color# 远程文件路径和 IP 地址
remote_file=$1
ip='192.168.1.10'# 密码(此处已做修改,实际使用时请替换为你的密码)
password='your_password_here'# 本地目标目录(默认为当前目录)
destination_dir=$2
if [[ -z $destination_dir ]]; thendestination_dir='.'
fi# 使用 Expect 自动化 SCP 下载过程
expect -c 'set timeout 10set password "'"$password"'"spawn scp -o StrictHostKeyChecking=no root@'"$ip"':'"$remote_file"' '"$destination_dir"'expect {# 自动回复 "yes" 以接受主机的真实性"*yes/no*" { send "yes\r"; exp_continue }# 当出现密码提示时,发送实际的密码"*password:*" { send "$password\r"; exp_continue }eof}
'
脚本说明
  • 参数处理:接受两个参数,$1 为远程服务器上的文件路径,$2 为本地目标目录。
  • 特殊字符处理
    • 与前两个脚本相同,正确处理密码中的特殊字符。
  • Expect 模式匹配
    • 自动处理主机真实性确认和密码输入。
  • 超时时间:同样设置为 10 秒。

4. 脚本的使用方法

为了方便地使用上述脚本,可以按照以下步骤进行配置:

  • 将脚本存放在指定目录

    建议将三个脚本(例如 ssh_my.shscp_my.shrscp_my.sh)放置在 ~/.ssh 目录下。这样可以统一管理与 SSH 和 SCP 相关的脚本。

    mv ssh_my.sh ~/.ssh/
    mv scp_my.sh ~/.ssh/
    mv rscp_my.sh ~/.ssh/
    
  • 赋予脚本执行权限

    确保脚本具有可执行权限:

    chmod +x ~/.ssh/ssh_my.sh
    chmod +x ~/.ssh/scp_my.sh
    chmod +x ~/.ssh/rscp_my.sh
    
  • 在 Shell 配置文件中设置别名

    为了在终端中方便地调用这些脚本,可以在 ~/.bashrc~/.zshrc 文件中添加别名:

    alias sshmy='~/.ssh/ssh_my.sh'
    alias scpmy='~/.ssh/scp_my.sh'
    alias rscpmy='~/.ssh/rscp_my.sh'
    
  • 重新加载配置文件

    修改完配置文件后,重新加载使之生效:

    source ~/.bashrc
    # 或者
    source ~/.zshrc
    
  • 使用别名调用脚本

    • 登录远程服务器

      sshmy
      
    • 上传文件到远程服务器

      scpmy 本地文件路径 [远程目标目录]
      

      示例:

      scpmy ./example.txt /root/
      
    • 从远程服务器下载文件

      rscpmy 远程文件路径 [本地目标目录]
      

      示例:

      rscpmy /root/example.txt ./
      

5. 关键技术点

5.1. Expect 脚本的引号处理

  • 单引号:将整个 Expect 脚本包裹在单引号内,防止 Bash 对其中内容的变量和特殊字符进行解析。
  • 双引号嵌入变量:在单引号内,需要嵌入 Bash 变量时,使用 '"$variable"' 的形式。

5.2. 处理密码中的特殊字符

  • 由于密码中可能包含 Shell 或 Expect 的特殊字符,直接使用可能导致解析错误。
  • 通过上述引号处理方法,可以安全地传递包含特殊字符的密码。

5.3. 自动接受主机密钥

  • 使用 -o StrictHostKeyChecking=no 选项,自动接受新的主机密钥,防止脚本因交互式提示而挂起。
  • 在 Expect 脚本中,匹配 "*yes/no*",并发送 "yes\r",进一步确保自动化。

6. 参考资料

  • Expect 官方文档
  • Bash Shell 脚本高级编程指南

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【Java】注解与单元测试的使用【主线学习笔记】
  • MySQL高阶1965-丢失信息的雇员
  • Java 入门指南:JVM(Java虚拟机)垃圾回收机制 —— 新一代垃圾回收器 ZGC 收集器
  • MICS:PythonJail沙箱逃逸(持续更新中)
  • 初识C#(二)- 流程控制
  • 模拟自然的本质:与IBM量子计算研究的问答
  • Redis存储原理
  • 3、等保1.0 与 2.0 的区别
  • Mac强制停止应用
  • 数据结构总结
  • 学习记录:js算法(四十一): 基于时间的键值存储
  • Qt --- 常用控件的介绍 --- 其他控件
  • Vscode Run Code Py中文乱码问题
  • 市面第一款 C++ 版本的U盘装机软件(即将上线)
  • TCP: Textual-based Class-aware Prompt tuning for Visual-Language Model
  • CSS3 聊天气泡框以及 inherit、currentColor 关键字
  • js操作时间(持续更新)
  • js递归,无限分级树形折叠菜单
  • mysql常用命令汇总
  • select2 取值 遍历 设置默认值
  • 个人博客开发系列:评论功能之GitHub账号OAuth授权
  • 检测对象或数组
  • 前嗅ForeSpider中数据浏览界面介绍
  • 使用 @font-face
  • ​Redis 实现计数器和限速器的
  • ‌U盘闪一下就没了?‌如何有效恢复数据
  • #pragma once与条件编译
  • #鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行
  • (152)时序收敛--->(02)时序收敛二
  • (k8s中)docker netty OOM问题记录
  • (pytorch进阶之路)CLIP模型 实现图像多模态检索任务
  • (代码示例)使用setTimeout来延迟加载JS脚本文件
  • (附源码)ssm失物招领系统 毕业设计 182317
  • (考研湖科大教书匠计算机网络)第一章概述-第五节1:计算机网络体系结构之分层思想和举例
  • (十六)串口UART
  • (十七)Flink 容错机制
  • (太强大了) - Linux 性能监控、测试、优化工具
  • (贪心 + 双指针) LeetCode 455. 分发饼干
  • (一) storm的集群安装与配置
  • (转)JVM内存分配 -Xms128m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=512m
  • (自用)仿写程序
  • .gitignore
  • .net core 6 集成 elasticsearch 并 使用分词器
  • .Net Core 微服务之Consul(三)-KV存储分布式锁
  • .NET Framework 的 bug?try-catch-when 中如果 when 语句抛出异常,程序将彻底崩溃
  • .net 无限分类
  • .NET(C#、VB)APP开发——Smobiler平台控件介绍:Bluetooth组件
  • .Net--CLS,CTS,CLI,BCL,FCL
  • .NET运行机制
  • .NET中统一的存储过程调用方法(收藏)
  • [2016.7 test.5] T1
  • [2016.7.Test1] T1 三进制异或
  • [ACM独立出版] 2024年虚拟现实、图像和信号处理国际学术会议(VRISP 2024,8月2日-4)
  • [BeginCTF]真龙之力
  • [BUUCTF 2018]Online Tool(特详解)