shell结合expect实现ssh批量免密登录

一、运行准备

系统环境:Linux操作系统(Centos7)
在执行脚本的主机上安装tcl和expect包,部署expect脚本运行环境

安装tcl

#下载tcl包
wget http://nchc.dl.sourceforge.net/sourceforge/tcl/tcl8.4.11-src.tar.gz
#解压
tar xfvz tcl8.4.11-src.tar.gz
#编译安装
cd tcl8.4.11/unix
./configure --prefix=/usr/tcl --enable-shared
make && make install
#安装完毕以后,进入tcl源代码的根目录,把子目录unix下面的tclUnixPort.h copy到子目录generic中
cp ~/tcl8.4.11/unix/tclUnixPort.h copy ~/tcl8.4.11/generic/

注:暂时不要删除tcl源代码,因为expect的安装过程还需要用。

安装expect

#下载
wget http://sourceforge.net/projects/expect/files/Expect/5.45/expect5.45.tar.gz
#解压
tar xzvf expect5.45.tar.gz
#编译安装
cd expect5.45
./configure --prefix=/usr/expect --with-tcl=/usr/tcl/lib --with-tclinclude=../tcl8.4.11/generic
make && make install
ln -s /usr/expect/bin/expect /usr/expect/bin/expect
ln -s /usr/expect/bin/expect /usr/bin/expect

此时,在命令行中输入expect应该有如下显示

[root@mongo3 sshTest]# expect 
expect1.1> 

二、文件说明

名称 说明
ipAndpasswd.txt IP及其密码记录文件
sshPassLogin.sh shell脚本文件
sshPassResult时间戳.txt 批量主机免密登录结果记录文件,每次运行得到的文件名都不同

注:ipAndpasswd.txt中的IP只要是有密码,那么密码必须是正确的,不然脚本运行时会出错


ipAndpasswd.txt记录,以空格为分隔,第一列是IP,第二列是IP对应的密码

三、脚本说明

利用expect自动化执行ssh-copy-id命令,并与远程终端进行交互。先提取ipAndpasswd.txt中有密码的IP,逐个进行免密登录(将本机公钥发送到远程主机),成功登陆将记录success在sshPassResult时间戳.txt中;在ipAndpasswd.txt中没有密码的IP将会追加在sshPassResult时间戳.txt末尾。

四、运行结果

[root@mongo3 sshTest]#./sshPassLogin.sh

注:如果第一次的时候报错,提示免密登录配置失败,有可能是网络的问题,我在第一次执行脚本时也遇到过了。等待一段时间之后,重新执行一次脚本就好。


运行结果.png

验证免密登录主机A.png

验证免密登录主机B.png

对于已经设置过ssh免密登录的IP,脚本也会将IP记录为success状态

注:以下特殊情况同样能正确记录:1.之前做过免密登录,现仍可以免密登录,记录为success;2.之前做过免密登录,现不能免密登录,没有了authorized_keys文件:将重新复制公钥到机器上,并记录为success

五、完整代码

function sshpass(){
    local host=$1
    local username=$2
    local passwd=$3
    local ofile=$4
    #expect交互脚本,执行ssh-copy-id username@ip的命令
    /usr/bin/expect<< EOF
    proc sshLogin { host username passwd ofile} {
        set file [open $ofile a]
        set timeout 60
        spawn ssh-copy-id $username@$host
        expect {        
          "yes/no" {send "yes\r"}
          "*install the new keys*" {puts \$file "$host success";exp_contin
ue}
          "password:" {send "$passwd\r"}
          "*already exist*" { 
                puts \$file "$host success";
           }
          close $file
        }
        expect eof
}
    sshLogin "$host" "$username" "$passwd" "$ofile"

EOF
}

username=root
ofile="sshPassResult`date +%Y%m%d%H%M%S`.txt"
remoteInfo="ipAndpasswd.txt"
#awk从loginResult.txt提取有密码的IP及其密码信息;用cut切割出IP和密码
awk '{if($2!=null){print $0}}' $remoteInfo | while read LINE
do
        host="`echo "$LINE" | cut -d ' ' -f 1`"
        passwd="`echo "$LINE" | cut -d ' ' -f 2`"
        echo "#####对$host进行ssh免密登录#####"
        sshpass $host $username $passwd $ofile
        grep -q "$host" $ofile
        if [ $? -eq 0 ];then
                echo "*****$host success*****"
        else
                echo "*****$host fail*****"
                echo "$host fail" >> $ofile
        fi
done
#将没有密码的IP追加到sshResult.txt中
awk '{if($2==null){print $0" nopasswd"}}' $remoteInfo >> $ofile
if [ $? -eq 0 ];then
        echo "$ofile save!"
fi

小结

这是我的第一篇简书,表达上还有很多不足的地方,我会继续努力的~如果大家遇到了什么问题,欢迎评论留言呐!

安装步骤参考(转):
https://www.cnblogs.com/daojian/archive/2012/10/10/2718390.html
expect用法参考(转):
https://blog.csdn.net/a9254778/article/details/78636653
https://blog.csdn.net/boyishachang/article/details/8677936

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容