#!/bin/bash set -e # 出错时终止脚本 # 配置信息 APP_DIR="/root/AutoScraperX" LOG_FILE="${APP_DIR}/logs/autoscraperx_deploy.log" # 部署日志路径(统一到项目logs目录) VENV_DIR="${APP_DIR}/venv" # 虚拟环境路径(与项目中实际venv目录对应) PYTHON="${VENV_DIR}/bin/python" # 虚拟环境Python解释器 PIP="${VENV_DIR}/bin/pip" # 虚拟环境pip工具 REQUIREMENTS="${APP_DIR}/requirements.txt" STARTUP_LOG="${APP_DIR}/logs/main_startup.log" # 服务启动日志 # 日志函数 log() { local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $1" echo "$msg" echo "$msg" >> "$LOG_FILE" } # 错误处理函数 handle_error() { log "部署失败: $1" exit 1 } # 确保目录存在 ensure_dir() { if [ ! -d "$1" ]; then log "创建目录: $1" mkdir -p "$1" || handle_error "无法创建目录 $1" fi } # 检查文件权限 check_permission() { if [ ! -x "$1" ]; then log "修复文件权限: $1" chmod +x "$1" || handle_error "无法修复 $1 权限" fi } # 主函数 main() { # 前置检查:确保项目目录存在 ensure_dir "$APP_DIR" ensure_dir "${APP_DIR}/logs" # 确保日志目录存在 check_permission "${APP_DIR}/run.sh" # 修复run.sh权限 log "===== 开始部署 AutoScraperX =====" cd "$APP_DIR" || handle_error "应用目录不存在: $APP_DIR" # 拉取最新代码(如果是Git仓库) log "拉取最新代码..." if [ -d ".git" ]; then git pull origin master || handle_error "Git拉取失败" else log "警告: 当前目录不是Git仓库,跳过拉取" fi # 创建或更新虚拟环境 log "检查虚拟环境..." if [ ! -d "$VENV_DIR" ]; then log "创建新的虚拟环境..." python3 -m venv "$VENV_DIR" || handle_error "创建虚拟环境失败" fi # 安装依赖(使用虚拟环境pip) log "安装Python依赖..." "$PIP" install --upgrade pip || handle_error "更新pip失败" "$PIP" install -r "$REQUIREMENTS" || handle_error "安装依赖失败" # 停止现有服务(精准匹配虚拟环境Python) log "停止现有服务..." pkill -f "${PYTHON} main.py" || true # 忽略"无进程可杀"的错误 sleep 2 # 等待进程终止 # 启动服务(输出日志到文件,便于排查) log "启动新服务...(日志: ${STARTUP_LOG})" nohup "${PYTHON}" main.py > "${STARTUP_LOG}" 2>&1 & sleep 3 # 延长等待时间,确保服务有足够时间启动 # 检查服务状态(更可靠的检测方式) if ps aux | grep -v grep | grep -E "${PYTHON}.*main\.py" > /dev/null; then log "服务已成功启动!" else # 启动失败时,输出启动日志片段帮助排查 log "服务启动失败!启动日志最后10行:" tail -n 10 "${STARTUP_LOG}" >> "$LOG_FILE" # 将启动日志尾部写入部署日志 handle_error "服务启动失败,详情见启动日志: ${STARTUP_LOG}" fi log "===== 部署完成 =====" } # 执行主函数 main