对于登陆单个服务器
1.SSH采用基于公钥和基于私钥的加密技术进行自动化认证。在网上找的自动登陆都是通过ssh-keygen -t rsa语句来创建SSH密钥,并且规定加密类型为rsa,现在~/.ssh/id_rsa.pub和~/.ssh/id_ras已经生成了。id_rsa.pub是生成的公钥,id_ras是生成的私钥。
2.公钥必须添加到远程服务器~/.ssh/authorized_keys文件中,这台服务器也就是我们想从当前主机自动登入的那台服务器。
ssh USER@REMOTE_HOST "cat >> ~/.ssh/authorized_keys" < ~/.ssh/id_rsa.pub
通过以上语句我们就把当前主机的公钥加到远程服务器了,并且已经进入那个服务器了,这一步骤之后会提醒输入密码,之后再通过ssh登陆服务器就不需要再次输入密码了。
对于登陆多个服务器
对于单个服务器,这种方式是可行的,也很方便快捷。但是如果需要登陆很多服务器进行相同的操作的时候(例如查看内存,CPU,磁盘等基础操作),显然重复这样的登陆以及查看是很没有效率的。所以希望通过脚本自动登陆服务器,再进行统一的操作。这时候有expect解释器可以来帮助我们。
在centOS7里面是没有预装expect解释器的,所以我们需要安装。expect是基于TCL语言的,所以也需要安装TCL。至于安装方法百度上面可以搜到很多。
网上很多ssh自动登陆的脚本都是用expect直接实现的。作为一个刚开始使用linux的小白,我刚开始都是用sh a.sh来运行.exp的脚本。完全不知道脚本首行的#!/usr/bin到底有什么作用。发现了这个问题之后,那么就需要用shell实现登陆了,很多直接的代码就不能使用了。
但是还是需要expect来实现模仿输入。所以我认为将expect语句嵌入shell脚本里面是最好的做法。可以通过$EXPECT <<EOF ...... EOF的结构来加入expect语句。(原因:Shell中通常将EOF与 << 结合使用,表示后续的输入作为子命令或子Shell的输入,直到遇到EOF为止,再返回到主调Shell。 可以把EOF替换成其他东西,意思是把内容当作标准输入传给程序。)这里$EXPECT是expect安装路径,可以通过which expect来查看。然后将$EXPECT设置为expect解释器。
所以在EOF里面就可以用expect语句来实现自动操作。以下纪录一下我对于expect的理解。
1.spawn+命令,表示命令后面的内容都会被监督,可以通过expect 来选择自动输入的内容。例如
expect {
"password:" {
send "$pass_word\r"
}
"*#" {
send "\r"
}
}
如果遇到“password:”就发送密码,如果是“#”就输入换行符。一个expect就是一次选择。当然expect里面也可以嵌套expect。
2.expect也可以用正则表达式进行匹配,在匹配的内容之前加上-re,例如-re “password:”
3.set timeout 2 设置超时时间,如果当前语句2秒之内没执行完,会停止当前语句,直接执行下一条语句。
4.expect对格式要求还是很重要的(真的很重要的,因为格式调试了很多次)。建议不用tab来进行缩进,直接空格好了,我用tab缩进总是会报bug。{ }中括号前后最好都加上空格,最好命令和符合之间都记得加空格,会减少很多bug。
5.在不需要与命令互动的时候,可以不用spawn,直接expect "*#" send 就可以在多台服务器的终端输入命令了。send "命令"命令中出现某些符号,需要通过"\"反斜杠来进行转义。具体有哪些符号我也不太了解,所以可以看运行的结果进行修改。
6.sleep 1 的意义是停止一秒再执行下一条语句。防止电脑运行的速度低于脚本执行的速度所导致的命令紊乱。
7.expect "*#" { send "exit\r" }有这样重复的两条命令,并不是写错了==。当只有一条这样的命令的时候,在连接主机的时候并没有退出这台机器。
[root@openbras-test ~]# exit
登出
Connection to 10.217.253.11 closed.
运行的时候并不会出现以上语句。具体原因我也不是很明白。但是只有一条exit的时候,上面的那个expect也不会执行。如果是先ifconfig,再exit,不会出现ifconfig的内容。如果有童鞋们知道这个原因,请告知我,谢谢!
以下附上我的完整代码,当然ip和密码都是不能用的,都是随便编的==。如果要运行,请换上可以使用的。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#!/usr/bin
#通过ssh命令自动登陆以下机器,并打印出CPU、内存、磁盘使用率 (账号/密码:root 66666666,需设置免密钥登陆)
# 10.21.23.1# 10.21.23.7
# 10.21.23.8
# 10.21.23.14
# 10.21.23.16
EXPECT=/usr/bin/expect
for I in 1 7 8 14 16;do
ip=10.21.23.$I
user_name=root
pass_word=66666666
$EXPECT <<EOF
spawn ssh $user_name@$ip
set timeout 2
expect {
"Are you sure you want to continue connecting (yes/no)?" {
send "yes\r";exp_continue
}
"password:*" {
send "$pass_word\r"
}
"*#"{
send "\r"
}
}
expect {
"password:" {
send "$pass_word\r"
}
"*#" {
send "\r"
}
}
sleep 1
expect "*#" { send "top -n 1| grep 'Cpu' \r" }
sleep 1
expect "*#" { send "free -m|grep 'Mem' |awk -F' ' '{print \$ 3/\$ 2}' \r" }
sleep 1
expect "*#" { send "df -h | awk '{print \$ 1,\$ 5}' OFS='|' \r" }
sleep 1
expect "*#" { send "exit\r" }
sleep 1
expect "*#" { send "exit\r" }
exit
EOF
done学习