一、背景
大家在使用linux系统的很多时候,都用linux指令来实现一些操作,执行特定的job,有时一些场景中需要执行交互指令来完成任务,比如ssh登录这个命令大家一定很熟悉:
ssh-keygen -t rsa
# 以及
ssh-copy-id -i /home/test/.ssh/id_rsa.pub $username@$host_name
以上两条指令执行任务需要按三次回车键,或输入yes/no
以及密码
才可以。当然,如果是单点操作的话,还是相对简单。
但是比如我们要在一个集群规模的每个节点都进行上面的操作,那么会非常繁琐。所以此时我们就应该用脚本来管理它,让重复劳动交给机器,自动化执行以上命令。
下面我们的主角来了,expect。
二、expect
expect是一款免费的强大的工具,适用于人机交互场景,是处理交互的常用命令,可以将交互的过程写成一个脚本,通过调用脚本完成自动化过程,可无需人工干预。
Expect是一个基于Tcl语言的脚本工具。
其有以下关键命令:
1、安装
安装该命令非常简单。
yum install -y expect
2、基本语法
- 首行/usr/bin/expect,声明使用except组件,类似/bin/sh用法。
- spawn: spawn + 需要执行的shell命令
- expect: 只有spawn执行的命令结果才会被expect捕捉到,因为spawn会启动一个进程,只有这个进程的相关信息才会被捕捉到,主要包括:标准输入的提示信息,eof和timeout。
- send和send_user:send会将expect脚本中需要的信息发送给spawn启动的那个进程,而send_user只是回显用户发出的信息,类似于shell中的echo而已。
#!/usr/bin/expect
# 2025/01/19 hhd
spawn ssh test
expect {
"yes/no" {send "yes\r";exp_continue}
"password*" {send "test\r"}
}
expect eof
# or
# interact
注意:expect脚本文件的头信息与bash不同
三、使用示例
1、基于key的expect自动化运行脚本
1、使用dsa算法:
ssh-keygen -t dsa # 使用dsa算法生成密钥,默认id_rsa2、ssh指定密钥地址,并进行加密:(防止私钥被偷走场景)
ssh-keygen -p -f id_dsa
验证加密场景:
ssh ip地址3、可以使用启用代理的方式,避免重复输入口令:
ssh-agent bash # 启用代理
ssh-add # 将加密口令添加到代理,窗口关闭后需要重新启动4、通过脚本执行基于key验证,管理多台机器的expect脚本:
ssh-keygen -t rsa -P "" -f /root/.ssh/id_rsa
#!/bin/bash
PASS=真实密码
ssh-keygen -t rsa -P "" -f /root/.ssh/id_rsa &> /dev/null && echo "ssh key is created"
rpm -q expect &> /dev/null || yum -y install expect &> /dev/null
while read IP;do
expect << EOF
set timeout 20
spawn ssh-copy-id -i /root/.ssh/id_rsa.pub root@$IP
expect {
"yes/no" { send "yes\n" }
"password" { send "$PASS\n" }
}
expect eof
EOF
echo $IP is read
done < hosts.txt
或者使用另一种方式:
#! /usr/bin/expect
# 1.make sure expect exist!
rpm -q expect &> /dev/null
if [ $? -ne 0 ];then
yum -y install expect
fi
# 2.make sure public key exist!
password='xxx'
if [ ! -f ~/.ssh/id_rsa ];then
ssh-keygen -P "" -f ~/.ssh/id_rsa
fi
# 3.interactive process
for i in {178..180}
do
{
ip=192.168.8.$i
ping -c1 -W1 $ip &> /dev/null
if [ $? -eq 0 ];then
echo "$ip" >> hosts.txt
/usr/bin/expect <<- EOF
set timeout 10
spawn ssh-copy-id $ip
expect {
"yes/no" { send "yes\r"; exp_continue }
"password:" { send "$password\r" }
}
expect eof
EOF
fi
}&
done
wait
echo "ssh-key is finished"
集群环境内的所有的主机共用一套公钥和私钥:实现所有主机之间可以互连
ssh-copy-id -i .ssh/id_rsa.pub 127.0.0.1 # 公钥复制到自己的主机上
scp -r /root/.ssh/ 192.172.20.50:/root/ # 拷贝ssh到目标主机上
注释:ssh-keygen
ssh-keygen(选项) - - 为ssh生成、管理和转换认证密钥
-f:指定用来保存密钥的文件名;
-P:提供(旧)密语;
-t:指定要创建的密钥类型。
2、实现远程拷贝文件到本地
#/user/bin/expect
spawn scp -P 22 -r root@192.168.1.128:/etc/* /home/test/
expect{
"(yes/no)?"{
send "yes\n"
expect "*password:"{
send "root@123\n"
}
}
"*password:"{
send "root@123\n"
}
}
expect "100%"
expect eof