好久没更新了,今天决定不要懒。
今天分享一个最近用python写了一个应用部署工程,用来替代原来主要使用shell命令完成的操作。
开发的初衷是shell的脚本使用实在是不便,完成功能就已经很勉强(主要是不好调试,并且没有ide辅助),更遑论对各种异常情况的处理。
考虑到python在linux环境运行的便利性,于是考虑使用python完成部分操作,只在少量局部地区使用shell命令完成操作。在python中完成全部的操作以及对各操作步骤的完成情况进行实时检查,遇到异常时自动尝试恢复。
项目结构如图:

考虑到内容比较少,所以根路径仍然放置了一些内容。
主逻辑如下:
#!/usr/bin/python3
# coding:utf-8
'''
standard run command
python3 dynamicImport.py
--artifactId={artifactId}(required)
--isSpringAppFlag={true or false}(not required, if class not exist and not necessary)
--newFileFlag={true or false}(not required, give false if no file need to be operated)
--confirmVersion={current version}(not required, useless now)
--env={current environment}(not required, default is prod. selection include dev, test, vprod, prod)
spring jar app:
python3 dynamicImport.py --artifactId=abc-ddd --isSpringAppFlag=true --env=dev
'''
import argparse
import Constant
from MainFunction import get_obj, kill_process, application_startup, health_check, del_useless_file, sendEmail, \
file_handling, arg_handling
env = None
logger = Constant.logging.getLogger("dynamicImport")
try:
artifactId, confirmVersion, newFileFlag, isSpringAppFlag, env = arg_handling(argparse)
obj = get_obj(artifactId, isSpringAppFlag, env)
logger.info("obj start")
# print("ob start")
projectPath = Constant.startPath + "/" + artifactId.replace("_", "-")
if not newFileFlag:
kill_process(obj)
# 前台项目跳过kill过程
logger.info("kill pid finish")
# print("kill pid finish")
uploadFilePathForDeploy, oldFileBackupPath, deployFilePath = file_handling(obj, projectPath, newFileFlag)
# print("new file handle finish")
logger.info("new file handle finish")
currentPid = application_startup(obj, projectPath, deployFilePath, oldFileBackupPath)
# print("application start finish")
logger.info("application start finish")
health_check(obj, currentPid, deployFilePath, projectPath, oldFileBackupPath)
# print("check application finish")
logger.info("check application finish")
# TODO 前端工程的最终访问确认
'''
Frontend accessible check
'''
del_useless_file(obj, oldFileBackupPath, uploadFilePathForDeploy)
except Exception as e:
# send email
if env and str(env).__eq__("prod"):
sendEmail(artifactId, str(e))
raise e
最主要的核心在于对实现类的动态加载,搜索相关的介绍并不多,如果还有不知道的小伙伴,这里推荐一下这个类:
import Constant
def importAny(name):
try:
return __import__(name, fromlist=[''])
except:
try:
i = name.rfind('.')
mod = __import__(name[:i], fromlist=[''])
return getattr(mod, name[i + 1:])
except Exception as e:
logger = Constant.logging.getLogger("importAny")
logger.error("e: {}".format(e))
return None
def get_obj(artifactId, isSpringAppFlag, env):
cls = importAny('lib.' + artifactId + '.' + artifactId + '')
obj = None
if not cls:
if isSpringAppFlag:
cls = importAny(Constant.springClass)
obj = cls(Constant.startPath + artifactId.replace("_", "-"), artifactId, env)
else:
raise RuntimeError('handle class not found')
else:
logger.info("env {}".format(env))
# print("env {}".format(env))
obj = cls(Constant.startPath + artifactId.replace("_", "-"), None, env)
return obj
整体流程经过改造以后,整体的部署适应能力明显得到了加强。异常信息比较精准,且能够在一定情况下部署失败时能够自动恢复环境。
第一次写python的项目,并且用途比较古怪,还希望能有朋友指点一下问题,感谢。
网友评论