zoukankan      html  css  js  c++  java
  • expect配合shell 实现自动分发秘钥文件

    expect使用场景

    有时候需要批量地执行一些操作,或者执行自动化的操作的时候,有些指令需要交互式地进行这就会有很多麻烦,linux下有一个程序交expect,它可以模拟键盘输入文本,省去人工干预交互式的指令

    expect工作方式

    首先使用 spawn 开启一个会话,然后使用 expect-send 对来执行交互式操作。
    spawn 后面跟上一个命令操作,表示开启一个会话。expect 等待输出特定的字符串(通常是提示符),然后使用send 发送交互字符串。比如:

    spawn ssh username@host # 远程登录
    
    expect "*assword" # 提示为:"username@host's password:", 等待用户输入密码
    send "${password}
    " # 这时使用send模拟用户输入密码的字符串,完成登录验证
    

    安装expect

    正常情况下linux默认没有安装这个软件,需要自己安装;

    [root@localhost ~]# yum install expect -y
    

    基本语法使用

    expect可以写成独立的格式,脚本格式为

    #!/usr/bin/expect
    

    也可以嵌套在shell脚本中使用
    set
    设置会话超时时间
    set timeout 5
    spawn
    spawn 后面跟一个shell命令,就是开启了一个会话
    例如:

    spwan scp f1.txt 192.168.214.111:/home
    

    expect-send

    expect接收 spwan 后面的命令执行的输出,然后和期望字符串匹配,若对应匹配则执行相应的send来发送交互信息;
    expect 使用 ‘{ }’表示一组表达式,且花括号前后要留空格
    例如:

    expect "(yes/no)" {send "yes
    "}
    # "(yes/no)"   是期望匹配的字符串
    #{ send "yes
    "; exp_continue } expect 匹配到字符串后执行模拟输入的内容
    

    expect还可以使用多字符匹配:如下

    expect {
        "(yes/no)" { send "yes
    "; exp_continue }
        "password:" { send "$password
    " }
    }
    

    结束符

    expect eof
    expect脚本必须以interact或expect eof结束,执行自动化任务通常expect eof就够了

    expect一般用于登录ssh服务器,除了ssh命令输入密码外,还有scp也是需要密码输入的,因此expect与scp结合起来使用的场景也是很多的。

    实例:自动推送秘钥文件到远程主机

    试想,如果要实现一些自动化的工作时,免密远程登录是必不可少的,假如在部署ansible前要将ansible的秘钥文件推送给100台服务器,这个时候在脚本中使用scp指令避免不了要进行交互式地应答,(使用ansible的authoried_keys模块的方式推送就另说了)这个时候就需要使用expect来进行自动应答地执行了
    编写shell脚本,在脚本中调用expect来实现自动向远处主机推送秘钥:

    #!/bin/bash
    
    keypath=/root/.ssh
    [ -d ${keypath} ] || mkdir -p ${keypath}
    rpm -q expect &> /dev/null || yum install expect -y
    ssh-keygen -t rsa -f /root/.ssh/id_rsa  -P ""
    password=123456
    while read ip;do
    expect <<EOF
    set timeout 5
    spawn ssh-copy-id $ip
    expect {
    "yes/no" { send "yes
    ";exp_continue }
    "password" { send "$password
    "  }
    }
    expect eof
    EOF
    done < /home/ip.txt
    

    执行结果:要分发秘钥的主机会自动生成秘钥文件并将秘钥文件推送给ip.txt文件列表中的主机

    [root@Ansible script]# ./autokey.sh 
    Generating public/private rsa key pair.
    Your identification has been saved in /root/.ssh/id_rsa.
    Your public key has been saved in /root/.ssh/id_rsa.pub.
    The key fingerprint is:
    96:4d:4b:be:be:54:d8:54:98:4c:24:be:6d:ef:6d:53 root@Ansible
    The key's randomart image is:
    +--[ RSA 2048]----+
    |          .+oo.  |
    |         . .+.   |
    |          + .    |
    |         * B     |
    |        S * =    |
    |       .   + .  E|
    |          o   . .|
    |         o   . o.|
    |          o.  ..o|
    +-----------------+
    spawn ssh-copy-id 192.168.214.128
    The authenticity of host '192.168.214.128 (192.168.214.128)' can't be established.
    RSA key fingerprint is af:6f:6a:b1:40:b9:ab:c2:05:a4:04:3e:0d:df:1a:e0.
    Are you sure you want to continue connecting (yes/no)? yes
    Warning: Permanently added '192.168.214.128' (RSA) to the list of known hosts.
    root@192.168.214.128's password: 
    Now try logging into the machine, with "ssh '192.168.214.128'", and check in:
    
      .ssh/authorized_keys
    
    to make sure we haven't added extra keys that you weren't expecting.
    
    spawn ssh-copy-id
    Usage: /usr/bin/ssh-copy-id [-i [identity_file]] [user@]machine
    expect: spawn id exp4 not open
        while executing
    "expect eof"
    

    测试一下:

    [root@Ansible script]# ssh 192.168.214.128 'hostname'
    localhost.localdomain
    
  • 相关阅读:
    网络--会话层、表示层、应用层
    Unix C
    操作系统原理
    TCP/UDP
    config OSX firewall programmatically
    Objective-C 浅谈
    OS X background process
    CreateProcessWithToken 1058 error
    WebBrowser keystroke
    MFC加载PNG图片并实现双缓冲
  • 原文地址:https://www.cnblogs.com/anay/p/9059548.html
Copyright © 2011-2022 走看看