#-*- coding:utf-8 -*-
'''
python一键启动服务器--所有部署的项目
'''
import paramiko
import configparser
import time
import ast
import threadpool
##设置日志打印级别
#logging.basicConfig(format='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s',level=logging.DEBUG)
#配置文件读取
cf = configparser.ConfigParser()
cf.read(".\config.ini") # 读取配置文件,如果写文件的绝对路径,就可以不用os模块
missHosts=["data4","name2","name4"]#todo 排除host
pool = threadpool.ThreadPool(4)
'''
执行操作
'''
def operation():
secs = cf.sections() # 获取文件中所有的section(一个配置文件中可以有多个配置,如数据库相关的配置,邮箱相关的配置,每个section由[]包裹,即[section]),并以列表的形式返回
secs=[sec for sec in secs if sec not in missHosts]
print("{}==>开始初始化所有数据库服务。。。。。。。。".format(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())))
db_success = {}
#先初始化数据库操作
for sec in secs:
host = cf.get(sec, "host")
port = cf.get(sec, "port")
user = cf.get(sec, "user")
pwd = cf.get(sec, "pwd")
ssh = getConnection(host,port,user,pwd)
if ssh:
db_status = initDatabse(sec,ssh)
db_success.setdefault(sec,db_status)
else:
print("【error】{}主机连接失败!".format(sec))
closeConnection(ssh)
#如果数据库都初始化成功,则开始执行启动指令
if False not in db_success.values():
print("{}==>所有数据库服务初始化完成!!!".format(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
for sec in secs:
host = cf.get(sec, "host")
port = cf.get(sec, "port")
user = cf.get(sec, "user")
pwd = cf.get(sec, "pwd")
ssh = getConnection(host, port, user, pwd)
if ssh:
startProject(sec,ssh)
else:
print("【error】{}主机连接失败!".format(sec))
closeConnection(ssh)
else:
print("{}==>数据库没有初始化成功,请检查后在尝试!",format("|".join([k for k,v in db_success.items() if v==False])))
#启动项目
def startProject(secname,ssh):
flag = {}
if assertKey(secname,"command"):
print("启动项目操作:【{}】".format(secname))
dbs = ast.literal_eval(cf.get(secname,"command"))
for k,v in dbs.items():
success = assertServiceStatus(ssh,k)
if success:
print("=====[{}]项目服务已经启动,指令=[{}]".format(secname,k))
flag.setdefault(k,True)
else:
print("=====[{}]项目服务正在启动,指令=[{}]".format(secname, v))
executeService(ssh,v)
#再次验证是否都已启动
time.sleep(1)
for k,v in dbs.items():
success = assertServiceStatus(ssh,k)
if success:
flag.setdefault(k,True)
else:
print("=====[{}]主机中[{}]启动失败!".format(secname, v))
#尝试重启一次,返回True 或False ,并会打印执行信息
flag.setdefault(k,restartProject(ssh,k,v))
if False not in flag.values():
print("=====[{}]所有项目完成!".format(secname))
return True
else:
print("【error】=====[{}]项目启动失败!".format(secname))
return False
#初始化所有数据库
def initDatabse(secname,ssh):
flag = {}
if assertKey(secname,"database"):
print("数据库操作:【{}】:".format(secname))
dbs = ast.literal_eval(cf.get(secname,"database"))
for k,v in dbs.items():
success = assertServiceStatus(ssh,k)
if success:
print("=====[{}]数据库服务已经启动,指令=[{}]".format(secname,k))
flag.setdefault(k,True)
else:
print("=====[{}]数据库服务正在启动,指令=[{}]".format(secname, v))
executeService(ssh,v)
#再次验证程序是否都已启动
time.sleep(2)
for k,v in dbs.items():
success = assertServiceStatus(ssh,k)
if success:
flag.setdefault(k,True)
else:
print("=====[{}]主机中[{}]数据库服务初始化失败!".format(secname, v))
flag.setdefault(k,False)
if False not in flag.values():
print("=====[{}]初始化数据库完成!".format(secname))
return True
else:
print("【error】=====[{}]初始化数据库失败!".format(secname))
return False
#针对启动失败的程序,tomcat启动失败,但是ps查询还是会有进程
def restartProject(ssh,k,v):
pids=[]
stdin, stdout, stderr = ssh.exec_command(k,get_pty=True)#查询进程
lines = stdout.readlines()
for line in lines:
pid = line[9:14]
pids.append(pid)
print("进程=[{}],info=【{}】".format(pid,line))
if pids:
ssh.exec_command("kill -9 {}".format(" ".join(pids)))
#杀完进程后尝试重新启动
stdin, stdout, stderr = ssh.exec_command(v,get_pty=True)
for out in stdout:
print("执行返回信息:【{}】".format(out))
for err in stderr:
print("执行错误信息:【{}】".format(err))
time.sleep(3)
success = assertServiceStatus(ssh,k)
return success
#判断服务是否启动
def assertServiceStatus(ssh,command):
stdin, stdout, stderr = ssh.exec_command(command,get_pty=True)
res = [line for line in stdout]
if len(res) > 0:
return True
else:
return False
#判断服务是否启动
def executeService(ssh,command):
try:
ssh.exec_command("{}".format(command),timeout=2)#不等待执行结果
except:
print("{}==>执行完毕!")
def assertKey(secname,key):
has =cf.has_option(secname,key)
return has
def getConnection(host,port,user,pwd):
'''
重新获取链接
:param host:
:param port:
:param user:
:param pwd:
:return:
'''
ssh = paramiko.SSHClient() # 创建SSH对象
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 允许连接不在know_hosts文件中的主机
try:
ssh.connect(hostname=host, port=port, username=user, password=pwd,timeout=5) # 连接服务器
return ssh
except:
print("【error】{}连接失败".format(host))
return None
def closeConnection(ssh):
'''
关闭链接
:param ssh:
:return:
'''
try:
ssh.close()
except:
print("【error】{}:链接关闭异常".format(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
if __name__ == '__main__':
start = time.time()
operation()
end = time.time()
print("所有项目启动完成,共耗时{}秒".format((end-start)))
# sec="data2"
# host = cf.get(sec, "host")
# port = cf.get(sec, "port")
# user = cf.get(sec, "user")
# pwd = cf.get(sec, "pwd")
# ssh = getConnection(host, port, user, pwd)
# k = "service mysqld status"
# v = "cd /var/neo4j-community-3.5.1/bin;./neo4j start"
# #restartProject(ssh,k,v)
# stdin, stdout, stderr = ssh.exec_command(k, get_pty=True) # 查询进程
#
# if str(stdout.readlines()[-1]).__contains__("Started MySQL Server."):
# print("服务已经启动!")