原因:
100多台服务器的用户密码修改,要求速度快。(几百台还可以,上千台的话expect速度慢。它本来就不快)
说明:
共三个文件,如下:
ip.txt 文本文件,所有待修改密码的服务器ip放这里,一行一个,无空行。
expect.exp expect程序,单纯修改密码,被循环调用,需有执行权限x。
change-passwd.sh 主程序,直接执行它即可,需有执行权限x。
如何运行:
三个文件放在同一目录下,根据具体情况设置你的ip和其他参数,赋予执行权限,直接执行change-passwd.sh即可。
程序流程分析:
直接执行change-passwd.sh,按要求输入所有ip的文件名,如ip.txt
程序会先用nmap分析ip.txt里所有主机及其22端口是否正常(也可以是其他SSHD端口,根据你的具体情况设置),正常的ip则导入到goodip.txt文件供expect.exp使用;无响应的则导入到badid.txt,供你以后分析原因。这样会迅速淘汰那些网络不通的超时的或SSHD服务异常的主机。
接下来会清空$HOME/.ssh/known_hosts文件,避免旧KEY影响SSH连接。
下面就是循环调用expect.exp子程序修改密码;成功的不管,由于其他原因修改不成功的会把其IP导入到fail_ip.txt文件,供你以后查找分析解决,如某些服务器的旧密码可能和你这里设定的不符之类的原因。
最后完成后会生成$LOG文件,可以分析它,然后删除之。安全原因。
文件详情:
--------------------------------------------------------------------
cat ip.txt
192.168.0.5
192.168.0.6
192.168.0.x
......
---------------------------------------------------------------------
cat expect.exp
#!/usr/bin/expect -f
#
set force_conservative 0 ;# set to 1 to force conservative mode even if
;# script wasn't run conservatively originally
if {$force_conservative} {
set send_slow {1 .1}
proc send {ignore arg} {
sleep .1
exp_send -s -- $arg
}
}
set timeout 5 #5秒超时。若你网络差就改大。嗯,是的,越大就越慢。
spawn ssh [lindex $argv 0]@[lindex $argv 1] -p22
match_max 100000
expect -exact "(yes/no)?"
send -- "yes\r"
expect -exact "assword:"
send -- "[lindex $argv 2]\r"
expect -exact "$"
send -- "passwd\r"
expect -exact "assword:"
send -- "[lindex $argv 2]\r"
expect -exact "New password:"
send -- "[lindex $argv 3]\r"
expect -exact "Retype new password:"
send -- "[lindex $argv 3]\r"
expect -exact "$"
send -- "exit\r"
-----------------------------------------------------------------------
cat change-passwd.sh
#!/bin/bash
#201105 version 0.0.2
#This shell will change user password,use expect.
DATE=`date +%Y%m%d" "%H:%M:%S`
LOG=/tmp/expectlog.$$.$RANDOM.log
TMPFILE=$RANDOM.log
GOODIPFILE=goodip.txt
BADIPFILE=badip.txt
FAILIP=fail_ip.txt
USERNAME=yourname
OLDPASSWD=xxxxxx #注意特殊字符要加转义\,如“$”,需要写成“\$”. 可事先用autoexpect -p ssh x.x.x.x -p 22 命令记录一个你的修改密码过程,然后查看生成的script.exp,看你的特殊字符到底该如何转义。方便不是。不用死记expect的字符哪些需要转义。
NEWPASSWD=yyyyyy #同上
SSHKEYFILE=$HOME/.ssh/known_hosts
#if host and 22 port is good,check out to goodip.txt
echo -e "Please input the all ip file name:"
read ALLIPFILE
echo -e "Begin check host and port..."
nmap -sT -p22 -v -i $ALLIPFILE|awk -F'[)(]' '/^Host.*good.$/{print $2 >"'"$GOODIPFILE"'"}/^Host.*skipping it.$/{print $2 >"'"$BADIPFILE"'"}'
echo -e "Total number ip is `wc -l $ALLIPFILE`"
echo -e "Good ip number ip is `wc -l $GOODIPFILE`"
echo -e "Bad ip number ip is `wc -l $BADIPFILE`"
#change the username passwd with expect.exp
echo -e "Continue? Please input (y/n)"
read CONTINUE
if [ $CONTINUE = "y" ]
then
echo -e "BEGIN--->"
echo -e "We will clean the $HOME/.ssh/known_hosts,please input (y/n)"
read INPUT
if [ $INPUT = "y" ]
then
echo >$SSHKEYFILE
if [ $? -eq 0 ]
then
echo "Ok,$SSHKEYFILE has been cleand.We will go..."
echo $DATE>>$LOG
for i in `cat $GOODIPFILE`
do
./expect.exp $USERNAME $i $OLDPASSWD $NEWPASSWD >>$LOG
done
echo -e "<---END"
echo -e "Failed ip is(are):($FAILIP)"
#this awk shell will select these ip of change passwd failed.
awk -v var="" '/^'"$USERNAME"'@[0-9]/{gsub(/('"$USERNAME"'@)||([^0-9]s password:.*$)/,"");var=$0};/current/{print var > "'"$TMPFILE"'"}' $LOG
grep -vFf $TMPFILE $GOODIPFILE > $FAILIP
cat $FAILIP
rm -f $TMPFILE
#$LOG must been deleted.Because username and passwd had included by $LOG.
#If you check the error in $LOG,can delete it after check it.
#rm -f $LOG
else
echo "Sorry,$SSHKEYFILE has not been cleand,please check it."
exit
fi
else
echo "Sorry,$SSHKEYFILE must been cleand.Otherwise the ssh connect server will faild and expect will faild also."
exit
fi
else
echo -e "Ok,bye."
exit
fi
--------------------------------------------------------------------
---end---
阅读(2148) | 评论(0) | 转发(0) |