1、代码文件 deploy.py
import os
from datetime import datetime
import shutil
import sys
import win32serviceutil
import win32service
import time
import tkinter as tk
# from tkinter import filedialog
import configparser
import logging
import ctypes
# 创建备份文件夹并备份前端或后端
def createBackupFolderAndBackup(isFront,isBack):
# 获取当前日期
now = datetime.now()
# 获取当前时间的年月日/时分秒
folderNameOfYmd = now.strftime("%Y%m%d")
folderNameOfHms = now.strftime("%H%M%S")
# 要新建的备份文件夹的完整路径
folderPathOfBackupNew = dirOfBackup + "\\" + folderNameOfYmd + "\\" + folderNameOfHms
# 创建备份文件夹
os.makedirs(folderPathOfBackupNew, exist_ok=True)
logging.info("创建备份文件夹成功:"+ folderPathOfBackupNew)
if(isFront):
# 旧apk包路径
apkPathOfOld = os.path.join(deployDirOfApk , deployNameOfApk)
# 备份apk文件
shutil.copy2(apkPathOfOld, folderPathOfBackupNew)
if not os.path.exists(os.path.join(folderPathOfBackupNew,deployNameOfApk)):
logging.error("apk备份失败")
sys.exit(1)
else:
logging.info("apk已完成备份")
if (isBack):
# 旧jar包路径
jarPathOfOld = os.path.join(deployDirOfJar , deployNameOfJar)
# 备份jar文件
shutil.copy2(jarPathOfOld, folderPathOfBackupNew)
if not os.path.exists(os.path.join(folderPathOfBackupNew,deployNameOfJar)):
logging.error("jar备份失败")
sys.exit(1)
else:
logging.info("jar已完成备份")
# 停止服务部署后端
def stopServiceAndDeployJar(service_name):
# 1、停止服务
try:
win32serviceutil.StopService(service_name)
logging.info("停止服务")
except win32service.error as e:
if e.winerror == 1062: # 1062表示服务已经停止
pass
else:
raise
# 2. 等待服务完全停止
logging.info("等待服务完全停止")
while True:
try:
status = win32serviceutil.QueryServiceStatus(service_name)
if status[1] == win32service.SERVICE_STOPPED:
break
except win32service.error as e:
if e.winerror == 1060: # 1060表示服务不存在
break
else:
raise
time.sleep(1)
logging.info("服务已完全停止")
# 3.替换jar包
# 删除旧的jar包
pathOfJarOld = os.path.join(deployDirOfJar, deployNameOfJar)
try:
os.remove(pathOfJarOld)
logging.info(f"成功删除jar包:{pathOfJarOld}")
except OSError as e:
logging.error(f"删除jar包失败:{pathOfJarOld}")
raise
# 拷贝新的jar包到要部署的文件夹
myPathOfJar = os.path.join(myDirOfJar, myNameOfJar)
shutil.copy2(myPathOfJar, deployDirOfJar)
if(not os.path.exists(os.path.join(deployDirOfJar, myNameOfJar))):
logging.error("拷贝新jar包失败")
sys.exit(1)
else:
# 重命名
os.rename(os.path.join(deployDirOfJar, myNameOfJar),os.path.join(deployDirOfJar, deployNameOfJar) )
logging.info("jar包替换成功")
# 4.启动服务
try:
win32serviceutil.StartService(service_name)
logging.info("启动服务")
except win32service.error as e:
if e.winerror == 1056: # 1056表示服务已经在运行
pass
else:
raise
# 前端部署
def replaceApk():
pathOfApkOld = os.path.join(deployDirOfApk, deployNameOfApk)
try:
os.remove(pathOfApkOld)
logging.info(f"成功删除apk包:{pathOfApkOld}")
except OSError as e:
logging.error(f"删除apk包失败:{pathOfApkOld}")
raise
# 拷贝新的jar包到要部署的文件夹
myPathOfApk = os.path.join(myDirOfApk, myNameOfApk)
shutil.copy2(myPathOfApk, deployDirOfApk)
if(not os.path.exists(os.path.join(deployDirOfApk, myNameOfApk))):
logging.error("拷贝新apk包失败")
sys.exit(1)
else:
# 重命名
os.rename(os.path.join(deployDirOfApk, myNameOfApk),os.path.join(deployDirOfApk, deployNameOfApk) )
logging.info("apk替换成功")
# 部署
def deploy(isFront, isBack):
if(isFront and isBack):
logging.info("部署:前端+后端")
elif isFront:
logging.info("部署:前端")
elif isBack:
logging.info("部署:后端")
createBackupFolderAndBackup(isFront,isBack)
if(isBack):
stopServiceAndDeployJar(serviceName)
if(isFront):
replaceApk()
logging.info("done")
# 读取配置
def configuration():
if not os.path.exists(configFilePath):
logging.error(f"配置文件{configFilePath}不存在")
sys.exit(1)
# 开始解析配置文件
logging.info(f"开始解析配置文件{configFilePath}...")
# 声明全局变量
global dirOfBackup,isFront,isBack
global deployDirOfJar,deployDirOfApk,deployNameOfJar,deployNameOfApk
global myDirOfJar,myDirOfApk,myNameOfJar,myNameOfApk
global serviceName,logFilePath
# 修改全局变量
try:
config = configparser.ConfigParser()
config.read(configFilePath)
dirOfBackup = config.get("backup","dirOfBackup")
isFront = config.getboolean("deploy","isFront")
isBack = config.getboolean("deploy","isBack")
deployDirOfJar = config.get("deploy","deployDirOfJar")
deployDirOfApk = config.get("deploy","deployDirOfApk")
deployNameOfJar = config.get("deploy","deployNameOfJar")
deployNameOfApk = config.get("deploy","deployNameOfApk")
myDirOfJar = config.get("my","myDirOfJar")
myDirOfApk = config.get("my","myDirOfApk")
myNameOfJar = config.get("my","myNameOfJar")
myNameOfApk = config.get("my","myNameOfApk")
serviceName = config.get("service","serviceName")
logFilePath = config.get("log","logFilePath")
logging.info("配置文件解析成功")
except:
logging.error("配置文件解析失败")
sys.exit(1)
# 检测文件是否齐全
def initCheck():
logging.info("检查文件是否准备齐全")
if(isBack):
logging.info("检查后端文件和服务是否存在")
myJarPath = os.path.join(myDirOfJar,myNameOfJar)
if not os.path.exists(myJarPath):
logging.error(f"文件{myJarPath}不存在")
sys.exit(1)
oldJarPath = os.path.join(deployDirOfJar,deployNameOfJar)
if not os.path.exists(oldJarPath):
logging.error(f"文件{oldJarPath}不存在")
sys.exit(1)
try:
status = win32serviceutil.QueryServiceStatus(serviceName)
except win32service.error as e:
if e.winerror == 1060: # 1060表示服务不存在
logging.error(f"服务{serviceName}不存在")
sys.exit(1)
if(isFront):
logging.info("检查前端文件是否存在")
myApkPath = os.path.join(myDirOfApk,myNameOfApk)
if not os.path.exists(myApkPath):
logging.error(f"文件{myApkPath}不存在")
sys.exit(1)
oldApkPath = os.path.join(deployDirOfApk,deployNameOfApk)
if not os.path.exists(oldApkPath):
logging.error(f"文件{oldApkPath}不存在")
sys.exit(1)
# 判断是否以管理员身份运行
def isAdmin():
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False
# 配置文件路径
configFilePath = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(sys.executable))),"config.ini")
# 变量设置默认值
# 备份文件夹所在路径
dirOfBackup = "E:\\test\\backup"
# 后端部署文件夹路径
deployDirOfJar = "E:\\apiTest"
# 前端部署文件夹路径
deployDirOfApk = "E:\\test\\targetApp"
# 我要更新的jar包所在的文件夹
myDirOfJar = "E:\\test\\deployed"
# 我要更新的apk包所在的文件夹
myDirOfApk = "E:\\test\\deployed"
# 后端部署文件名
deployNameOfJar = "testapp.jar"
# 前端部署文件名
deployNameOfApk = "zfapp.apk"
# 我的jar包文件名
myNameOfJar = "zbj-fwapp-api-dev.jar"
# 我的apk文件名
myNameOfApk = "zfapp.apk"
# 服务名称
serviceName = "testapp"
# 日志文件路径
logFilePath = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(sys.executable))),"logs\\log.txt")
# 是否部署前端
isFront = False
isBack = False
# 日志文件配置
logging.basicConfig(filename=logFilePath,
format='%(asctime)s %(levelname)s : %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
filemode='a',
level=logging.INFO
)
# 判断是否以管理员身份运行
if isAdmin():
logging.info("当前程序以管理员身份运行,继续")
# 配置文件设置变量
configuration()
if(isFront or isBack):
# 检查文件
initCheck()
# 部署
deploy(isFront,isBack)
else:
logging.info("不进行部署,结束")
else:
logging.error("当前程序不是以管理员身份运行,结束")
2、配置文件 config.ini
[backup]
dirOfBackup = E:\\test\\backup
[deploy]
isFront = False
isBack = False
deployDirOfJar = E:\\apiTest
deployDirOfApk = E:\\test\\targetApp
deployNameOfJar = testapp.jar
deployNameOfApk = zfapp.apk
[my]
myDirOfJar = E:\\test\\deployed
myDirOfApk = E:\\test\\deployed
myNameOfJar = zbj-fwapp-api-dev.jar
myNameOfApk = zfapp.apk
[service]
serviceName = testapp
[log]
logFilePath = E:\\test\\deployed\\logs\\log.txt
3、使用pyinstaller打包成exe
4、readme.txt
1、使用配置文件config.ini进行配置:
dirOfBackup ——备份文件夹路径
isFront/isBack ——设置为True/False来控制部署前端还是后端
deployDirOfJar ——后端部署的文件夹路径
deployDirOfApk ——前端部署的文件夹路径
deployNameOfJar ——后端部署的Jar包名称
deployNameOfApk ——前端部署的apk名称
myDirOfJar —— 我的Jar包存放文件夹路径
myDirOfApk ——我的Apk包存放文件夹路径
myNameOfJar ——我的Jar包名称
myNameOfApk ——我的Apk包名称
serviceName ——服务的名称
logFilePath ——日志文件存放的路径
2、使用管理员身份运行dist/deploy.exe(或通过windows计划任务定时运行)
3、查看log日志查看运行结果
标签:info,logging,python,join,备份,jar,自动化,path,os
From: https://www.cnblogs.com/congshaoblog/p/18024671