先抛出一个问题
现在有两台Linux主机A和B,如何从A主机ssh到B主机,然后在B主机上执行命令,如何使这个过程实现全程自动化?你可能会使用这种方法:
ssh admin@10.220.20.15 "ls"
但是这种方式比较笨拙,每次都要输入密码,同时并不能执行一些复杂的逻辑或命令。
expect是什么?
expect是一个免费的编程工具,用来实现自动的交互式任务,而无需人为干预。说白了,expect就是一套用来实现自动交互功能的软件。
在实际工作中,我们运行命令、脚本或程序时,这些命令、脚本或程序都需要从终端输入某些继续运行的指令,而这些输入都需要人为的手工进行。而利用expect,则可以根据程序的提示,模拟标准输入提供给程序,从而实现自动化交互执行。这就是expect!!!
expect就是用来帮助ssh登录输入账号密码的(当然不止这一个点)
vim expect.sh
注意这里的expect后面的选项相当于case,遇到什么就怎么处理,但是一个expect对应只能处理一次,如果还有后续的操作就继续再写一个expect{}
#!/usr/bin/expect
set ip 192.168.122.52 #设置变量
set user root
set password centos
set timeout 5 设置5秒后无响应则退出
spawn ssh $user@$ip #开启一个会话
expect{
"yes/no" { send "yes\r"; exp_continue } //期待出现"yes/no"字段,出现后再执行{}内的send "yes\r";没出现则执行exp_continue ,exp_continue的作用是如果yes/no这个字符串没有出现的话,则跳过
"password:" { send "$password\r" };同理
}
interact 最后停在对方那边,即可以使用对方的机器了
使用位置参数 类似于bash的$1 $2
lindex $argv 0
#!/usr/bin/expect
set ip [lindex $argv 0] #这里
set user [lindex $argv 1]
set password centos
set timeout 5
spawn ssh $user@$ip
expect{
"yes/no" { send "yes\r"; exp_continue }
"password:" { send "$password\r" };
}
继续expect
expect "#" 即命令行后面的#号
send "useradd y\r"
send "pwd\r"
send "exit\r"
expect eof 完事结束,断开连接
传文件
#!/usr/bin/expect
set ip [lindex $argv 0] #这里
set user [lindex $argv 1]
set password centos
set timeout 5
spawn scp -r /etc/hosts $user@ip:/tmp 将/etc/hosts传到$user@ip:/tmp下
expect{
"yes/no" { send "yes\r"; exp_continue }
"password:" { send "$password\r" };
}
expect eof 完事结束,断开连接
bash中插入expect脚本
#!/usr/bin/bash
>ip.txt 清空ip.txt
password=centos
for i in {2..254}
do
{
ip=192.168.122.$i
ping -c1 -W1 $ip &>/dev/null
if [ $? -eq 0 ];then
echo "$ip" >> ip.txt
/usr/bin/expect <<-EOF
spawn ssh-copy-id $ip
expect {
"yes/no" { send "yes\r"; exp_continue }
"password:" { send "$password\r" }
}
expect eof
EOF
fi
}&
done
wait
echo "finish......"
更好的版本,提供了可能出现的情况的处理
#!/usr/bin/bash
>ip.txt 清空ip.txt
password=centos
rpm -q expect &>/dev/null 检查有没有装expect
if [ $? -ne 0 ];then
yum -y install expect
fi
if [ ! -f ~/.ssh/id_rsa ];then 检查秘钥对有没有(貌似expect会自动给你创建,所以这一步可能没有必要)
ssh-keygen -P "" -f ~/.ssh/id_rsa
fi
for i in {2..254}
do
{
ip=192.168.122.$i
ping -c1 -W1 $ip &>/dev/null
if [ $? -eq 0 ];then
echo "$ip" >> ip.txt
/usr/bin/expect <<-EOF
spawn ssh-copy-id $ip
expect {
"yes/no" { send "yes\r"; exp_continue }
"password:" { send "$password\r" }
}
expect eof
EOF
fi
}&
done
wait
echo "finish......"
缩进一定是要用tab键,不能用空格 可以在vim中用:set list查看缩进:set nolist 退出查看
ps:
回车 \r