332 lines
8.2 KiB
Python
332 lines
8.2 KiB
Python
#!/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() |