4ceb5eac7e
文件结构优化: - docs/ 归档所有项目文档(PROJECT.md, PROJECT_ISSUES.md 等) - deploy/ 归档所有部署相关文件(docker-compose.prod.yml, nginx 配置等) - scripts/ 归档脚本文件(deploy.sh, rollback.sh) - tests/ 归档测试文件(test_data.php) 更新引用路径: - CLAUDE.md 更新文档路径引用 - 部署文档更新配置文件路径引用 清理文件: - 移除非必要的测试文件(TestController, 测试脚本等) - 移除重复/错误的目录 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
170 lines
3.7 KiB
Bash
Executable File
170 lines
3.7 KiB
Bash
Executable File
#!/bin/bash
|
|
# X-Server Mobile 生产部署脚本
|
|
# 使用方法: ./deploy.sh [server]
|
|
|
|
set -e
|
|
|
|
# 配置
|
|
SERVER=${1:-"your-server.com"} # 默认服务器,可以通过参数指定
|
|
DEPLOY_USER="root"
|
|
DEPLOY_PATH="/opt/x-server-mobile"
|
|
FRONTEND_BUILD_DIR="./frontend/dist"
|
|
BACKEND_SOURCE_DIR="./backend"
|
|
|
|
# 颜色输出
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
log_info() {
|
|
echo -e "${GREEN}[INFO]${NC} $1"
|
|
}
|
|
|
|
log_warn() {
|
|
echo -e "${YELLOW}[WARN]${NC} $1"
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|
}
|
|
|
|
# 检查环境
|
|
check_env() {
|
|
log_info "检查部署环境..."
|
|
|
|
if ! command -v rsync &> /dev/null; then
|
|
log_error "rsync 未安装,请先安装: apt-get install rsync"
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -d "$FRONTEND_BUILD_DIR" ]; then
|
|
log_error "前端构建目录不存在: $FRONTEND_BUILD_DIR"
|
|
log_info "请先运行: cd frontend && npm install && npm run build"
|
|
exit 1
|
|
fi
|
|
|
|
log_info "环境检查通过"
|
|
}
|
|
|
|
# 备份远程服务器
|
|
backup_remote() {
|
|
log_info "备份远程服务器..."
|
|
|
|
BACKUP_NAME="$(date +%Y%m%d_%H%M%S)"
|
|
|
|
ssh ${DEPLOY_USER}@${SERVER} << EOF
|
|
mkdir -p ${DEPLOY_PATH}/backup/${BACKUP_NAME}
|
|
cp -r ${DEPLOY_PATH}/frontend ${DEPLOY_PATH}/backup/${BACKUP_NAME}/ 2>/dev/null || true
|
|
cp -r ${DEPLOY_PATH}/backend ${DEPLOY_PATH}/backup/${BACKUP_NAME}/ 2>/dev/null || true
|
|
echo "备份完成: ${BACKUP_NAME}"
|
|
EOF
|
|
|
|
log_info "备份完成: ${BACKUP_NAME}"
|
|
}
|
|
|
|
# 部署前端
|
|
deploy_frontend() {
|
|
log_info "部署前端..."
|
|
|
|
rsync -avz --delete \
|
|
--exclude='*.map' \
|
|
${FRONTEND_BUILD_DIR}/ \
|
|
${DEPLOY_USER}@${SERVER}:${DEPLOY_PATH}/frontend/
|
|
|
|
log_info "前端部署完成"
|
|
}
|
|
|
|
# 部署后端
|
|
deploy_backend() {
|
|
log_info "部署后端..."
|
|
|
|
rsync -avz \
|
|
--exclude='vendor/' \
|
|
--exclude='runtime/' \
|
|
--exclude='.git/' \
|
|
--exclude='*.log' \
|
|
${BACKEND_SOURCE_DIR}/ \
|
|
${DEPLOY_USER}@${SERVER}:${DEPLOY_PATH}/backend/
|
|
|
|
log_info "后端部署完成"
|
|
}
|
|
|
|
# 重启服务
|
|
restart_services() {
|
|
log_info "重启服务..."
|
|
|
|
ssh ${DEPLOY_USER}@${SERVER} << 'EOF'
|
|
cd /opt/x-server-mobile
|
|
|
|
# 重启后端容器
|
|
docker-compose -f docker-compose.prod.yml restart backend
|
|
|
|
# 等待后端启动
|
|
sleep 5
|
|
|
|
# 检查容器状态
|
|
docker ps | grep x-server-backend-prod
|
|
|
|
# 重载 OpenResty
|
|
openresty -s reload || nginx -s reload
|
|
|
|
echo "服务重启完成"
|
|
EOF
|
|
|
|
log_info "服务重启完成"
|
|
}
|
|
|
|
# 健康检查
|
|
health_check() {
|
|
log_info "健康检查..."
|
|
|
|
sleep 3
|
|
|
|
# 检查前端
|
|
if curl -s -o /dev/null -w "%{http_code}" http://${SERVER}/ | grep -q "200\|301\|302"; then
|
|
log_info "前端检查通过"
|
|
else
|
|
log_warn "前端检查失败"
|
|
fi
|
|
|
|
# 检查 API
|
|
if curl -s http://${SERVER}/api/v1/health 2>/dev/null | grep -q "ok\|success"; then
|
|
log_info "API 检查通过"
|
|
else
|
|
log_warn "API 检查失败(可能需要登录)"
|
|
fi
|
|
}
|
|
|
|
# 主流程
|
|
main() {
|
|
echo "========================================="
|
|
echo " X-Server Mobile 生产部署脚本"
|
|
echo "========================================="
|
|
echo "服务器: ${SERVER}"
|
|
echo "部署路径: ${DEPLOY_PATH}"
|
|
echo ""
|
|
|
|
# 确认部署
|
|
read -p "确认部署到 ${SERVER}? (y/N) " -n 1 -r
|
|
echo
|
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
log_info "部署已取消"
|
|
exit 0
|
|
fi
|
|
|
|
check_env
|
|
backup_remote
|
|
deploy_frontend
|
|
deploy_backend
|
|
restart_services
|
|
health_check
|
|
|
|
echo ""
|
|
log_info "部署完成!"
|
|
echo "查看日志: ssh ${DEPLOY_USER}@${SERVER} 'docker logs -f x-server-backend-prod'"
|
|
}
|
|
|
|
# 执行主流程
|
|
main
|