#!/bin/bash # Ubuntu 环境快速设置脚本 set -e # 遇到错误立即退出 # 确保使用 bash 运行(兼容性问题处理) if [ -z "$BASH_VERSION" ]; then echo "警告: 此脚本需要使用 bash 运行" echo "请使用: bash $0" exit 1 fi echo "==========================================" echo "京东物流提取工具 - Ubuntu 环境设置" echo "==========================================" echo "" # 1. 检查并安装系统依赖 echo "步骤 1: 检查系统依赖..." if ! command -v python3 >/dev/null 2>&1; then echo "安装 Python3..." sudo apt update sudo apt install -y python3 python3-pip python3-venv else echo "✅ Python3 已安装" fi # 检查 Chrome/Chromium CHROME_PATH="" if command -v google-chrome >/dev/null 2>&1; then CHROME_PATH=$(which google-chrome) echo "✅ 找到 Google Chrome: $CHROME_PATH" elif [ -f "/usr/bin/google-chrome" ]; then CHROME_PATH="/usr/bin/google-chrome" echo "✅ 找到 Google Chrome: $CHROME_PATH" elif command -v chromium-browser >/dev/null 2>&1; then CHROME_PATH=$(which chromium-browser) echo "✅ 找到 Chromium: $CHROME_PATH" elif [ -f "/usr/bin/chromium-browser" ]; then CHROME_PATH="/usr/bin/chromium-browser" echo "✅ 找到 Chromium: $CHROME_PATH" else echo "⚠️ 未找到 Chrome/Chromium,将尝试安装..." echo "选择要安装的浏览器:" echo "1) Google Chrome (推荐)" echo "2) Chromium (开源版本)" read -p "请选择 [1-2]: " choice if [ "$choice" = "1" ]; then echo "正在安装 Google Chrome..." wget -q https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb sudo apt install -y ./google-chrome-stable_current_amd64.deb rm -f google-chrome-stable_current_amd64.deb CHROME_PATH="/usr/bin/google-chrome" elif [ "$choice" = "2" ]; then echo "正在安装 Chromium..." sudo apt update sudo apt install -y chromium-browser CHROME_PATH="/usr/bin/chromium-browser" fi fi # 2. 安装 Chrome 运行时依赖 echo "" echo "步骤 2: 检查 Chrome 运行时依赖..." DEPS="libnss3 libatk-bridge2.0-0 libdrm2 libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1 libasound2" MISSING_DEPS="" for dep in $DEPS; do if ! dpkg -l 2>/dev/null | grep -q "^ii.*$dep"; then if [ -z "$MISSING_DEPS" ]; then MISSING_DEPS="$dep" else MISSING_DEPS="$MISSING_DEPS $dep" fi fi done if [ -n "$MISSING_DEPS" ]; then echo "安装缺失的依赖: $MISSING_DEPS" sudo apt install -y $MISSING_DEPS else echo "✅ 所有依赖已安装" fi # 3. 创建虚拟环境 echo "" echo "步骤 3: 设置 Python 虚拟环境..." if [ ! -d "venv" ]; then echo "创建虚拟环境..." python3 -m venv venv echo "✅ 虚拟环境创建成功" else echo "✅ 虚拟环境已存在" # 检查虚拟环境是否正常 if [ ! -f "venv/bin/pip" ]; then echo "⚠️ 虚拟环境可能已损坏,正在重新创建..." rm -rf venv python3 -m venv venv echo "✅ 虚拟环境重新创建成功" fi fi # 4. 激活虚拟环境并安装 Python 包 echo "" echo "步骤 4: 安装 Python 依赖包..." # 检查并修复 activate 脚本的行尾符问题 if [ -f "venv/bin/activate" ]; then # 修复可能的行尾符问题 sed -i 's/\r$//' venv/bin/activate 2>/dev/null || true fi # 激活虚拟环境 source venv/bin/activate # 验证虚拟环境是否正常激活 if [ -z "$VIRTUAL_ENV" ]; then echo "❌ 错误: 虚拟环境激活失败,尝试重新创建..." deactivate 2>/dev/null || true rm -rf venv python3 -m venv venv source venv/bin/activate fi # 升级 pip(使用 python3 -m pip 避免行尾符问题) echo "升级 pip..." python3 -m pip install --upgrade pip # 安装依赖 echo "安装 DrissionPage..." python3 -m pip install DrissionPage # 安装 Flask(API 服务需要) echo "安装 Flask..." python3 -m pip install flask # 可选:如果需要数据库功能 read -p "是否需要数据库功能?(sqlalchemy, pymysql) [y/N]: " need_db if [ "$need_db" = "y" ] || [ "$need_db" = "Y" ]; then echo "安装数据库相关包..." python3 -m pip install sqlalchemy pymysql fi deactivate # 5. 创建运行脚本 echo "" echo "步骤 5: 创建便捷运行脚本..." cat > run_logistics.sh << 'EOF' #!/bin/bash # 激活虚拟环境并运行物流提取脚本 # 获取脚本所在目录 SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" cd "$SCRIPT_DIR" # 检查虚拟环境是否存在 if [ ! -d "venv" ]; then echo "❌ 错误: 虚拟环境不存在,请先运行 setup_ubuntu.sh" exit 1 fi # 修复可能的行尾符问题 if [ -f "venv/bin/activate" ]; then sed -i 's/\r$//' venv/bin/activate 2>/dev/null || true fi # 激活虚拟环境 source venv/bin/activate # 验证虚拟环境是否激活成功 if [ -z "$VIRTUAL_ENV" ]; then echo "❌ 错误: 虚拟环境激活失败" exit 1 fi # 使用虚拟环境中的 Python3 PYTHON_CMD="$VIRTUAL_ENV/bin/python3" if [ ! -f "$PYTHON_CMD" ]; then PYTHON_CMD="python3" fi # 检查脚本文件是否存在 SCRIPT_FILE="jd/fetch_logistics_ubuntu.py" if [ ! -f "$SCRIPT_FILE" ]; then echo "❌ 错误: 找不到脚本文件 $SCRIPT_FILE" echo "当前目录: $(pwd)" echo "文件列表:" ls -la jd/ 2>/dev/null || echo " jd/ 目录不存在" echo "" echo "请确保脚本文件存在" deactivate exit 1 fi # 检查文件是否为空 if [ ! -s "$SCRIPT_FILE" ]; then echo "❌ 错误: 脚本文件 $SCRIPT_FILE 为空" deactivate exit 1 fi # 修复脚本文件的行尾符问题 sed -i 's/\r$//' "$SCRIPT_FILE" 2>/dev/null || true # 检查是否要后台运行 BACKGROUND=false ARGS=() for arg in "$@"; do if [ "$arg" = "--background" ] || [ "$arg" = "-b" ] || [ "$arg" = "--daemon" ] || [ "$arg" = "-d" ]; then BACKGROUND=true else ARGS+=("$arg") fi done # 运行脚本 echo "使用 Python: $PYTHON_CMD" echo "运行脚本: $SCRIPT_FILE" echo "脚本大小: $(wc -c < "$SCRIPT_FILE") 字节" if [ "$BACKGROUND" = "true" ]; then # 后台运行模式 LOG_FILE="logistics_service.log" PID_FILE="logistics_service.pid" echo "以后台模式启动服务..." echo "日志文件: $LOG_FILE" echo "PID 文件: $PID_FILE" echo "" # 使用 nohup 后台运行,确保使用虚拟环境的 Python # 注意:不传递 --background 参数给 Python 脚本 nohup $PYTHON_CMD -u "$SCRIPT_FILE" "${ARGS[@]}" > "$LOG_FILE" 2>&1 & PID=$! echo $PID > "$PID_FILE" # 等待一下,检查进程是否启动成功 sleep 3 if ps -p $PID > /dev/null 2>&1; then echo "✅ 服务已启动,PID: $PID" echo "" echo "使用以下命令管理服务:" echo " 查看日志: tail -f $LOG_FILE" echo " 停止服务: ./manage_service.sh stop" echo " 查看状态: ./manage_service.sh status" echo "" # 后台模式下,不退出虚拟环境(因为后台进程已经独立运行) # 直接退出脚本 exit 0 else echo "❌ 服务启动失败,请查看日志: $LOG_FILE" rm -f "$PID_FILE" deactivate exit 1 fi else # 前台运行模式 echo "参数: ${ARGS[@]}" echo "" echo "以前台模式启动服务(按 Ctrl+C 停止)..." echo "" # 使用 -u 参数确保输出不被缓冲,并明确指定以脚本模式运行 # 使用 exec 替换当前进程,这样 deactivate 不会执行 exec $PYTHON_CMD -u "$SCRIPT_FILE" "${ARGS[@]}" # 如果 exec 失败(不应该发生),才会执行到这里 EXIT_CODE=$? deactivate exit $EXIT_CODE fi EOF chmod +x run_logistics.sh # 创建服务管理脚本 cat > manage_service.sh << 'EOF' #!/bin/bash # 物流服务管理脚本 SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" cd "$SCRIPT_DIR" PID_FILE="logistics_service.pid" LOG_FILE="logistics_service.log" case "$1" in start) echo "启动物流服务..." if [ -f "$PID_FILE" ]; then PID=$(cat "$PID_FILE") if ps -p $PID > /dev/null 2>&1; then echo "⚠️ 服务已在运行,PID: $PID" exit 1 else rm -f "$PID_FILE" fi fi # 重定向输出,避免显示在终端 ./run_logistics.sh --background > /dev/null 2>&1 sleep 2 if [ -f "$PID_FILE" ]; then PID=$(cat "$PID_FILE") if ps -p $PID > /dev/null 2>&1; then echo "✅ 服务已启动,PID: $PID" echo "查看日志: tail -f $LOG_FILE" else echo "❌ 服务启动失败,请查看日志: $LOG_FILE" exit 1 fi else echo "❌ 服务启动失败,请查看日志: $LOG_FILE" exit 1 fi ;; stop) echo "停止物流服务..." if [ ! -f "$PID_FILE" ]; then echo "⚠️ PID 文件不存在,服务可能未运行" exit 1 fi PID=$(cat "$PID_FILE") if ps -p $PID > /dev/null 2>&1; then kill $PID sleep 1 if ps -p $PID > /dev/null 2>&1; then echo "强制停止服务..." kill -9 $PID fi rm -f "$PID_FILE" echo "✅ 服务已停止" else echo "⚠️ 进程不存在,清理 PID 文件" rm -f "$PID_FILE" fi ;; restart) echo "重启物流服务..." $0 stop sleep 2 $0 start ;; status) if [ -f "$PID_FILE" ]; then PID=$(cat "$PID_FILE") if ps -p $PID > /dev/null 2>&1; then echo "✅ 服务正在运行" echo "PID: $PID" echo "进程信息:" ps -p $PID -o pid,ppid,cmd,etime else echo "❌ 服务未运行(PID 文件存在但进程不存在)" rm -f "$PID_FILE" fi else echo "❌ 服务未运行" fi ;; logs) if [ -f "$LOG_FILE" ]; then tail -f "$LOG_FILE" else echo "日志文件不存在: $LOG_FILE" fi ;; *) echo "用法: $0 {start|stop|restart|status|logs}" echo "" echo "命令说明:" echo " start - 启动服务(后台运行)" echo " stop - 停止服务" echo " restart - 重启服务" echo " status - 查看服务状态" echo " logs - 查看实时日志" exit 1 ;; esac EOF chmod +x manage_service.sh # 6. 完成 echo "" echo "==========================================" echo "✅ 环境设置完成!" echo "==========================================" echo "" echo "快速开始:" echo " 方式1: 使用便捷脚本(前台运行)" echo " ./run_logistics.sh" echo "" echo " 方式2: 后台运行服务" echo " ./run_logistics.sh --background" echo " 或" echo " ./run_logistics.sh -b" echo "" echo " 方式3: 手动运行" echo " source venv/bin/activate" echo " python jd/fetch_logistics_ubuntu.py" echo " deactivate" echo "" echo "后台运行管理:" echo " 方式1: 使用管理脚本(推荐)" echo " ./manage_service.sh start - 启动服务" echo " ./manage_service.sh stop - 停止服务" echo " ./manage_service.sh restart - 重启服务" echo " ./manage_service.sh status - 查看状态" echo " ./manage_service.sh logs - 查看日志" echo "" echo " 方式2: 直接使用 run_logistics.sh" echo " ./run_logistics.sh --background - 后台启动" echo " tail -f logistics_service.log - 查看日志" echo " kill \$(cat logistics_service.pid) - 停止服务" echo "" echo "浏览器路径: $CHROME_PATH" echo "虚拟环境: $(pwd)/venv" echo ""