用python写一个自动化部署工具

效果

1688121596787.png

起因

现在springboot项目的自动化部署已经非常普遍,有用Jenkins的,有用git钩子函数的,有用docker的…等等。这段时间在玩python,想着用python实现自动化部署,即能锻炼下编码能力,又方便运维。于是开始着手写了一个exe程序,可直接在任何windows电脑上运行(不具备python环境的windows电脑也可以运行)。有兴趣的小伙伴可以跟着代码一起练一练噢,写的详细一点,对python新手也很友好。

实现步骤

开发准备

  1. 具有python基本环境和ide的windows或macOS电脑一台
  2. 安装打包工具pip install pyinstaller
  3. 一点小小的python基础

步骤

1. 导入依赖

image.png 新建一个py文件,可以把它命名为 deployment.py(名字随意哈,什么名儿都可以),然后把下面的库导入语句copy到此py文件中

import os #用于-提取文件名  
import re #用于-正则表达式  
import time #用于-线程休眠  
import paramiko #用于-远程执行linux命令  
from alive_progress import alive_bar #用于-进度条工具类  
from cryptography.fernet import Fernet #用于-加解密代码  
import base64 #用于-加解密代码  
import hashlib #用于-加解密代码

在导入依赖的时候,可能有些依赖咱们的电脑上之前没下载过,不要紧,只需要在pycharm中按 alt+enter就可以自动导入了,PyCharm跟Idea的快捷键一模一样,可以按Idea的习惯使用。而且在python中还不用配置maven或pom文件,非常方便。

2. 输入校验

部署毕竟是件严谨的事情,我们增加个部署密钥校验,我的这个部署密钥承担了以下的功能

  1. 确保部署的安全性,不是谁拿到这个exe程序都能运行的(哼~傲娇)
  2. 密钥字符串用-分割开,前面的区分环境,后面的区分项目或模块。
  3. 如果同学们不需要区分项目子模块,就不需要搞这么复杂,随便定义一个密钥就好了
import os #用于-提取文件名  
import re #用于-正则表达式  
import time #用于-线程休眠  
import paramiko #用于-远程执行linux命令  
from alive_progress import alive_bar #用于-进度条工具类  
from cryptography.fernet import Fernet #用于-加解密代码  
import base64 #用于-加解密代码  
import hashlib #用于-加解密代码  #检查密钥格式
def check_deploy_sign(deploy_site):  #确保密钥只能是以下4个之一才能继续往下操作,否则无限循环输入 或 退出程序if deploy_site != 'pro-main' and deploy_site != 'pro-manage' and deploy_site != 'test-main' and deploy_site != 'test-manage': #校验失败,一直校验new_deploy_site = input("错误:请填写部署密钥:")  check_deploy_sign(new_deploy_site)  #校验成功,退出return deploy_site  try:  deploy_sign = input("提示:请填写部署密钥:")  deploy_sign = check_deploy_sign(deploy_sign)  # 部署环境  pro代表生成环境,test代表测试环境deploy_server = deploy_sign.split('-')[0]  # 部署模块或项目 manage代表manage模块,main代表main模块, deploy_site = deploy_sign.split('-')[1]  # 打包时的包名,三目运算符package_name = 'production' if deploy_server == 'pro' else 'staging'  except Exception as e:  print(f"异常: {str(e)}")  

上面的代码中 增加了全局的异常处理,类似Java的try catch,也定义了一些基本的变量。密钥是一串由短线连接的字符串,短线前的代码用以区分环境,短线后的代码用以区分模块或项目。另外上面代码中的package_name是打包时的包名(即profiles.profile.id),一般配置在springboot项目pom文件中的编辑模块,类似下面这样:

image.png

3. 连接linux服务器
import os #用于-提取文件名  
import re #用于-正则表达式  
import time #用于-线程休眠  
import paramiko #用于-远程执行linux命令  
from alive_progress import alive_bar #用于-进度条工具类  
from cryptography.fernet import Fernet #用于-加解密代码  
import base64 #用于-加解密代码  
import hashlib #用于-加解密代码  #检查密钥格式
def check_deploy_sign(deploy_site):  #确保密钥只能是以下4个之一才能继续往下操作,否则无限循环输入 或 退出程序if deploy_site != 'pro-main' and deploy_site != 'pro-manage' and deploy_site != 'test-main' and deploy_site != 'test-manage': #校验失败,一直校验new_deploy_site = input("错误:请填写部署密钥:")  check_deploy_sign(new_deploy_site)  #校验成功,退出return deploy_site  # 连接服务器  
def connect_service(deploy_server):server_password = ''  server_host = ''  sign = hashlib.sha256(deploy_server.encode()).digest()  sign = base64.urlsafe_b64encode(sign)  if deploy_server == 'pro':  server_password = decrypt_str(sign, service_password_pro)  server_host = decrypt_str(sign, service_host_pro)  elif deploy_server == 'test':  server_password = decrypt_str(sign, service_password_test)  server_host = decrypt_str(sign, service_host_test)  else:  raise Exception('失败:部署服务器标识有误')  # 连接远程服务器  ssh = paramiko.SSHClient()  ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())  ssh.connect(server_host, username='root', password=server_password)  return ssh  # 解密密码  
def decrypt_str(key, encrypted_password):  f = Fernet(key)  decrypted_password = f.decrypt(encrypted_password).decode()  return decrypted_passwordtry:  # 服务器环境信息的加密字符串,包含各服务器的 ip和密码  service_password_pro = 'asdatrgsd=='  service_password_test = 'sgherfhdf=='  service_host_pro = 'jfhgfvdcfdtr=='  service_host_test = 'jutyrbfvret=='deploy_sign = input("提示:请填写部署密钥:")  deploy_sign = check_deploy_sign(deploy_sign)  # 部署环境  pro代表生成环境,test代表测试环境deploy_server = deploy_sign.split('-')[0]  # 部署模块或项目 manage代表manage模块,main代表main模块, deploy_site = deploy_sign.split('-')[1]  # 打包时的包名,三目运算符package_name = 'production' if deploy_server == 'pro' else 'staging'  #进度条with alive_bar(7, force_tty=True, title="进度") as bar:  # 连接服务器  ssh = connect_service(deploy_server)  bar(0.1)  print("完成-服务器连接成功")  time.sleep(0.5)
except Exception as e:  print(f"异常: {str(e)}")  

在连接服务器之前,我们加个进度条显示,方便查看部署到哪一步了,要点讲解:

  1. with alive_bar 中放的事需要进度条显示的步骤,connect_service是连接服务器的方法
  2. 主机的ip和密码我们用加密的密文显示,解密的密钥就是 手动输入的部署密钥
  3. 当一段逻辑执行完成后,通过bar(0.1)来显示进度条进度,alive_bar的第一个参数就是步骤总数
4. 部署工具主逻辑

代码要点讲解: 下面的代码是工程的全部代码,主要包含了以下逻辑

  1. 连接服务器
  2. 进入到项目工程目录,拉取git代码
  3. 编译公共依赖的代码(有的项目不一定有公共模块,可酌情删减)
  4. 编译打包程序代码
  5. 杀死旧进程
  6. 寻找编译好的程序jar包并启动
  7. 检测启动结果
import os #用于-提取文件名
import re #用于-正则表达式
import time #用于-线程休眠
import paramiko #用于-远程执行linux命令
from alive_progress import alive_bar #用于-进度条工具类
from cryptography.fernet import Fernet #用于-加解密代码
import base64 #用于-加解密代码
import hashlib #用于-加解密代码def check_deploy_sign(deploy_site):if deploy_site != 'pro-main' and deploy_site != 'pro-manage' and deploy_site != 'test-main' and deploy_site != 'test-manage':new_deploy_site = input("错误:请填写部署密钥:")check_deploy_sign(new_deploy_site)return deploy_site# 解密密码
def decrypt_str(key, encrypted_password):f = Fernet(key)decrypted_password = f.decrypt(encrypted_password).decode()return decrypted_password# 执行远程命令
def execute_command(ssh, command):stdin, stdout, stderr = ssh.exec_command(command)stdout.channel.recv_exit_status()  # 等待命令执行完毕output = stdout.read().decode('utf-8')time.sleep(0.5)return output# 执行远程命令
def execute_command_shell(shell, command, endword):shell.send(command + '\n')output = ''while True:while shell.recv_ready():recv = shell.recv(1024).decode('utf-8', errors='ignore')output += recvif endword == '# ':if output.endswith('$ ') or output.endswith('# '):breakelif endword in output:breaktime.sleep(0.5)return output# 连接服务器
def connect_service(deploy_server):  server_password = ''server_host = ''sign = hashlib.sha256(deploy_server.encode()).digest()sign = base64.urlsafe_b64encode(sign)if deploy_server == 'pro':server_password = decrypt_str(sign, service_password_pro)server_host = decrypt_str(sign, service_host_pro)elif deploy_server == 'test':server_password = decrypt_str(sign, service_password_test)server_host = decrypt_str(sign, service_host_test)else:raise Exception('失败:部署服务器标识有误')# 连接远程服务器ssh = paramiko.SSHClient()ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())ssh.connect(server_host, username='root', password=server_password)return ssh# 查询进程
def query_process(ssh, process_name):  process_id = ''command = f"ps -ef | grep {process_name}-system-master. | grep -v grep"process_output = execute_command(ssh, command)if process_output:# 提取进程ID并杀死进程process_id = process_output.split("    ")[1]return process_id# 杀掉进程
def kill_process(ssh, process_id):  command = f"kill -9 {process_id}"output = execute_command(ssh, command)return output# 寻找编译好的jar包
def find_jarname(output):match = re.search(r"Building jar: .+?\/(.+?\.jar)", output)if match:jar_filepath = match.group(1)jar_filename = os.path.basename(jar_filepath)return jar_filenameelse:raise Exception('失败:jar未找到')try:service_password_pro = 'asdatrgsd=='service_password_test = 'sgherfhdf=='service_host_pro = 'jfhgfvdcfdtr=='service_host_test = 'jutyrbfvret=='deploy_sign = input("提示:请填写部署密钥:")deploy_sign = check_deploy_sign(deploy_sign)# 部署环境deploy_server = deploy_sign.split('-')[0]# 部署模块deploy_site = deploy_sign.split('-')[1]# 部署环境对应服务正式的名字package_name = 'production' if deploy_server == 'pro' else 'staging'with alive_bar(7, force_tty=True, title="进度") as bar:# 连接服务器ssh = connect_service(deploy_server)bar(0.1)print("完成-服务器连接成功")time.sleep(0.5)# 拉取代码shell = ssh.invoke_shell()execute_command_shell(shell, 'cd /root/build/x-system','#')execute_command_shell(shell, 'git pull','#')bar(0.2)print("完成-git代码拉取成功")# 编译代码execute_command_shell(shell, 'cd /root/build/x-system/modules', '#')execute_command_shell(shell, 'mvn clean install', 'BUILD SUCCESS')bar(0.4)print("完成-公共模块编译成功")# 打包代码execute_command_shell(shell, 'cd /root/build/x-system/webapps/' + deploy_site + '-system ', '#')output=execute_command_shell(shell, 'mvn clean package -P ' + package_name, 'BUILD SUCCESS')bar(0.6)print("完成-" + deploy_site + "模块打包成功")# 查询进程,如果查不到 就不执行kill命令pid = query_process(ssh, deploy_site)if pid != '':kill_process(ssh, pid)print("完成-旧程序进程已被杀掉,等待启动")else:print("完成-旧程序PID未找到,直接启动")bar(0.7)# 启动jarjar_name = find_jarname(output)execute_command_shell(shell, 'cd /root/build/x-system/webapps/' + deploy_site + '-system/target', '#')execute_command_shell(shell, 'nohup java -jar ' + jar_name + '>log.out  2>&1 & ', '#')bar(0.8)print("完成-程序正在启动中...")# 查看日志确认服务启动成功log_path = '/var/log/x-system/' + deploy_site + '-system' if deploy_server == 'pro' else '/var/log/x-system/' + deploy_site + '-system-staging'execute_command_shell(shell, 'cd '+log_path, '#')execute_command_shell(shell, 'tail -200f '+deploy_site+'-system-info.log', 'TomcatWebServer:206 - Tomcat started on port(s)')bar(1)print("完成-程序启动成功")
except Exception as e:print(f"异常: {str(e)}")finally:time.sleep(10)# 关闭连接shell.close()ssh.close()

代码用try catch finally包裹,如果过程中出现任何异常,都输出错误原因 一些提示:

  1. 每个人的项目服务器的路径都不同,我只是提供个例子,不可盲目复制运行
  2. 每个人项目的名字也不同,我在文中出现类似 manage和main,是我项目模块中的名字,只是个例子,不可盲目复制
5.打包

打包命令:

pyinstaller --onefile --icon 太空人.ico --add-data ".\grapheme_break_property.json;grapheme\data"  --name 远程部署 deployment.py

打包命令中的几个参数解释一下:

  1. –onefile :将项目工程文件输出在同一个可执行文件中即exe中
  2. –icon 太空人.ico :exe的图标是一个ico的图片
  3. –add-data “.\grapheme_break_property.json;grapheme\data” : 打包时 grapheme_break_property这个依赖找不到,导致打包失败,就手动添加一下
  4. –name 远程部署 :exe的名字(注意不需要带.exe后缀)
  5. deployment.py :python工程的文件名

结语

python很好玩,希望大家玩的开心!

如果你对Python感兴趣,想要学习python,这里给大家分享一份Python全套学习资料,都是我自己学习时整理的,希望可以帮到你,一起加油!

😝有需要的小伙伴,可以V扫描下方二维码免费领取🆓

1️⃣零基础入门

① 学习路线

对于从来没有接触过Python的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
在这里插入图片描述

② 路线对应学习视频

还有很多适合0基础入门的学习视频,有了这些视频,轻轻松松上手Python~
在这里插入图片描述

③练习题

每节视频课后,都有对应的练习题哦,可以检验学习成果哈哈!
在这里插入图片描述

2️⃣国内外Python书籍、文档

① 文档和书籍资料

在这里插入图片描述

3️⃣Python工具包+项目源码合集

①Python工具包

学习Python常用的开发软件都在这里了!每个都有详细的安装教程,保证你可以安装成功哦!
在这里插入图片描述

②Python实战案例

光学理论是没用的,要学会跟着一起敲代码,动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。100+实战案例源码等你来拿!
在这里插入图片描述

③Python小游戏源码

如果觉得上面的实战案例有点枯燥,可以试试自己用Python编写小游戏,让你的学习过程中增添一点趣味!
在这里插入图片描述

4️⃣Python面试题

我们学会了Python之后,有了技能就可以出去找工作啦!下面这些面试题是都来自阿里、腾讯、字节等一线互联网大厂,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
在这里插入图片描述
在这里插入图片描述

上述所有资料 ⚡️ ,朋友们如果有需要的,可以扫描下方👇👇👇二维码免费领取🆓

效果

1688121596787.png

起因

现在springboot项目的自动化部署已经非常普遍,有用Jenkins的,有用git钩子函数的,有用docker的…等等。这段时间在玩python,想着用python实现自动化部署,即能锻炼下编码能力,又方便运维。于是开始着手写了一个exe程序,可直接在任何windows电脑上运行(不具备python环境的windows电脑也可以运行)。有兴趣的小伙伴可以跟着代码一起练一练噢,写的详细一点,对python新手也很友好。

实现步骤

开发准备

  1. 具有python基本环境和ide的windows或macOS电脑一台
  2. 安装打包工具pip install pyinstaller
  3. 一点小小的python基础

步骤

1. 导入依赖

image.png 新建一个py文件,可以把它命名为 deployment.py(名字随意哈,什么名儿都可以),然后把下面的库导入语句copy到此py文件中

import os #用于-提取文件名  
import re #用于-正则表达式  
import time #用于-线程休眠  
import paramiko #用于-远程执行linux命令  
from alive_progress import alive_bar #用于-进度条工具类  
from cryptography.fernet import Fernet #用于-加解密代码  
import base64 #用于-加解密代码  
import hashlib #用于-加解密代码

在导入依赖的时候,可能有些依赖咱们的电脑上之前没下载过,不要紧,只需要在pycharm中按 alt+enter就可以自动导入了,PyCharm跟Idea的快捷键一模一样,可以按Idea的习惯使用。而且在python中还不用配置maven或pom文件,非常方便。

2. 输入校验

部署毕竟是件严谨的事情,我们增加个部署密钥校验,我的这个部署密钥承担了以下的功能

  1. 确保部署的安全性,不是谁拿到这个exe程序都能运行的(哼~傲娇)
  2. 密钥字符串用-分割开,前面的区分环境,后面的区分项目或模块。
  3. 如果同学们不需要区分项目子模块,就不需要搞这么复杂,随便定义一个密钥就好了
import os #用于-提取文件名  
import re #用于-正则表达式  
import time #用于-线程休眠  
import paramiko #用于-远程执行linux命令  
from alive_progress import alive_bar #用于-进度条工具类  
from cryptography.fernet import Fernet #用于-加解密代码  
import base64 #用于-加解密代码  
import hashlib #用于-加解密代码  #检查密钥格式
def check_deploy_sign(deploy_site):  #确保密钥只能是以下4个之一才能继续往下操作,否则无限循环输入 或 退出程序if deploy_site != 'pro-main' and deploy_site != 'pro-manage' and deploy_site != 'test-main' and deploy_site != 'test-manage': #校验失败,一直校验new_deploy_site = input("错误:请填写部署密钥:")  check_deploy_sign(new_deploy_site)  #校验成功,退出return deploy_site  try:  deploy_sign = input("提示:请填写部署密钥:")  deploy_sign = check_deploy_sign(deploy_sign)  # 部署环境  pro代表生成环境,test代表测试环境deploy_server = deploy_sign.split('-')[0]  # 部署模块或项目 manage代表manage模块,main代表main模块, deploy_site = deploy_sign.split('-')[1]  # 打包时的包名,三目运算符package_name = 'production' if deploy_server == 'pro' else 'staging'  except Exception as e:  print(f"异常: {str(e)}")  

上面的代码中 增加了全局的异常处理,类似Java的try catch,也定义了一些基本的变量。密钥是一串由短线连接的字符串,短线前的代码用以区分环境,短线后的代码用以区分模块或项目。另外上面代码中的package_name是打包时的包名(即profiles.profile.id),一般配置在springboot项目pom文件中的编辑模块,类似下面这样:

image.png

3. 连接linux服务器
import os #用于-提取文件名  
import re #用于-正则表达式  
import time #用于-线程休眠  
import paramiko #用于-远程执行linux命令  
from alive_progress import alive_bar #用于-进度条工具类  
from cryptography.fernet import Fernet #用于-加解密代码  
import base64 #用于-加解密代码  
import hashlib #用于-加解密代码  #检查密钥格式
def check_deploy_sign(deploy_site):  #确保密钥只能是以下4个之一才能继续往下操作,否则无限循环输入 或 退出程序if deploy_site != 'pro-main' and deploy_site != 'pro-manage' and deploy_site != 'test-main' and deploy_site != 'test-manage': #校验失败,一直校验new_deploy_site = input("错误:请填写部署密钥:")  check_deploy_sign(new_deploy_site)  #校验成功,退出return deploy_site  # 连接服务器  
def connect_service(deploy_server):server_password = ''  server_host = ''  sign = hashlib.sha256(deploy_server.encode()).digest()  sign = base64.urlsafe_b64encode(sign)  if deploy_server == 'pro':  server_password = decrypt_str(sign, service_password_pro)  server_host = decrypt_str(sign, service_host_pro)  elif deploy_server == 'test':  server_password = decrypt_str(sign, service_password_test)  server_host = decrypt_str(sign, service_host_test)  else:  raise Exception('失败:部署服务器标识有误')  # 连接远程服务器  ssh = paramiko.SSHClient()  ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())  ssh.connect(server_host, username='root', password=server_password)  return ssh  # 解密密码  
def decrypt_str(key, encrypted_password):  f = Fernet(key)  decrypted_password = f.decrypt(encrypted_password).decode()  return decrypted_passwordtry:  # 服务器环境信息的加密字符串,包含各服务器的 ip和密码  service_password_pro = 'asdatrgsd=='  service_password_test = 'sgherfhdf=='  service_host_pro = 'jfhgfvdcfdtr=='  service_host_test = 'jutyrbfvret=='deploy_sign = input("提示:请填写部署密钥:")  deploy_sign = check_deploy_sign(deploy_sign)  # 部署环境  pro代表生成环境,test代表测试环境deploy_server = deploy_sign.split('-')[0]  # 部署模块或项目 manage代表manage模块,main代表main模块, deploy_site = deploy_sign.split('-')[1]  # 打包时的包名,三目运算符package_name = 'production' if deploy_server == 'pro' else 'staging'  #进度条with alive_bar(7, force_tty=True, title="进度") as bar:  # 连接服务器  ssh = connect_service(deploy_server)  bar(0.1)  print("完成-服务器连接成功")  time.sleep(0.5)
except Exception as e:  print(f"异常: {str(e)}")  

在连接服务器之前,我们加个进度条显示,方便查看部署到哪一步了,要点讲解:

  1. with alive_bar 中放的事需要进度条显示的步骤,connect_service是连接服务器的方法
  2. 主机的ip和密码我们用加密的密文显示,解密的密钥就是 手动输入的部署密钥
  3. 当一段逻辑执行完成后,通过bar(0.1)来显示进度条进度,alive_bar的第一个参数就是步骤总数
4. 部署工具主逻辑

代码要点讲解: 下面的代码是工程的全部代码,主要包含了以下逻辑

  1. 连接服务器
  2. 进入到项目工程目录,拉取git代码
  3. 编译公共依赖的代码(有的项目不一定有公共模块,可酌情删减)
  4. 编译打包程序代码
  5. 杀死旧进程
  6. 寻找编译好的程序jar包并启动
  7. 检测启动结果
import os #用于-提取文件名
import re #用于-正则表达式
import time #用于-线程休眠
import paramiko #用于-远程执行linux命令
from alive_progress import alive_bar #用于-进度条工具类
from cryptography.fernet import Fernet #用于-加解密代码
import base64 #用于-加解密代码
import hashlib #用于-加解密代码def check_deploy_sign(deploy_site):if deploy_site != 'pro-main' and deploy_site != 'pro-manage' and deploy_site != 'test-main' and deploy_site != 'test-manage':new_deploy_site = input("错误:请填写部署密钥:")check_deploy_sign(new_deploy_site)return deploy_site# 解密密码
def decrypt_str(key, encrypted_password):f = Fernet(key)decrypted_password = f.decrypt(encrypted_password).decode()return decrypted_password# 执行远程命令
def execute_command(ssh, command):stdin, stdout, stderr = ssh.exec_command(command)stdout.channel.recv_exit_status()  # 等待命令执行完毕output = stdout.read().decode('utf-8')time.sleep(0.5)return output# 执行远程命令
def execute_command_shell(shell, command, endword):shell.send(command + '\n')output = ''while True:while shell.recv_ready():recv = shell.recv(1024).decode('utf-8', errors='ignore')output += recvif endword == '# ':if output.endswith('$ ') or output.endswith('# '):breakelif endword in output:breaktime.sleep(0.5)return output# 连接服务器
def connect_service(deploy_server):  server_password = ''server_host = ''sign = hashlib.sha256(deploy_server.encode()).digest()sign = base64.urlsafe_b64encode(sign)if deploy_server == 'pro':server_password = decrypt_str(sign, service_password_pro)server_host = decrypt_str(sign, service_host_pro)elif deploy_server == 'test':server_password = decrypt_str(sign, service_password_test)server_host = decrypt_str(sign, service_host_test)else:raise Exception('失败:部署服务器标识有误')# 连接远程服务器ssh = paramiko.SSHClient()ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())ssh.connect(server_host, username='root', password=server_password)return ssh# 查询进程
def query_process(ssh, process_name):  process_id = ''command = f"ps -ef | grep {process_name}-system-master. | grep -v grep"process_output = execute_command(ssh, command)if process_output:# 提取进程ID并杀死进程process_id = process_output.split("    ")[1]return process_id# 杀掉进程
def kill_process(ssh, process_id):  command = f"kill -9 {process_id}"output = execute_command(ssh, command)return output# 寻找编译好的jar包
def find_jarname(output):match = re.search(r"Building jar: .+?\/(.+?\.jar)", output)if match:jar_filepath = match.group(1)jar_filename = os.path.basename(jar_filepath)return jar_filenameelse:raise Exception('失败:jar未找到')try:service_password_pro = 'asdatrgsd=='service_password_test = 'sgherfhdf=='service_host_pro = 'jfhgfvdcfdtr=='service_host_test = 'jutyrbfvret=='deploy_sign = input("提示:请填写部署密钥:")deploy_sign = check_deploy_sign(deploy_sign)# 部署环境deploy_server = deploy_sign.split('-')[0]# 部署模块deploy_site = deploy_sign.split('-')[1]# 部署环境对应服务正式的名字package_name = 'production' if deploy_server == 'pro' else 'staging'with alive_bar(7, force_tty=True, title="进度") as bar:# 连接服务器ssh = connect_service(deploy_server)bar(0.1)print("完成-服务器连接成功")time.sleep(0.5)# 拉取代码shell = ssh.invoke_shell()execute_command_shell(shell, 'cd /root/build/x-system','#')execute_command_shell(shell, 'git pull','#')bar(0.2)print("完成-git代码拉取成功")# 编译代码execute_command_shell(shell, 'cd /root/build/x-system/modules', '#')execute_command_shell(shell, 'mvn clean install', 'BUILD SUCCESS')bar(0.4)print("完成-公共模块编译成功")# 打包代码execute_command_shell(shell, 'cd /root/build/x-system/webapps/' + deploy_site + '-system ', '#')output=execute_command_shell(shell, 'mvn clean package -P ' + package_name, 'BUILD SUCCESS')bar(0.6)print("完成-" + deploy_site + "模块打包成功")# 查询进程,如果查不到 就不执行kill命令pid = query_process(ssh, deploy_site)if pid != '':kill_process(ssh, pid)print("完成-旧程序进程已被杀掉,等待启动")else:print("完成-旧程序PID未找到,直接启动")bar(0.7)# 启动jarjar_name = find_jarname(output)execute_command_shell(shell, 'cd /root/build/x-system/webapps/' + deploy_site + '-system/target', '#')execute_command_shell(shell, 'nohup java -jar ' + jar_name + '>log.out  2>&1 & ', '#')bar(0.8)print("完成-程序正在启动中...")# 查看日志确认服务启动成功log_path = '/var/log/x-system/' + deploy_site + '-system' if deploy_server == 'pro' else '/var/log/x-system/' + deploy_site + '-system-staging'execute_command_shell(shell, 'cd '+log_path, '#')execute_command_shell(shell, 'tail -200f '+deploy_site+'-system-info.log', 'TomcatWebServer:206 - Tomcat started on port(s)')bar(1)print("完成-程序启动成功")
except Exception as e:print(f"异常: {str(e)}")finally:time.sleep(10)# 关闭连接shell.close()ssh.close()

代码用try catch finally包裹,如果过程中出现任何异常,都输出错误原因 一些提示:

  1. 每个人的项目服务器的路径都不同,我只是提供个例子,不可盲目复制运行
  2. 每个人项目的名字也不同,我在文中出现类似 manage和main,是我项目模块中的名字,只是个例子,不可盲目复制
5.打包

打包命令:

pyinstaller --onefile --icon 太空人.ico --add-data ".\grapheme_break_property.json;grapheme\data"  --name 远程部署 deployment.py

打包命令中的几个参数解释一下:

  1. –onefile :将项目工程文件输出在同一个可执行文件中即exe中
  2. –icon 太空人.ico :exe的图标是一个ico的图片
  3. –add-data “.\grapheme_break_property.json;grapheme\data” : 打包时 grapheme_break_property这个依赖找不到,导致打包失败,就手动添加一下
  4. –name 远程部署 :exe的名字(注意不需要带.exe后缀)
  5. deployment.py :python工程的文件名

结语

python很好玩,希望大家玩的开心!

如果你对Python感兴趣,想要学习python,这里给大家分享一份Python全套学习资料,都是我自己学习时整理的,希望可以帮到你,一起加油!

😝有需要的小伙伴,可以V扫描下方二维码免费领取🆓

1️⃣零基础入门

① 学习路线

对于从来没有接触过Python的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
在这里插入图片描述

② 路线对应学习视频

还有很多适合0基础入门的学习视频,有了这些视频,轻轻松松上手Python~
在这里插入图片描述

③练习题

每节视频课后,都有对应的练习题哦,可以检验学习成果哈哈!
在这里插入图片描述

2️⃣国内外Python书籍、文档

① 文档和书籍资料

在这里插入图片描述

3️⃣Python工具包+项目源码合集

①Python工具包

学习Python常用的开发软件都在这里了!每个都有详细的安装教程,保证你可以安装成功哦!
在这里插入图片描述

②Python实战案例

光学理论是没用的,要学会跟着一起敲代码,动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。100+实战案例源码等你来拿!
在这里插入图片描述

③Python小游戏源码

如果觉得上面的实战案例有点枯燥,可以试试自己用Python编写小游戏,让你的学习过程中增添一点趣味!
在这里插入图片描述

4️⃣Python面试题

我们学会了Python之后,有了技能就可以出去找工作啦!下面这些面试题是都来自阿里、腾讯、字节等一线互联网大厂,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
在这里插入图片描述
在这里插入图片描述

上述所有资料 ⚡️ ,朋友们如果有需要的,可以扫描下方👇👇👇二维码免费领取🆓

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/711068.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

每日学习总结20240228

每日总结 20240228 1.获取系统命令执行结果 #include <stdio.h>#define TRUE 1 #define FALSE 0int get_system_cmd_result(const char *command, char *buffer, int bufferLen) {FILE *pipe popen(command, "r");if (pipe NULL) {return FALSE;}while (f…

HTML-表格、表单和CSS初识,选择器,书写规范

&#xff11;. 表格标签 &#xff11;.&#xff11;创建表格 表格标签是一种用来处理&#xff0c;显示表格式数据的常用标签。 注意&#xff1a; &#xff11;. tr 用于定义表格中的一行&#xff0c;必须嵌套在 table标签中&#xff0c;在 table中包含几对 tr&#xff0c;就有…

实用指南:SOLIDWORKS数据失真问题的解决之道

在数据处理和模拟计算的过程中&#xff0c;数据失真是一个常见的挑战。数据失真指的是由于计算机或人为操作导致的原始数据与计算结果或实际情况之间的偏差。特别是在使用SOLIDWORKS这类工程设计软件时&#xff0c;数据失真可能由多种因素引起&#xff0c;如软件版本老旧、设置…

AI大模型-启航

文章目录 什么是大模型&#xff1f;&#xff08;大体现在参数量巨大&#xff09;大模型将会改变那些行业&#xff08;大模型有哪些作用&#xff1f;&#xff09;如何搞数据训练模型&#xff1f;LangChain带来的技术变革LangChain架构 什么是大模型&#xff1f;&#xff08;大体…

Vue+SpringBoot打造不良邮件过滤系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统用户模块2.2 收件箱模块2.3 发件箱模块2.4 垃圾箱模块2.5 回收站模块2.6 邮箱过滤设置模块 三、实体类设计3.1 系统用户3.2 邮件3.3 其他实体 四、系统展示五、核心代码5.1 查询收件箱档案5.2 查询回收站档案5.3 新…

图像分割 - 查找图像的轮廓(cv2.findContours函数)

1、前言 轮廓,是指图像中或者物体的外边缘线条。在简单的几何图形中,图形的轮廓是由平滑的线条构成,容易被识别。但不规则的图形或者生活中常见的物体轮廓复杂,识别起来比较困难 2、findContours函数 这里先介绍函数的参数,具体的含义会在下面实验中阐述 opencv 提供的轮…

React入门之React_渲染基础用法和class实例写法

渲染元素 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>04元素渲染</title><script src&…

2024-2-29-网络编程作业

1>TCP 源代码: 服务器端&#xff1a; #include <myhead.h> #define SER_IP "10.168.1.111" #define SER_PORT 8888 #define MAXSIZE 128 int main(int argc, char const *argv[]) {int sfd socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in sin;sin…

RDD简介与基础编程

1. 什么是RDD&#xff1f; RDD&#xff08;Resilient Distributed Dataset&#xff09;叫做弹性分布式数据集&#xff0c;是Spark中最基本的数据处理模型。在代码中&#xff0c;RDD是一个抽象类&#xff0c;他代表着一个弹性的、不可变的、可分区的、里面的元素可并行计算的集…

android TextView 实现富文本显示

android TextView 实现富文本显示&#xff0c;实现抖音直播间公屏消息案例 使用&#xff1a; val tvContent: TextView helper.getView(R.id.tvContent)//自己根据UI业务要求&#xff0c;可以控制 图标显示 大小val levelLabel MyImgLabel( bitmap 自己业务上的bitmap )va…

第零章_计算机导论

0.1 计算机&#xff1a;辅助人脑的好工具 所谓的计算机就是一种计算器&#xff0c;而计算器其实是:『接受用户输入指令与数据&#xff0c;经由中央处理器的数学与逻辑单元运算处理后&#xff0c;以产生或储存成有用的信息』。因此&#xff0c;只要有输入设备(不管是键盘还是触摸…

HTML5:七天学会基础动画网页4

backgorund-size 值与说明 length(单位像素):设置背景图片高度和宽度&#xff0c;第一个值设置宽度&#xff0c;第二个值设置高度&#xff0c;如果只给出一个值&#xff0c;第二个是设置为auto。 percentage(百分比):以父元素的百分比来设置背景图像的宽度和高度&#xff0c…

CSS技巧:实现两个div在同一行显示的方法

css如何让两个div在同一行显示 - web开发 - 亿速云 在Web开发中&#xff0c;经常遇到需要将多个元素水平排列在同一行的情况。其中一个常见的需求是将两个div元素放置在同一行上&#xff0c;使它们并排显示。在本文中&#xff0c;我们将介绍几种实现这一效果的CSS方法。 1. 使…

day06_菜单管理(查询菜单,添加菜单,添加子菜单,修改菜单,删除菜单,角色分配菜单,查询菜单,保存菜单,动态菜单)

文章目录 1 菜单管理1.1 表结构介绍1.2 查询菜单1.2.1 需求说明1.2.2 页面制作1.2.3 后端接口SysMenuSysMenuControllerSysMenuServiceMenuHelperSysMenuMapperSysMenuMapper.xml 1.2.4 前端对接sysMenu.jssysMenu.vue 1.3 添加菜单1.3.1 需求说明1.3.3 页面制作1.3.3 后端接口…

腾讯云安装MYSQL远程连接不上解决方案

推荐安装步骤博客&#xff0c;写的很详细&#xff0c;如果不会安装的话&#xff0c;可以根据安装步骤一直走。 Windows10下超详细Mysql安装_win10安装mysql-CSDN博客 修改 my.cnf或者my.ini 找到里面bind-address将bind-address 127.0.0.1设置成bind-address 0.0.0.0&#x…

AI英语学习助手-帮助建立词库和句子-极简安装(python基于Django和 OpenAI GPT API的网站程序)

AI英语学习助手-帮助建立词库和句子-极简安装&#xff08;python基于Django和 OpenAI GPT API的网站程序&#xff09; 学了很久的英语&#xff0c;但是发现还是被单词困住了&#xff0c;天天查句子查单词太麻烦&#xff0c;现在有了Chat GPT&#xff0c;能够很好得帮助学习英语…

CSP-202109-2-非零段划分

CSP-202109-2-非零段划分 【70分思路-暴力枚举】 这段代码的目的是在给定一个由自然数&#xff08;非负整数&#xff09;组成的数组后&#xff0c;通过选择一个适当的正整数 p&#xff0c;将数组中所有小于 p 的数变为 0&#xff0c;从而使得数组中非零段的数量达到最大。这里…

使用 gma 绘制隋唐洛阳城

背景 最近河南文旅大伙&#xff0c;给家乡带了一波热度&#xff0c;想想又是王子又是公主&#xff0c;着实羡慕。出门在外&#xff0c;还是对加很有感觉得&#xff0c;不过很遗憾&#xff0c;本人不能为家乡做出贡献&#xff0c;只能使用这种小伎俩&#xff0c;稍稍展示&#…

【网络编程】理解客户端和服务器并使用Java提供的api实现回显服务器

目录 一、网络编程 二、客户端和服务器 三、客户端和服务器的交互模式 四、TCP 和 UDP UDP socket api 的使用 1、DatagramSoket 2、DatagramPacket TCP socket api 的使用 1、ServerSocket 2、Socket 一、网络编程 本质上就是学习传输层给应用层提供的 api&#x…

ARM简介

ARM&#xff1a;ARM是Advanced RISC Machine的缩写&#xff0c;意为高级精简指令集计算机。 英国ARM公司&#xff0c;2016年被软银创始人孙正义斥资320亿美元收购了。现在是软银旗下的芯片设计公司&#xff0c;总部位于英国剑桥&#xff0c;专注于设计芯片&#xff0c;卖芯片生…