【学习心得】linux下多客户端批量操作脚本(含expect交互)

时间:2022-06-17 14:20:15

按照惯例先报一下运行环境:实体机ubuntu 12.04.3 LTS

    shell使用GNU bash,版本为4.2.25

需求:ssh免验证登陆。

首先说明一下,这里用发起ssh连接的服务端称为S,接受连接的客户端称为C,配合需求解释一下就是从S发起ssh连接到C通过公私钥配对验证,免去手动输入密码验证。除了需要在服务端S上使用ssh-keygen命令生成密钥对之外,还需要把生成的公钥拷贝到客户端C中,而ssh命令集存在一个命令ssh-copy-id可以指定公钥文件并发送到指定客户端中,在这里我使用了默认生成的私钥和公钥文件名,即id_rsa和id_rsa.pub。而生成密钥对文件的过程中会产生交互操作,所以要实现无人值守批量操作的话需要用到expect这个shell脚本的扩展方法来进行交互操作,expect有自己一套语法,具体可以自己百度。

首先是批量实现ssh免验证登陆脚本keygenSCdi.sh:

#!/usr/bin/expect //声明脚本解释器,由此可见这是一个expect脚本

#deliver the key gen sc to clinet

#keygenSCdi.sh

#author:drowsc

set iplist [open [lindex $argv 0] ] //设定变量iplist从第一个参数传递的外部文件读入
set cmdfile [open [lindex $argv 1] ]


set password "bita\r"                                                  
set timeout 10


        while {[gets $iplist ip] >0} {  //获取iplist变量的值并赋值给变量ip,判断获得的ip地址个数是否大于0
                seek $cmdfile 0
                spawn ssh -p36000 bita@$ip                  //依次远程登录每个客户端

                for {} {1} {} {
                        expect {
                                "password:" {send "$password"}       //出现密码输入提示自动输入密码$password
                                "$" {
                                while { [gets $cmdfile c] > 0 } {
                                    send "$c\r" ; //传递任务文件cmdfile里的内容并执行
                                    expect {
                                        "yes/no)?" { send "yes\r"; exp_continue }             //当客户端回显的结果出现“yes/no)?"的时候应答"yes”并回车
                                        "password:" { send "$password" }
                                     }
                                  }
                                expect "$"
break //执行完任务后跳出for循环并开始连接下一个客户端
                                     }                                                  
                        timeout {puts "timeout";break}//响应超时设置
                }
           }
        }

close $iplist //关闭变量iplist从传参获取的文件内容
close $cmdfile

echo "all key gen complete!!"

接着是使用expect脚本所需的前提,批量给客户机安装expect方法expect_install.sh:

#!/bin/bash
#!/usr/bin/expect
#for install expect funtion on client

#expect_install.sh

#author:drowsc

bitadir=/home/bita/ //设定目录变量
workdir=/home/bita/bisc

for ip in $(cat $workdir"/iplist.txt") //获取iplist.txt里的ip地址并逐一取值赋给变量ip,然后开始循环
do
        ssh  -p36000 bita@$ip << EOF
        echo "bita" | sudo -S apt-get -y install expect//使用apt-get安装expect
        exit
EOF
done

echo "expect install finished!!!"

附所执行的任务文件cmdfile.txt:

echo "bita"|sudo -S chown bita.bita /home/bita/.ssh
ssh-keygen -t rsa -P '' -f /home/bita/.ssh/id_rsa > /dev/null                //在指定路径生成密钥对
cd /home/bita/.ssh
ssh-copy-id  "-p 36000 bita@192.168.11.200"                                     //使用ssh-copy-id命令把默认情况下/home/user/.ssh/目录下的id_rsa.pub公钥文件发出到指定主机的默认ssh密钥存放目录



PS:一.查看当前linux的发行版本方法有1:gnome-system-monitor 2.uname -a(通常查内核版本) 3.cat /etc/ubuntu(发行版本名称)-release 4.cat /etc/issue

      二.查看当前使用的shell:1. ps |grep $$|awk '{print $4}'//不带参数的ps命令显示和当前终端有关的进程状况
//$$变量存储当前进程的PID
//ps第四列是进程所使用的命令,如果是Shell,那么显示shell名,比如sh/ksh等
//awk '{print $4}'就是只显示第四列的值

      三.find -name *.txt -exec cat {} \; //选项-exec可以为find的结果提供后续操作,此处的{} \代表find所得到的结果

    四.关于ssh建立握手验证:一般首次进行ssh登陆时的yes/no是提示是否进行特征码生成并记录到~/.ssh/known_hosts中,若重新使用ssh-keygen生成秘钥则本机生成的新特征码则会跟旧特征码不匹配,导致ssh连接时产生安全报错,此时只要根据错误信息提示删除对应特征码记录即可重新进行验证。