前言
此脚本虽然是
python
脚本,但是里面调用了太多
os.system
命令
(
囧,哥的
python
太水了
)
,只要懂
shell
脚本,就可用
shell
来完成自动配置
ssh
互信脚本。为何当初没有使用
except
,因为本公司的
centos
中没有携带
except
安装包,
centos
还是精简版,很多依赖包都没有。我不想太折腾。
我会一点
python,
使用
python
是理所当然的。原计划用
python paramiko
模块来实现密码放文件里登陆,但是
paramiko
安装编译需要
gcc
环境。精简的
centos
也没有,弄了半天,几十个依赖包弄得我头晕眼花,大小达到
50M
,不通用,懒得做了。
现在的这个脚本需要手动输入远程主机密码,不适用于成百上千台服务器部署
ssh
互信。在网上找了很久,确认
ssh
不支持脚本输入密码。
由于我的业务上经常也就同时做
10
台以内的
ssh
互信,这个脚本就满足需求了。
ssh
配置互信重点
1
、不交互自动生成密钥文件
用
ssh-keygen
的
-f
和
-P
参数,生成密钥不需要交互。如下:
rm -rf ~/.ssh/
/usr/bin/ssh-keygen -t rsa -f ~/.ssh/id_rsa -P ”
cp ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys
2
、
自动添加
/etc/hosts
中主机名与
IP
对应关系,并推送到远端主机
这个简单,手动配置或脚本配置都行。互信成功后,用脚本批量推送就行了。
3
、推送密钥文件至远端主机
最简单的方法:
scp -r /root/.ssh root@hostb:/root
但是咱公司精简的
centos
没有关闭
selinux
。拷贝过去还是不能无密码登陆
(
不信可自己测试
)
。如果采用输入两次密码,第一次登陆上去关闭
selinux
,第二次拷贝
/root/.ssh
过去也可以
(
不想梅开二度
)
。我采用的是另一种方法,只需输入一次密码即可。怎么实现的?见代码。
第一次登陆交互需要输入
yes
获取对端公钥
.ssh
文件拷贝过去后,第一次登陆会让你输入
yes
接收公钥,而且,不止自己登陆对方要输入
yes,
每一台登陆远端主机都要输入
yes,
如果一共
10
台服务器,每台输入
9
次,共需要输入
81
次。这个怎么破?见代码。
执行效果
[root@VueOS scripts]#
python ssh_trust.py
Input node’s info. Usage:hosta/192.168.0.101. Press Enter is complete.
Please input Node info:
nodea/192.168.2.151
#
获取节点信息,主机名与
IP
,生产中尽量使用主机名,方便以后环境迁移
check ip address success!
Input node’s info. Usage:hosta/192.168.0.101. Press Enter is complete.
Please input Node info:
nodeb/192.168.2.158
check ip address success!
Input node’s info. Usage:hosta/192.168.0.101. Press Enter is complete.
Please input Node info:
Are you sure you want to set ssh mutual trust? (yes/no)
yes
#
是否要设置互信?
因为本次互信是我部署其它程序的前提。互信一次就能配置成功,程序可能多次失败,不需要每次运行都做互信。
Generating public/private rsa key pair.
Created directory ‘/root/.ssh’.
Your identification has been saved in/root/.ssh/id_rsa.
Your public key has been saved in/root/.ssh/id_rsa.pub.
The key fingerprint is:
79:97:67:36:e5:db:0d:4c:8e:20:63:a2:59:f6:bf:17root@VueOS
The key’s randomart image is:
+–[ RSA 2048]—-+
| |
| |
| + + . . .|
| = + + . * o |
| o S . + O .|
| o .E+ o+|
| . . .o|
| .. |
| .. |
+—————–+
#
自动生成完密钥后,把密钥拷贝到其它节点
Scp ssh key file too another node…
The authenticity of host ‘nodeb(192.168.2.158)’ can’t be established.
RSA key fingerprint isc6:2d:8e:e0:a1:e1:2e:c3:77:c7:1d:ef:92:7c:41:ba.
Are you sure you want to continueconnecting (yes/no)?
yes
Warning: Permanently added’nodeb,192.168.2.158′ (RSA) to the list of known hosts.
root@nodeb’s password:
#
输入远端节点密码
copy ssh file successful
Done
Warning: Permanently added’nodea,192.168.2.151′ (RSA) to the list of known hosts.
local nodea RsaKey remote nodea issuccessful
local nodea RsaKey remote nodeb issuccessful
known_hosts 100% 802 0.8KB/s 00:00
hosts 100% 84 0.1KB/s 00:00
[root@VueOS scripts]#
ssh nodeb
Last login: Fri Apr 4 15:34:06 2014 from 192.168.2.72
[root@VueOS ~]#
exit
logout
Connection to nodeb closed.
[root@VueOS scripts]#
ssh nodea
Last login: Fri Apr 4 11:55:58 2014 from hosta
[root@VueOS ~]#
exit
logout
Connection to nodea closed.
#
如上所示,互信自动配置成功。
脚本代码
[root@VueOS scripts]# cat ssh_trust.py
#!/usr/bin/python
import datetime
import os,sys,time
import commands
#这个函数是校验IP合法性的。
def check_ip(ipaddr):
import sys
addr=ipaddr.strip().split('.')
#print addr
if len(addr) != 4:
print "check ip address failed!"
sys.exit()
for i in range(4):
try:
addr[i]=int(addr[i])
except:
sys.exit()
if addr[i]<=255 and addr[i]>=0:
pass
else:
print "check ip address failed!"
sys.exit()
i+=1
else:
print "check ip address success!"
node_dict={}
host_all=[]
host_ip_all={}
#这个函数获取输入的节点信息,并校验输入的IP是否合法。
def get_nodes():
while True:
node=raw_input("""Input node's info. Usage: hosta/192.168.0.101. Press Enter is complete.
Please input Node info: """)
if len(node)==0:
return 2
node_result=node.strip().split('/')
host_ip_all[node_result[0]]=[node_result[1],'']
#print node_result
if len(node_result[0])==0:
print "Hostname is failed!"
sys.exit()
check_ip(node_result[1])
#node_dict[node_result[0]]=[node_result[1]]
host_all.append(node_result[0])
#print node_dict
local_ip_status,local_ip_result=commands.getstatusoutput("""ifconfig |grep 'inet addr'|awk -F '[: ]+' '{print $4}' """)
local_ip=local_ip_result.split('\n')
#print host_all
if len(host_all)==1:
if node_result[1] in local_ip:
pass
else:
print "The first IP must be native IP."
sys.exit()
#这个函数生成ssh密钥文件,简单的3条shell命令
def create_sshkey_file():
os.system("rm -rf ~/.ssh/")
os.system("/usr/bin/ssh-keygen -t rsa -f ~/.ssh/id_rsa -P '' ")
os.system("cp ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys")
#这个函数配置/etc/hosts文件
def add_etc_hosts():
for i in host_ip_all.keys():
#print host_ip_all.keys()
#判断/etc/hosts是否存在
if os.path.exists('/etc/hosts'):
pass
else:
os.system("touch /etc/hosts")
#删除掉原有主机名项,并添加新的对应关系
os.system("sed -i '/%s/d' /etc/hosts"%i)
#print i,host_ip_all[i][0]
os.system(''' echo '%s %s\r' >>/etc/hosts '''%(host_ip_all[i][0],i))
#with open('/etc/hosts','ab') as f :
# f.write('%s %s\r'%(host_ip_all[i][0],i))
#拷贝ssh密钥文件
def scp_sshkey():
#把/root/.ssh文件放在/tmp下,并开使其生效。
os.system("sed -i /tmp/d /etc/exports")
os.system("echo '/tmp *(rw)' >>/etc/exports")
os.system("exportfs -r")
os.system("cp -a /root/.ssh /tmp")
os.system("chmod 777 /tmp")
os.system("/etc/init.d/iptables stop")
os.system("chmod 777 /tmp/.ssh/id_rsa")
os.system("chmod 777 /tmp/.ssh")
print 'Scp ssh key file too another node...'
print host_all[1:]
localhost=host_all[0]
local_ip=host_ip_all[localhost][0]
#输入一次密码,登陆上去后执行了N条命令,挂载nfs,拷贝.ssh,修改权限,卸载等等。
for i in host_all[1:]:
os.system('''/usr/bin/ssh %s "/bin/umount -lf /mnt >/dev/null 2 &>1;/bin/mount %s:/tmp /mnt ;rm -rf /root/.ssh;mkdir /root/.ssh;sleep 3; /bin/cp -a /mnt/.ssh/* /root/.ssh/ ;echo 'copy ssh file successful';/bin/chmod 600 /root/.ssh/id_rsa;/bin/chmod 700 /root/.ssh;/bin/umount -lf /mnt "'''%(i,local_ip))
print "Done"
#测试ssh互信是否成功
def test_sshkey(host):
for host_n in host_all:
try:
#to gain public key
#使用StrictHostKeyChecking跳过公钥接收提示。并远程执行命令,连上了自然会输出成功信息。
os.system(''' ssh -o "StrictHostKeyChecking no" %s "echo -e local %s RsaKey remote %s is successful" '''%(host_n,host_all[0],host_n))
except:
print "\033[31mlocal %s RsaKey remote %s is fail.\033[0m"%(host_all[0],host_n)
else:
#全部测试完成后,把known_hosts文件拷贝到所有主机。一台服务器获取了所有公钥,那拷贝到远端自然是所有节点都有对方公钥了。
for host_m in host_all[1:]:
#copy ~/.ssh/known_hosts file to another host...
os.system("""/usr/bin/scp ~/.ssh/known_hosts %s:~/.ssh/known_hosts"""%host_m)
# copy hosts file to another host...
os.system("""/usr/bin/scp /etc/hosts %s:/etc/hosts """%host_m)
#函数执行部分
get_nodes()
a=raw_input("Are you sure you want to set ssh mutual trust? (yes/no) ").strip()
#提示一下,做不做互信要让用户选择。
if a=="yes":
create_sshkey_file()
add_etc_hosts()
scp_sshkey()
test_sshkey('192.168.2.73')
elif a=="no":
#输入no就代表互信已做好了。接下来执行别的代码。
pass
else:
print 'Byebye,Please input yes or no.'
sys.exit()