Files
soul/开发文档/服务器管理/scripts/一键部署.py

139 lines
5.0 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
一键部署脚本
============
用途根据配置文件一键部署Node项目到宝塔服务器
使用方法
python3 一键部署.py 项目名称 本地项目路径
示例
python3 一键部署.py soul /Users/karuo/Documents/开发/3自营项目/一场soul的创业实验
"""
import sys
import os
import subprocess
import time
# 默认服务器配置
默认配置 = {
"服务器IP": "42.194.232.22",
"SSH用户": "root",
"SSH密码": "Zhiqun1984",
"服务器根目录": "/www/wwwroot"
}
def 执行命令(命令: str, 显示输出: bool = True) -> tuple:
"""执行shell命令"""
result = subprocess.run(命令, shell=True, capture_output=True, text=True)
if 显示输出 and result.stdout:
print(result.stdout)
if result.stderr and "Warning" not in result.stderr:
print(f"错误: {result.stderr}")
return result.returncode, result.stdout
def 部署项目(项目名称: str, 本地路径: str):
"""执行部署流程"""
服务器路径 = f"{默认配置['服务器根目录']}/{项目名称}"
压缩文件 = f"/tmp/{项目名称}_update.tar.gz"
print(f"\n{'='*60}")
print(f"开始部署: {项目名称}")
print(f"本地路径: {本地路径}")
print(f"服务器路径: {服务器路径}")
print(f"{'='*60}\n")
# 步骤1: 压缩项目
print("📦 步骤1: 压缩项目文件...")
排除项 = "--exclude='node_modules' --exclude='.next' --exclude='.git' --exclude='android' --exclude='out'"
压缩命令 = f"cd '{本地路径}' && tar {排除项} -czf {压缩文件} ."
code, _ = 执行命令(压缩命令, False)
if code != 0:
print("❌ 压缩失败")
return False
# 获取文件大小
大小 = os.path.getsize(压缩文件) / 1024 / 1024
print(f" ✅ 压缩完成,大小: {大小:.2f} MB")
# 步骤2: 上传到服务器
print("\n📤 步骤2: 上传到服务器...")
上传命令 = f"sshpass -p '{默认配置['SSH密码']}' scp -o StrictHostKeyChecking=no {压缩文件} {默认配置['SSH用户']}@{默认配置['服务器IP']}:/tmp/"
code, _ = 执行命令(上传命令, False)
if code != 0:
print("❌ 上传失败")
return False
print(" ✅ 上传完成")
# 步骤3-6: SSH远程执行
print("\n🔧 步骤3-6: 服务器端操作...")
SSH前缀 = f"sshpass -p '{默认配置['SSH密码']}' ssh -o StrictHostKeyChecking=no {默认配置['SSH用户']}@{默认配置['服务器IP']}"
# 清理旧文件
清理命令 = f"{SSH前缀} 'cd {服务器路径} && rm -rf app components lib public styles *.json *.js *.ts *.mjs *.md .next 2>/dev/null || true'"
执行命令(清理命令, False)
print(" ✅ 清理旧文件")
# 解压
解压命令 = f"{SSH前缀} 'cd {服务器路径} && tar -xzf /tmp/{项目名称}_update.tar.gz'"
执行命令(解压命令, False)
print(" ✅ 解压新代码")
# 安装依赖
print("\n📚 安装依赖 (这可能需要几分钟)...")
安装命令 = f"{SSH前缀} 'export PATH=/www/server/nodejs/v22.14.0/bin:$PATH && cd {服务器路径} && npm install --legacy-peer-deps 2>&1'"
执行命令(安装命令, True)
# 构建
print("\n🏗️ 构建项目...")
构建命令 = f"{SSH前缀} 'export PATH=/www/server/nodejs/v22.14.0/bin:$PATH && cd {服务器路径} && npm run build 2>&1'"
执行命令(构建命令, True)
# 重启PM2
print("\n🔄 重启服务...")
重启命令 = f"{SSH前缀} 'export PATH=/www/server/nodejs/v22.14.0/bin:$PATH && pm2 restart {项目名称} 2>&1'"
执行命令(重启命令, True)
# 清理临时文件
清理临时命令 = f"{SSH前缀} 'rm -f /tmp/{项目名称}_update.tar.gz'"
执行命令(清理临时命令, False)
os.remove(压缩文件)
print(f"\n{'='*60}")
print("✅ 部署完成!")
print(f"{'='*60}")
print("\n⚠️ 请在宝塔面板手动重启项目:")
print(f" 1. 登录 https://42.194.232.22:9988/ckbpanel")
print(f" 2. 进入【网站】→【Node项目】")
print(f" 3. 找到 {项目名称},点击【重启】")
return True
def main():
if len(sys.argv) < 3:
print("用法: python3 一键部署.py <项目名称> <本地项目路径>")
print("\n示例:")
print(" python3 一键部署.py soul /Users/karuo/Documents/开发/3、自营项目/一场soul的创业实验")
print(" python3 一键部署.py kr_wb /Users/karuo/Documents/开发/4、小工具/whiteboard")
sys.exit(1)
项目名称 = sys.argv[1]
本地路径 = sys.argv[2]
if not os.path.exists(本地路径):
print(f"❌ 本地路径不存在: {本地路径}")
sys.exit(1)
确认 = input(f"\n确认部署 {项目名称} 到服务器? (y/n): ")
if 确认.lower() != 'y':
print("已取消部署")
sys.exit(0)
部署项目(项目名称, 本地路径)
if __name__ == "__main__":
main()