#!/bin/bash # # CPCHECK 一键部署脚本 # 适用于 Ubuntu,需 root 权限运行 # 安装路径: /opt/cpcheck # 服务端口: 5230 # set -euo pipefail INSTALL_DIR="/opt/cpcheck" SERVICE_PORT=5230 PYTHON_MIN_VERSION="3.10" RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' log_info() { echo -e "${GREEN}[INFO]${NC} $*"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } log_error() { echo -e "${RED}[ERROR]${NC} $*"; } check_root() { if [[ $EUID -ne 0 ]]; then log_error "请使用 root 用户运行此脚本: sudo bash install.sh" exit 1 fi } check_ubuntu() { if [[ ! -f /etc/os-release ]]; then log_error "无法检测操作系统,本工具仅支持 Ubuntu" exit 1 fi source /etc/os-release if [[ "${ID}" != "ubuntu" ]]; then log_error "本工具仅支持 Ubuntu,当前系统: ${ID}" exit 1 fi log_info "检测到 Ubuntu ${VERSION_ID:-unknown}" } check_python() { if ! command -v python3 &>/dev/null; then log_info "安装 Python3..." apt-get update -qq apt-get install -y python3 python3-venv python3-pip fi PY_VERSION=$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")') log_info "Python 版本: ${PY_VERSION}" PY_MAJOR=$(echo "$PY_VERSION" | cut -d. -f1) PY_MINOR=$(echo "$PY_VERSION" | cut -d. -f2) REQ_MAJOR=$(echo "$PYTHON_MIN_VERSION" | cut -d. -f1) REQ_MINOR=$(echo "$PYTHON_MIN_VERSION" | cut -d. -f2) if [[ "$PY_MAJOR" -lt "$REQ_MAJOR" ]] || \ [[ "$PY_MAJOR" -eq "$REQ_MAJOR" && "$PY_MINOR" -lt "$REQ_MINOR" ]]; then log_error "需要 Python >= ${PYTHON_MIN_VERSION},当前: ${PY_VERSION}" exit 1 fi } install_system_deps() { log_info "安装系统依赖..." apt-get update -qq apt-get install -y iputils-ping curl git rsync } install_node_pm2() { if command -v pm2 &>/dev/null; then log_info "PM2 已安装: $(pm2 --version)" return fi if ! command -v node &>/dev/null; then log_info "安装 Node.js..." curl -fsSL https://deb.nodesource.com/setup_20.x | bash - apt-get install -y nodejs fi log_info "安装 PM2..." npm install -g pm2 } setup_app() { SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SOURCE_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" log_info "部署目录: ${INSTALL_DIR}" mkdir -p "${INSTALL_DIR}" mkdir -p "${INSTALL_DIR}/logs" log_info "复制应用文件..." rsync -a --delete \ --exclude 'venv' \ --exclude '__pycache__' \ --exclude '.git' \ --exclude 'logs' \ "${SOURCE_DIR}/" "${INSTALL_DIR}/" cd "${INSTALL_DIR}" if [[ ! -d "venv" ]]; then log_info "创建 Python 虚拟环境..." python3 -m venv venv fi log_info "安装 Python 依赖..." venv/bin/pip install --upgrade pip -q venv/bin/pip install -r requirements.txt -q log_info "Python 依赖安装完成" } setup_pm2() { cd "${INSTALL_DIR}" if pm2 describe cpcheck &>/dev/null; then log_info "重启 CPCHECK 服务..." pm2 restart ecosystem.config.js else log_info "启动 CPCHECK 服务..." pm2 start ecosystem.config.js fi pm2 save if ! pm2 startup systemd -u root --hp /root 2>/dev/null | grep -q "already"; then env PATH=$PATH:/usr/bin pm2 startup systemd -u root --hp /root 2>/dev/null || true fi log_info "PM2 服务配置完成" } setup_firewall() { if command -v ufw &>/dev/null && ufw status | grep -q "Status: active"; then log_info "配置 UFW 防火墙放行端口 ${SERVICE_PORT}..." ufw allow "${SERVICE_PORT}/tcp" || true fi } verify_service() { log_info "等待服务启动..." sleep 3 if curl -sf "http://127.0.0.1:${SERVICE_PORT}/api/health" >/dev/null; then log_info "服务健康检查通过" else log_warn "健康检查未通过,请检查日志: pm2 logs cpcheck" fi } print_summary() { echo "" echo "==========================================" echo -e " ${GREEN}CPCHECK 部署完成${NC}" echo "==========================================" echo "" echo " 访问地址: http://<服务器IP>:${SERVICE_PORT}" echo " 安装目录: ${INSTALL_DIR}" echo " 日志查看: pm2 logs cpcheck" echo " 重启服务: pm2 restart cpcheck" echo " 停止服务: pm2 stop cpcheck" echo "" } main() { echo "" echo "==========================================" echo " CPCHECK 一键部署脚本" echo "==========================================" echo "" check_root check_ubuntu install_system_deps check_python install_node_pm2 setup_app setup_pm2 setup_firewall verify_service print_summary } main "$@"