Files
full-stack-doc/backend/build_linux.py
2025-10-14 20:05:29 +08:00

332 lines
8.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
云盘后端Linux打包脚本
使用PyInstaller将后端应用打包成Linux可执行文件
"""
import os
import sys
import shutil
import subprocess
from pathlib import Path
import argparse
def check_python_version():
"""检查Python版本"""
if sys.version_info < (3, 8):
print("错误: 需要Python 3.8或更高版本")
sys.exit(1)
print(f"[OK] Python版本: {sys.version}")
def check_dependencies():
"""检查必要的依赖"""
try:
import PyInstaller
print(f"[OK] PyInstaller版本: {PyInstaller.__version__}")
except ImportError:
print("错误: 未安装PyInstaller")
print("请运行: pip install pyinstaller")
sys.exit(1)
def clean_build_dirs():
"""清理之前的构建目录"""
dirs_to_clean = ['build', 'dist', '__pycache__']
for dir_name in dirs_to_clean:
if os.path.exists(dir_name):
print(f"清理目录: {dir_name}")
shutil.rmtree(dir_name)
# 清理Python缓存文件
for root, dirs, files in os.walk('.'):
for file in files:
if file.endswith('.pyc') or file.endswith('.pyo'):
os.remove(os.path.join(root, file))
if '__pycache__' in dirs:
shutil.rmtree(os.path.join(root, '__pycache__'))
def create_spec_file():
"""创建或更新PyInstaller规格文件"""
# 直接使用现有的build.spec文件
print("[OK] build.spec 文件已存在,跳过创建")
def run_pyinstaller():
"""运行PyInstaller进行打包"""
print("开始打包...")
try:
# 使用spec文件进行打包
cmd = ['pyinstaller', '--clean', 'build.spec']
result = subprocess.run(cmd, check=True, capture_output=True, text=True)
print("[OK] PyInstaller执行成功")
if result.stdout:
print("输出:", result.stdout)
except subprocess.CalledProcessError as e:
print(f"错误: PyInstaller执行失败: {e}")
if e.stderr:
print("错误输出:", e.stderr)
sys.exit(1)
def create_deployment_package():
"""创建部署包"""
dist_dir = Path('dist')
deploy_dir = Path('deploy')
if deploy_dir.exists():
shutil.rmtree(deploy_dir)
deploy_dir.mkdir()
# 复制可执行文件
exe_file = dist_dir / 'cloud-drive-server'
if exe_file.exists():
shutil.copy2(exe_file, deploy_dir)
print(f"[OK] 复制可执行文件到 {deploy_dir}")
# 复制配置文件
config_files = ['.env.example']
for config_file in config_files:
if os.path.exists(config_file):
shutil.copy2(config_file, deploy_dir)
print(f"[OK] 复制配置文件 {config_file}")
# 复制安装脚本
install_scripts = ['install.sh', 'install_user.sh']
for script in install_scripts:
if os.path.exists(script):
shutil.copy2(script, deploy_dir)
os.chmod(deploy_dir / script, 0o755)
print(f"[OK] 复制安装脚本 {script}")
# 创建部署目录结构
(deploy_dir / 'logs').mkdir(exist_ok=True)
(deploy_dir / 'uploads').mkdir(exist_ok=True)
# 创建启动脚本
create_startup_script(deploy_dir)
# 创建README
create_readme(deploy_dir)
print(f"[OK] 部署包创建完成: {deploy_dir.absolute()}")
deploy_dir.mkdir()
# 复制可执行文件
exe_file = dist_dir / 'cloud-drive-server'
if exe_file.exists():
shutil.copy2(exe_file, deploy_dir)
print(f"[OK] 复制可执行文件到 {deploy_dir}")
# 复制配置文件
config_files = ['.env.example']
for config_file in config_files:
if os.path.exists(config_file):
shutil.copy2(config_file, deploy_dir)
print(f"[OK] 复制配置文件 {config_file}")
# 创建部署目录结构
(deploy_dir / 'logs').mkdir(exist_ok=True)
(deploy_dir / 'uploads').mkdir(exist_ok=True)
# 创建启动脚本
create_startup_script(deploy_dir)
# 创建README
create_readme(deploy_dir)
print(f"[OK] 部署包创建完成: {deploy_dir.absolute()}")
def create_startup_script(deploy_dir):
"""创建启动脚本"""
# Linux启动脚本
startup_script = '''#!/bin/bash
# 云盘后端服务启动脚本
# 设置环境变量
export PYTHONPATH=${PYTHONPATH}:$(dirname "$0")
# 进入脚本所在目录
cd "$(dirname "$0")"
# 检查环境文件
if [ ! -f ".env" ]; then
echo "警告: .env 文件不存在,将使用默认配置"
if [ -f ".env.example" ]; then
cp .env.example .env
echo "已复制 .env.example 为 .env请根据需要修改配置"
fi
fi
# 创建必要的目录
mkdir -p logs uploads
# 启动服务
echo "启动云盘后端服务..."
./cloud-drive-server
'''
script_path = deploy_dir / 'start.sh'
with open(script_path, 'w', encoding='utf-8') as f:
f.write(startup_script)
# 设置执行权限
os.chmod(script_path, 0o755)
print("[OK] 创建启动脚本 start.sh")
def create_readme(deploy_dir):
"""创建部署说明文档"""
readme_content = '''# 云盘后端服务部署说明
## 文件说明
- `cloud-drive-server`: 主程序可执行文件
- `start.sh`: 启动脚本
- `.env.example`: 环境配置示例文件
## 快速开始
1. **配置环境变量**
```bash
cp .env.example .env
# 编辑 .env 文件配置数据库和Redis连接信息
nano .env
```
2. **启动服务**
```bash
chmod +x start.sh
./start.sh
```
或者直接运行:
```bash
./cloud-drive-server
```
3. **访问服务**
- API文档: http://localhost:8000/docs
- 健康检查: http://localhost:8000/api/v1/health
## 环境配置
主要配置项(.env文件
```env
# 数据库配置
DATABASE_URL=mysql+pymysql://用户名:密码@主机:端口/数据库名
# Redis配置
REDIS_URL=redis://主机:端口
# JWT配置
JWT_SECRET_KEY=你的密钥
JWT_EXPIRE_MINUTES=30
# 文件上传配置
UPLOAD_DIR=uploads
MAX_FILE_SIZE=10485760 # 10MB
```
## 系统要求
- Linux 64位系统
- MySQL 5.7+ 或 8.0+
- Redis (可选)
- 至少512MB内存
- 至少100MB磁盘空间
## 日志
日志文件位置:`logs/app.log`
## 问题排查
1. **端口占用**
- 默认端口8000如需修改请编辑.env文件
2. **数据库连接失败**
- 检查DATABASE_URL配置
- 确保数据库服务正在运行
- 检查防火墙设置
3. **权限问题**
- 确保程序有执行权限:`chmod +x cloud-drive-server`
- 确保有写入logs和uploads目录的权限
## 后台运行
使用systemd或supervisor管理服务进程
### systemd 配置示例
创建服务文件 `/etc/systemd/system/cloud-drive.service`
```ini
[Unit]
Description=Cloud Drive Backend Service
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/path/to/deploy/directory
ExecStart=/path/to/deploy/directory/cloud-drive-server
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
```
启用和启动服务:
```bash
sudo systemctl daemon-reload
sudo systemctl enable cloud-drive
sudo systemctl start cloud-drive
```
'''
readme_path = deploy_dir / 'README.md'
with open(readme_path, 'w', encoding='utf-8') as f:
f.write(readme_content)
print("[OK] 创建部署说明文档 README.md")
def main():
"""主函数"""
parser = argparse.ArgumentParser(description='云盘后端Linux打包工具')
parser.add_argument('--clean', action='store_true', help='仅清理构建目录')
parser.add_argument('--no-clean', action='store_true', help='跳过清理步骤')
args = parser.parse_args()
print("=== 云盘后端Linux打包工具 ===")
print(f"当前目录: {os.getcwd()}")
# 检查环境
check_python_version()
check_dependencies()
# 清理构建目录
if args.clean:
clean_build_dirs()
print("[OK] 清理完成")
return
if not args.no_clean:
clean_build_dirs()
# 创建规格文件
create_spec_file()
# 运行打包
run_pyinstaller()
# 创建部署包
create_deployment_package()
print("\n=== 打包完成 ===")
print("部署包位置: ./deploy/")
print("请查看 ./deploy/README.md 了解部署说明")
if __name__ == '__main__':
main()