Title

使用python进行自动化备份和部署

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日志查看运行结果

posted @   Jackpot_ABC  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示