用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.pswp.cn/news/711068.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/711068.shtml
英文地址,請注明出處:http://en.pswp.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;大體…

九、GG bond的邏輯運算

描述 GG bond想要鍛煉自己的邏輯能力&#xff0c;于是輸入了兩個整型變量x和y&#xff0c;分別判斷它們的與、或、非關系&#xff0c;你能幫他輸出x與y&#xff0c;x或y&#xff0c;非x&#xff0c;非y的值嗎&#xff1f; 輸入描述&#xff1a; 輸入兩個整數x和y&#xff0c…

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 新…

Linux學習-etcdctl安裝

etcdctl3.5下載鏈接 1. 先通過上面鏈接下載gz包2. 解壓 [rootk8s-master ~]# tar xf etcd-v3.5.11-linux-amd64.tar.gz [rootk8s-master etcd-v3.5.11-linux-amd64]# ls Documentation etcd etcdctl etcdutl README-etcdctl.md README-etcdutl.md README.md READMEv2-e…

圖像分割 - 查找圖像的輪廓(cv2.findContours函數)

1、前言 輪廓,是指圖像中或者物體的外邊緣線條。在簡單的幾何圖形中,圖形的輪廓是由平滑的線條構成,容易被識別。但不規則的圖形或者生活中常見的物體輪廓復雜,識別起來比較困難 2、findContours函數 這里先介紹函數的參數,具體的含義會在下面實驗中闡述 opencv 提供的輪…

『大模型筆記』自用的“科技文章翻譯 GPT”和它的 Prompt

自用的“科技文章翻譯 GPT”和它的 Prompt 你是一位精通簡體中文的專業翻譯,尤其擅長將專業學術論文翻譯成淺顯易懂的科普文章。請你幫我將以下英文段落翻譯成中文,風格與中文科普讀物相似。規則: - 翻譯時要準確傳達原文的事實和背景。 - 即使上意譯也要保留原始段落格式,…

每天一個數據分析題(一百八十四)

在下列哪種情況下線性回歸模型不適合代替邏輯回歸模型&#xff1f; A. 預測的目標變量是連續型的并且分布范圍不受限制 B. 預測的目標變量是二元的并且服從二項分布 C. 自變量與因變量之間的關系可以假設為線性關系 D. 需要預測客戶的具體購買金額 題目來源于CDA模擬題庫 …

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&…

什么是RPC?談談你對RPC的理解

RPC&#xff08;Remote Procedure Call&#xff0c;遠程過程調用&#xff09;是一種計算機通信協議。它允許一臺計算機&#xff08;客戶端&#xff09;通過網絡調用另一臺計算機&#xff08;服務器&#xff09;上的程序&#xff0c;并等待該程序的結果返回。RPC抽象了網絡通信的…

go mod中如何解決 xxx/yyy/lib@v1.1.0: unrecognized import path

需要檢查的幾個地方 這個錯誤通常出現在 Go 模塊系統無法找到指定版本的模塊時。有幾種可能的原因和解決方法&#xff1a; 模塊未被發布或標記&#xff1a; 確保 xxx/yyy/lib 模塊的版本 v1.1.0 已經被正確地發布或標記。你可以在對應的 GitLab 倉庫中查看是否存在 v1.1.0 標簽…

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…

代碼隨想錄算法訓練營|day47

第九章 動態規劃 198.打家劫舍213.打家劫舍II337.打家劫舍III代碼隨想錄文章詳解 198.打家劫舍 dp[i]表示偷第i家及之前所能獲取的最大金額 偷第i家&#xff1a;dp[i] dp[i-2]nums[i]&#xff0c;不偷第i家&#xff1a;dp[i] dp[i-1] func rob(nums []int) int {if len(num…

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;只要有輸入設備(不管是鍵盤還是觸摸…

UE5基于RumtimeFBXImport插件使用C++加載服務器上fbx文件方法

UE5的RumtimeFBXImport插件其實只能加載本機的fbx文件&#xff0c;要加載服務器上的fbx文件的話&#xff0c;需要先將該fbx文件下載到本地&#xff0c;然后再使用RumtimeFBXImport插件加載。 示例文件如下&#xff1a; #include "Loader/WebLoader.h" #include &quo…

HTML5:七天學會基礎動畫網頁4

backgorund-size 值與說明 length(單位像素):設置背景圖片高度和寬度&#xff0c;第一個值設置寬度&#xff0c;第二個值設置高度&#xff0c;如果只給出一個值&#xff0c;第二個是設置為auto。 percentage(百分比):以父元素的百分比來設置背景圖像的寬度和高度&#xff0c…