Files
tools/jdckup.sh
T
sushen339 0e326f10fc
2025-10-20 13:36:17 +08:00

384 lines
10 KiB
Bash
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.
#!/bin/bash
# jdckup.sh - 京东Cookie自动更新工具安装脚本
# 描述: 自动化安装和配置 AutoUpdateJdCookie 项目
set -euo pipefail # 严格模式:遇到错误立即退出,未定义变量报错,管道命令失败即退出
# ============================================
# 配置变量
# ============================================
readonly SCRIPT_NAME="JdCkup Installer"
readonly REPO_URL="https://github.com/icepage/AutoUpdateJdCookie.git"
readonly PROJECT_DIR="AutoUpdateJdCookie"
readonly VENV_NAME="jdckup_env"
PYTHON_CMD="" # 动态检测的 Python 命令
LOG_FILE="jdckup_install_$(date +%Y%m%d_%H%M%S).log"
readonly LOG_FILE
# 颜色定义
readonly COLOR_RED='\033[0;31m'
readonly COLOR_GREEN='\033[0;32m'
readonly COLOR_YELLOW='\033[1;33m'
readonly COLOR_BLUE='\033[0;34m'
readonly COLOR_RESET='\033[0m'
# ============================================
# 工具函数
# ============================================
# 日志函数
log_info() {
echo -e "${COLOR_BLUE}[INFO]${COLOR_RESET} $(date '+%Y-%m-%d %H:%M:%S') - $*" | tee -a "$LOG_FILE"
}
log_success() {
echo -e "${COLOR_GREEN}[SUCCESS]${COLOR_RESET} $(date '+%Y-%m-%d %H:%M:%S') - $*" | tee -a "$LOG_FILE"
}
log_warning() {
echo -e "${COLOR_YELLOW}[WARNING]${COLOR_RESET} $(date '+%Y-%m-%d %H:%M:%S') - $*" | tee -a "$LOG_FILE"
}
log_error() {
echo -e "${COLOR_RED}[ERROR]${COLOR_RESET} $(date '+%Y-%m-%d %H:%M:%S') - $*" | tee -a "$LOG_FILE" >&2
}
# 带进度条的后台执行
run_with_progress() {
local description=$1
local command=$2
local log_file=$3
# 在后台执行命令
eval "$command" >> "$log_file" 2>&1 &
local pid=$!
# 显示进度动画
local spin='⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏'
local i=0
echo -n "$description: "
while kill -0 $pid 2>/dev/null; do
i=$(( (i+1) % 10 ))
printf "\r%s: %b%s%b 处理中..." "$description" "${COLOR_BLUE}" "${spin:$i:1}" "${COLOR_RESET}"
sleep 0.1
done
# 等待进程完成
wait $pid
local exit_code=$?
if [ $exit_code -eq 0 ]; then
printf "\r%s: %b✓%b 完成\n" "$description" "${COLOR_GREEN}" "${COLOR_RESET}"
else
printf "\r%s: %b✗%b 失败\n" "$description" "${COLOR_RED}" "${COLOR_RESET}"
fi
return $exit_code
}
# 检查命令是否存在
command_exists() {
command -v "$1" >/dev/null 2>&1
}
# 检查上一个命令的执行结果
check_result() {
if [ $? -ne 0 ]; then
log_error "$1"
exit 1
fi
}
# ============================================
# 安装函数
# ============================================
# 检测可用的 Python 版本
detect_python_version() {
log_info "检测系统 Python 版本..."
# 按优先级检测 Python 版本
local python_candidates=("python3.13" "python3.12" "python3.11" "python3.10" "python3.9" "python3")
for py_cmd in "${python_candidates[@]}"; do
if command_exists "$py_cmd"; then
local py_version
py_version=$($py_cmd --version 2>&1 | grep -oP '\d+\.\d+')
# Python 3.8+ 支持
if [[ $(echo "$py_version >= 3.8" | bc -l 2>/dev/null || echo "1") -eq 1 ]]; then
PYTHON_CMD="$py_cmd"
log_success "检测到 Python: $py_cmd (版本 $py_version)"
return 0
fi
fi
done
log_error "未找到可用的 Python 3.8+ 版本"
exit 1
}
# 检查系统依赖
check_system_dependencies() {
log_info "检查系统依赖..."
# 检查必要的命令
if ! command_exists apt; then
log_error "此脚本仅支持基于 apt 的系统(Debian/Ubuntu"
exit 1
fi
# 检查是否有 root 权限
if [ "$EUID" -ne 0 ]; then
log_warning "建议使用 root 权限运行此脚本"
read -p "是否继续?(y/n) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
fi
log_success "系统依赖检查完成"
}
# 安装系统包
install_system_packages() {
log_info "开始安装系统包..."
# 更新包列表
echo ""
run_with_progress "📦 更新 APT 包列表" "apt update" "$LOG_FILE" || {
log_error "更新包列表失败"
exit 1
}
# 基础包列表(不包含 venv,按需安装)
local base_packages=(
"git"
"python3-pip"
)
# 安装基础包
echo ""
run_with_progress "📦 安装系统包 (${base_packages[*]})" "apt install -y ${base_packages[*]}" "$LOG_FILE"
check_result "基础系统包安装失败"
echo ""
log_success "系统包安装完成"
}
# 安装 venv 包(仅在需要时)
install_venv_package() {
log_info "检测到缺少 venv 模块,尝试安装..."
# 尝试安装 python3-venv
echo ""
if run_with_progress "📦 安装 python3-venv" "apt install -y python3-venv" "../$LOG_FILE"; then
echo ""
log_success "python3-venv 安装成功"
return 0
else
echo ""
log_error "python3-venv 安装失败,请手动安装"
return 1
fi
}
# 克隆代码仓库
clone_repository() {
log_info "克隆代码仓库..."
if [ -d "$PROJECT_DIR" ]; then
log_warning "目录 $PROJECT_DIR 已存在"
read -p "是否删除并重新克隆?(y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
rm -rf "$PROJECT_DIR"
log_info "已删除旧目录"
else
log_info "跳过克隆步骤"
return 0
fi
fi
echo ""
run_with_progress "📥 克隆 GitHub 仓库" "git clone --depth=1 $REPO_URL" "$LOG_FILE"
check_result "克隆仓库失败"
echo ""
log_success "代码仓库克隆完成"
}
# 创建和配置虚拟环境
setup_virtual_environment() {
log_info "设置 Python 虚拟环境..."
cd "$PROJECT_DIR" || {
log_error "无法进入目录 $PROJECT_DIR"
exit 1
}
# 检查 Python 命令
if [ -z "$PYTHON_CMD" ] || ! command_exists "$PYTHON_CMD"; then
log_error "Python 命令不可用: $PYTHON_CMD"
exit 1
fi
# 创建虚拟环境
if [ -d "$VENV_NAME" ]; then
log_warning "虚拟环境 $VENV_NAME 已存在,将重新创建"
rm -rf "$VENV_NAME"
fi
log_info "使用 $PYTHON_CMD 创建虚拟环境..."
# 尝试创建虚拟环境
echo ""
if run_with_progress "🐍 创建 Python 虚拟环境" "$PYTHON_CMD -m venv $VENV_NAME" "../$LOG_FILE"; then
echo ""
log_success "虚拟环境创建完成"
else
echo ""
log_warning "虚拟环境创建失败,可能缺少 venv 模块"
# 尝试安装 venv 包
install_venv_package || {
log_error "无法安装 venv 模块"
exit 1
}
# 再次尝试创建虚拟环境
log_info "重新尝试创建虚拟环境..."
echo ""
run_with_progress "🐍 创建 Python 虚拟环境" "$PYTHON_CMD -m venv $VENV_NAME" "../$LOG_FILE"
check_result "创建虚拟环境失败(已安装 venv 模块)"
echo ""
log_success "虚拟环境创建完成"
fi
}
# 安装 Python 依赖
install_python_dependencies() {
log_info "安装 Python 依赖包..."
# 激活虚拟环境
# shellcheck source=/dev/null
source "$VENV_NAME/bin/activate" || {
log_error "激活虚拟环境失败"
exit 1
}
# 升级 pip
echo ""
run_with_progress "📚 升级 pip" "pip install --upgrade pip" "../$LOG_FILE"
# 安装项目依赖
if [ ! -f "requirements.txt" ]; then
log_error "requirements.txt 文件不存在"
exit 1
fi
echo ""
run_with_progress "📚 安装项目依赖" "pip install -r requirements.txt" "../$LOG_FILE"
check_result "安装 Python 依赖失败"
# 安装 opencv-python
echo ""
run_with_progress "📚 安装 opencv-python" "pip install opencv-python" "../$LOG_FILE"
check_result "安装 opencv-python 失败"
echo ""
log_success "Python 依赖安装完成"
}
# 安装 Playwright 和浏览器
install_playwright() {
log_info "安装 Playwright 浏览器..."
# 确保虚拟环境已激活
if [ -z "${VIRTUAL_ENV:-}" ]; then
source "$VENV_NAME/bin/activate"
fi
# 安装浏览器依赖
echo ""
run_with_progress "🌐 安装 Playwright 系统依赖" "playwright install-deps" "../$LOG_FILE"
check_result "安装 Playwright 系统依赖失败"
# 安装 Chromium 浏览器
echo ""
run_with_progress "🌐 安装 Chromium 浏览器" "playwright install chromium" "../$LOG_FILE"
check_result "安装 Chromium 浏览器失败"
echo ""
log_success "Playwright 安装完成"
}
# 生成配置文件
generate_config() {
log_info "生成配置文件..."
# 确保虚拟环境已激活
if [ -z "${VIRTUAL_ENV:-}" ]; then
# shellcheck source=/dev/null
source "$VENV_NAME/bin/activate"
fi
if [ ! -f "make_config.py" ]; then
log_error "make_config.py 文件不存在"
exit 1
fi
echo ""
run_with_progress "⚙️ 生成配置文件" "python make_config.py" "../$LOG_FILE"
check_result "生成配置文件失败"
echo ""
log_success "配置文件生成完成"
}
# 显示安装后信息
show_post_install_info() {
echo ""
echo "============================================"
log_success "$SCRIPT_NAME 安装完成!"
echo "============================================"
echo ""
echo "项目目录: $(pwd)"
echo "虚拟环境: $VENV_NAME"
echo "日志文件: ../$LOG_FILE"
echo ""
echo "使用说明:"
echo "1. 进入项目目录: cd $PROJECT_DIR"
echo "2. 激活虚拟环境: source $VENV_NAME/bin/activate"
echo "3. 运行程序: python main.py"
echo ""
echo "============================================"
}
# ============================================
# 主函数
# ============================================
main() {
log_info "开始执行 $SCRIPT_NAME..."
log_info "日志文件: $LOG_FILE"
# 执行安装步骤
check_system_dependencies
detect_python_version
install_system_packages
clone_repository
setup_virtual_environment
install_python_dependencies
install_playwright
generate_config
show_post_install_info
log_success "所有安装步骤完成!"
}
# 执行主函数
main "$@"