首页 > 编程语言 >使用python进行自动化备份和部署

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

时间:2024-02-21 11:00:05浏览次数:30  
标签:info logging python join 备份 jar 自动化 path os

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

相关文章

  • python更换国内镜像
    永久更改1.在python的命令提示符中运行以下语句,该条语句将pip的下载源永久更改为某个镜像站,这里以清华大学开源镜像站为例:pipconfigsetglobal.index-urlhttps://pypi.tuna.tsinghua.edu.cn/simple/2.windows环境下,在用户目录中创建一个文件夹,该文件夹的命名为pip;在该pip......
  • Python数据结构与算法04——栈与队列
    栈的实现:classStack(object):def__init__(self):self.__list=[]defpush(self,item):self.__list.append(item)defpop(self):returnself.__list.pop()defpeek(self):ifself.__list:returnself._......
  • Python数据结构与算法05——查找与排序
    冒泡排序:defbible_sort(aimlist):n=len(aimlist)j=len(aimlist)whilej>0:foriinrange(n-1):ifaimlist[i]>aimlist[i+1]:aimlist[i],aimlist[i+1]=aimlist[i+1],aimlist[i]n-=1j-=1r......
  • linux(Ubuntu)安装python2.7和pip2
    由于数据处理需要的软件有些老代码,需要安装python2,原服务器上已有python3,本想着使用源码包进行编译安装,奈何make时总是报如下错误,搞半天也没解决 或者  继续往下makeinstall后程序也无法正常执行,于是索性使用apt方式进行安装,过程如下:首先查看当前版本Ubuntu可支持的pyt......
  • python 爬虫模板
    前言在我们写爬虫的时候,一般想要的数据都在详情页里面,一般代码进入详情页参数,需要首页里面寻找,所以爬这样的网站,需要定义一个模板我的模板如下: importrandomimporttimeimportrequestsfromauctionimportlogtoolfromauction.BaseCrawlerimportBaseCrawlercla......
  • python实战:使用json序列化
    一,官方文档:https://docs.python.org/zh-cn/3/library/json.html二,json与字典的相互转化1,字典转json字符串1234567importjson #字典转jsond=dict(name='Tom',age=2,score=88)json_d=json.dumps(d)print(type(json_d))print(json_d)......
  • python中的内置函数zip函数
    关于zip()函数,有几点要讲的。首先,官方文档中,它是这样描述的:Makeaniteratorthataggregateselementsfromeachoftheiterables.Returnsaniteratoroftuples,wherethei-thtuplecontainsthei-thelementfromeachoftheargumentsequencesoriterables.The......
  • python实战:用requests+做爬虫
    一,安装requests1,用pip安装(venv)liuhongdi@192news%pip3installrequests2,查看所安装库的版本:(venv)liuhongdi@192news%pip3showrequestsName:requestsVersion:2.31.0Summary:PythonHTTPforHumans.Home-page:https://requests.readthedocs.ioAu......
  • Python 实现Excel和CSV格式之间的互转
    通过使用Python编程语言,编写脚本来自动化Excel和CSV之间的转换过程,可以批量处理大量文件,定期更新数据,并集成转换过程到自动化工作流程中。本文将介绍如何使用第三方库Spire.XLSforPython实现:使用Python将Excel转为CSV使用Python将CSV转为Excel安装PythonExcel类库:pip......
  • python文件获取并读取固定长度数据实例解析
    一概念1file操作:文件操作一般有open,write,read,close几种,这里重点是read固定长度数据。read() 用于从文件读取指定的字节数,如果未给定或为负则读取所有。本文中心不在概念,直接上源码。二源码解析importsysfromPyQt5importQtWidgetsfromPyQt5.QtWidgetsimportQF......