# 批量实现SSH无密码登陆认证脚本
## 问题背景
使用为了让linux之间使用ssh不需要密码,可以采用了数字签名RSA或者DSA来完成。主要使用ssh-key-gen实现。
1.通过 ssh-key-gen 来创建 public and private keys
2.使用ssh-copy-id复制public key 到远程主机
3.无密码登陆远程主机
## 脚本实例
但对于大规模集群,人工使用ssh-key-gen生成key,再使用ssh-copy-id显然费时费力。对于N台主机,需要进行N次ssh-key-gen,N*N次ssh-copy-id。
为此,写了一个批量SSH key-gen脚本,脚本包括四个文件:keygen_master.sh、keygen_slave.sh、hosts.conf、slaves.conf
## 使用方法
使用方法比较简单。把这四个文件拷贝到主节点上,设置hosts.conf和slaves.conf,然后执行keygen_master.sh即可。
**keygen_master.sh在主节点上执行**
```
[root@localhost ~]# cat keygen_master.sh
#!/bin/sh
this="$0"
while [ -h "$this" ]; do
ls=`ls -ld "$this"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '.*/.*' > /dev/null; then
this="$link"
else
this=`dirname "$this"`/"$link"
fi
done
# init base path
base=`dirname "$this"`
script=`basename "$this"`
base=`cd "$base"; pwd`
this="$base/$script"
slavesh="keygen_slave.sh"
slavescript="$base/$slavesh"
slaves="$base/slaves.conf"
hosts="$base/hosts.conf"
# install ssh
yum install -y openssh* expect
eval `ssh-agent`
if [ ! -s ~/.ssh/id_dsa ]; then
expect -c "
spawn ssh-keygen -t dsa
expect {
\"*y/n*\" {send \"y\r\"; exp_continue}
\"*key*\" {send \"\r\"; exp_continue}
\"*passphrase*\" {send \"\r\"; exp_continue}
\"*again*\" {send \"\r\";}
}
"
fi
ssh-add $HOME/.ssh/id_dsa # Add private key
# batch ssh
if [ -s $hosts ]; then
for p in $(cat $hosts) #
do
username=$(echo "$p"|cut -f1 -d":") # Get username
ip=$(echo "$p"|cut -f2 -d":") # Get ip
password=$(echo "$p"|cut -f3 -d":") # Get password
id=$HOME/.ssh/id_dsa.pub
echo "ssh-copy-id -i $id $username@$ip -P $password"
# ssh-copy-id
expect -c "
spawn ssh-copy-id -i $id $username@$ip
expect {
\"*yes/no*\" {send \"yes\r\"; exp_continue}
\"*password*\" {send \"$password\r\"; exp_continue}
\"*Password*\" {send \"$password\r\";}
}
"
done
fi
# dispath
if [ -s $slaves ]; then
for p in $(cat $slaves) #
do
username=$(echo "$p"|cut -f1 -d":") # Get username
ip=$(echo "$p"|cut -f2 -d":") # Get ip
password=$(echo "$p"|cut -f3 -d":") # Get password
id=$HOME/.ssh/id_dsa.pub
ssh $username@$ip 'yum install -y openssh*'
echo "scp $slavescript $hosts $username@$ip:~/ -P $password"
# Dispath to clients
expect -c "
spawn scp $slavescript $hosts $username@$ip:~/
expect {
\"*yes/no*\" {send \"yes\r\"; exp_continue}
\"*password*\" {send \"$password\r\"; exp_continue}
\"*Password*\" {send \"$password\r\";}
}
"
# ssh to clients
echo "ssh $username@$ip 'sh $HOME/keygen_slave.sh'"
ssh $username@$ip 'sh $HOME/keygen_slave.sh'
done
fi
```
**keygen_slave.sh在所有从节点执行**
```
[root@localhost ~]# cat keygen_slave.sh
#!/bin/sh
this="$0"
while [ -h "$this" ]; do
ls=`ls -ld "$this"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '.*/.*' > /dev/null; then
this="$link"
else
this=`dirname "$this"`/"$link"
fi
done
# init base path
base=`dirname "$this"`
script=`basename "$this"`
base=`cd "$base"; pwd`
this="$base/$script"
hosts="$base/hosts.conf"
echo $base
echo $script
echo $this
echo $hosts
# install ssh
yum install -y openssh* expect
eval `ssh-agent`
if [ ! -s ~/.ssh/id_dsa ]; then
expect -c "
spawn ssh-keygen -t dsa
expect {
\"*y/n*\" {send \"y\r\"; exp_continue}
\"*key*\" {send \"\r\"; exp_continue}
\"*passphrase*\" {send \"\r\"; exp_continue}
\"*again*\" {send \"\r\";}
}
"
fi
ssh-add $HOME/.ssh/id_dsa # Add private key
# batch ssh
if [ -s $hosts ]; then
for p in $(cat $hosts) #
do
username=$(echo "$p"|cut -f1 -d":") # Get username
ip=$(echo "$p"|cut -f2 -d":") # Get ip
password=$(echo "$p"|cut -f3 -d":") # Get password
id=$HOME/.ssh/id_dsa.pub
echo $username
echo $ip
echo $password
echo $id
# ssh-copy-id
expect -c "
spawn ssh-copy-id -i $id $username@$ip
expect {
\"*yes/no*\" {send \"yes\r\"; exp_continue}
\"*password*\" {send \"$password\r\"; exp_continue}
\"*Password*\" {send \"$password\r\";}
}
"
done
fi
```
**hosts.conf中设置所有主机(主节点+从节点),格式为用户名:主机IP:用户密码**
```
username:master_ip:passwd
username:client1_ip:passwd
username:client2_ip:passwd
#root:localhost:000000
```
**slaves.conf中设置所有从主机,格式同hosts.conf用户名:主机IP:用户密码**
```
username:client1_ip:passwd
username:client2_ip:passwd
#root:192.168.1.12:000000
```