之前编写了用python ,paramiko包实现linux互信,但是在大规模上有点问题,且速度不是很快,所以这次重新编写了下,流程一样,采用了协程配合多线程实现,下面是代码,可能有些地方写的不是很优美,这次的改进主要是加快校验,互信速度
#!/usr/bin/python3
# _*_coding:utf-8 _*_
# @Time :2020/6/24 11:46
# @Author : liwentong
#@ File :main.py
import os
import sys
import threading
from gevent import monkey
monkey.patch_all()
import gevent
from myautossh import *
from config import *
Allresult={}
def read_macinfo(filepath):
infoList=[]
with open(filepath,'r') as f:
for line in f.readlines():
#一个空格切分数据
lines=line.strip().split(' ')
if len(lines)==4:
infoList.append(lines)
return infoList
#校验服务器情况
def conn_ssh(line):
global Allresult
aush = Myautossh(line[0], line[1], line[2], line[3])
rec = aush.testPub()
if len(rec)==0:
if "no" not in Allresult.keys():
Allresult["no"]=[]
Allresult["no"].append(line[0])
else:
Allresult["no"].append(line[0])
else:
if "yes" not in Allresult.keys():
Allresult["yes"] = {}
Allresult["yes"][line[0]]=rec
else:
Allresult["yes"][line[0]]=rec
#携程配合多线程校验
def gevent_run(infoList):
task_list=[]
for line in infoList:
task=gevent.spawn(conn_ssh,line)
task_list.append(task)
gevent.joinall(task_list)
#做互信
def addPublic(tcc):
global Allresult
ip=tcc[0]
ic=tcc[1]
try:
myautossh=Myautossh(ip, ic[ip][0], ic[ip][1], ic[ip][2], Allresult["yes"])
myautossh.addPub()
except Exception as f:
print(f)
#协程搭配多线程做户型
def gvent_run_add(ipList,ic):
task_list=[]
for line in ipList:
task=gevent.spawn(addPublic,[line,ic])
task_list.append(task)
gevent.joinall(task_list)
def main():
filepath='./1.txt'
infoList=read_macinfo(filepath)
#默认线程数为核心数
step=int(len(infoList)/Pnum)
if step==0:
t=threading.Thread(target=gevent_run,args=(infoList,))
t.start()
t.join()
else:
tp=[]
alist=[infoList[i:i+step] for i in range(0,len(infoList),step)]
#print(alist)
for linec in alist:
t=threading.Thread(target=gevent_run,args=(linec,))
t.start()
tp.append(t)
for i in tp:
i.join()
print("功能选项:1,1对N互信 2,N对N互信")
#选出存活的已经获得公匙的服务器
isActive=[i for i,value in Allresult["yes"].items()]
isActiveInfo={}
for i in infoList:
if i[0] in isActive:
isActiveInfo["%s"%i[0]]=i[1:]
choice=input("输入你要做的功能选项:")
if choice=='1':
print("存活服务器列表:%s"%isActive)
ipc=''
while ipc!="break":
ipc = input("输入你要做1对N互信的服务器ip(输入break退出):")
if ipc in isActive:
Myautossh(ipc,isActiveInfo[ipc][0],isActiveInfo[ipc][1],isActiveInfo[ipc][2],Allresult["yes"]).addPub()
else:
print("没有这个服务器" if ipc!='break' else '')
elif choice=='2':
#分任务
step = int(len(isActive) / Pnum)
print(step)
if step == 0:
t=threading.Thread(target=gvent_run_add, args=(isActive,isActiveInfo))
t.start()
else:
tp=[]
alist=[isActive[i:i+step] for i in range(0,len(isActive),step)]
for line in alist:
t=threading.Thread(target=gvent_run_add,args=(line,isActiveInfo))
t.start()
tp.append(t)
for t in tp:
t.join()
if __name__=='__main__':
main()
#!/usr/bin/python3
# _*_coding:utf-8 _*_
# @Time :2020/6/24 14:17
# @Author : liwentong
#@ File :myautossh.py
import paramiko
import sys
import os
import socket
from config import *
class Myautossh(object):
def __init__(self,ip,username,password,port,*args):
self.ip=ip
self.username=username
self.password=password
self.port=port
self.result=''
self.success=False
self.server=paramiko.SSHClient()
self.macInfoList='' if len(args)==0 else args[0]
def checkHostExist(self):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((self.ip, int(self.port)))
s.settimeout(2)
self.success=True
except Exception as f:
self.success=False
def check_pub(self):
self.server.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.server.connect(self.ip,int(self.port),self.username,self.password)
stdin, stdout, stderr = self.server.exec_command(readPubCmd)
pubresult=stdout.read().decode('utf-8').replace('\n','')
if len(pubresult)>0:
self.result=pubresult
else:
retry=0
#尝试执行三次
while retry<3:
stdin,stdout,stderr=self.server.exec_command(keygenCmd)
rec=stdout.read().decode('utf-8')
if rec=="yes":
break
retry+=1
stdin,stdout,stderr=self.server.exec_command(readPubcmd)
rec=stdout.read().decode('utf-8').replace('\n','')
if len(rec)>0:
self.result=rec
#单增加公匙到
def addPub(self):
self.server.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.server.connect(self.ip, int(self.port), self.username, self.password)
for uip,pub in self.macInfoList.items():
addcmd = addKeyCmd % (pub)
stdin, stdout, stderr = self.server.exec_command(addcmd)
if stdout.read().decode("utf-8").strip()=="yes":
print("%s 对 %s 互信成功"%(uip,self.ip))
else:
print("%s 对 %s 互信失败"%(uip,self.ip))
#测试公匙是否存在,不存在创建
def testPub(self):
self.checkHostExist()
if self.success:
self.check_pub()
if len(self.result)!=0:
return self.result
else:
return ''
#!/usr/bin/python3
# _*_coding:utf-8 _*_
# @Time :2020/6/24 14:19
# @Author : liwentong
#@ File :config.py
import multiprocessing
import encodings.idna
PingHost=""
''' ssh-keygen 命令 '''
keygenCmd="ssh-keygen -q -t rsa -P '' -f ~/.ssh/id_rsa && echo yes || echo no"
''' 读取pub文件 '''
readPubCmd="test -f ~/.ssh/id_rsa.pub && cat ~/.ssh/id_rsa.pub || echo"
''' 查看pub文件是否存在 '''
testExistsCmd="test -f ~/.ssh/id_rsa.pub && echo yes || echo no"
''' 追加公钥至authorized_keys中'''
addKeyCmd="echo %s >> ~/.ssh/authorized_keys && chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys && echo yes || echo no"
'''进程数'''
Pnum=3
下面是输入文件,主要记录ip,username,password,port 中间以一个空格隔开
192.168.1.1 test test 22
程序我已经在小规模集群测试过,;测试可能不到位,可能有些地方有bug,有问题可以私信大家一起解决。