linux shell脚本批量创建公钥
为实现对多台服务器部署服务,如果只用交互方式输入密码,耗时耗力,因此必须考虑自动化部署,查询资料发现expect方式可以实现。
一、介绍
expect脚本是Tcl脚本语言的拓展。用来实现自动的交互式任务,无需人为干预。在实际开发中,运行shell脚本有时候会输入linux密码或者是mysql密码等,而expect可以帮我们输入。
二、安装
expect在linux系统中没有自带,需要我们自行安装,在centos系统下,安装命令如下
yum install expect -y
三、常用命令说明
命令 | 说明 |
---|---|
set timeout n | 设置expect语句超时时间为n秒。-1为永不超时 |
set name value | 设置变量名为name,其值为value |
set name [lindex $argv 0] | 设置变量名为name,其值为 传入 expect脚本的第一个 参数 。第一个参数的索引值为0,第二个为1,依次类推 |
spawn | 启动新的进程,执行命令或者指定程序 |
expect | 接收进程中返回的信息, 如果匹配成功(有大小写区分), 就执行expect后的动作 |
send | 向进程发送字符串 |
send_user | 用来打印信息,相当于shell中的echo |
exp_continue | 执行完expect后的动作后,使expect不退出,继续往下匹配 |
expect eof | 不允许用户交互,直接退出(这个用的会比interact多) |
interact | 允许用户交互 |
四、案例
#!/usr/bin/bash
# 利用expect实现批量公钥的传送,方便后续批量部署
>ip.txt
password=1111
# user=ljw
#判断公钥是否存在,不存在创建
if [ ! -f ~/.ssh/id_rsa ];thenssh-keygen -P "" -f ~/.ssh/id_rsa
fifor i in {12..16}
do{ip=192.168.10.$iping -c1 -W1 $ip &>/dev/nullif [ $? -eq 0 ];thenecho "$ip" >> ip.txt/usr/bin/expect <<-EOFset timeout 10 spawn ssh-copy-id $ipexpect {"yes/no" { send "yes\r"; exp_continue }"password:" {send "$password\r"}}expect eofEOFfi}& #后台执行
done
wait
解释:
#!/bin/bash => shell脚本执行,如果不需要shell,而是全部expect,则可以:#!/usr/bin/expect
/usr/bin/expect <<-EOF => 此处开始执行expect脚本,记住EOF前面的“-”
expect中最关键的四个命令是send,expect,spawn,interact。
send:用于向进程发送字符串
expect:从进程接收字符串
spawn:启动新的进程
interact:执行完成后保持交互状态,把控制权交给控制台,这个时候便可以手工操作。如果没有该命令,命令完成后即退出
1、spawn命令是Expect的初始命令,它用于启动一个进程,之后所有expect操作都在这个进程中进行,如果没有spawn语句,整个expect就无法再进行下去了
spawn ssh-copy-id $ip; =>启动expect操作进程
2、expect 是针对需要交互的地方进行自动发送消息,{ 大扣号前面必须要有空格,前面引号内的内容是交互界面等待输入的匹配字串,{} 内的是交互输入的内容:
a、send 发送数据,最后的\r必需,说明输入密码并回车了
b、exp_continue 继续处理下一步命令
expect eof =>此命令和spawn 是匹配的,spawn进程结束后会向expect发送eof,表示退出spwan
EOF 解除expect脚本执行,跳出到shell执行环境
五、 <<EOF和<<-EOF的区别
在我们使用cat <<EOF
时,我们输入完成后,需要在一个新的一行输入EOF
结束stdin的输入。EOF
必须顶行写,前面不能用制表符或者空格。
比如,下面的语句就不会出错:
cat <<EOF
Hello,world!
EOF
如果结束分解符EOF
前有制表符或者空格,则EOF
不会被当做结束分界符,只会继续被当做stdin来输入。
而<<-
就是为了解决这一问题:
cat <<-EOF
Hello,world! EOF
上面的写法,虽然最后的EOF前面有多个制表符和空格,但仍然会被当做结束分界符,表示stdin的结束。