#!/bin/bash # 即梦 Free API Node.js 启动脚本 # 使用方法: ./start-node.sh [dev|prod|stop|restart|status] set -e # 颜色输出 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # 日志函数 log_info() { echo -e "${BLUE}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } # 检查Node.js环境 check_node_env() { if ! command -v node &> /dev/null; then log_error "Node.js 未安装,请先安装 Node.js v20.x" exit 1 fi if ! command -v yarn &> /dev/null; then log_error "Yarn 未安装,请先安装 Yarn" exit 1 fi NODE_VERSION=$(node -v | cut -d'v' -f2 | cut -d'.' -f1) if [ "$NODE_VERSION" -lt 18 ]; then log_warning "建议使用 Node.js v20.x,当前版本: $(node -v)" fi log_success "Node.js 环境检查通过: $(node -v)" } # 检查PM2 check_pm2() { if ! command -v pm2 &> /dev/null; then log_info "PM2 未安装,正在安装..." npm install -g pm2 log_success "PM2 安装完成" else log_success "PM2 已安装: $(pm2 -v)" fi } # 构建项目 build_project() { log_info "构建项目..." yarn install yarn run build log_success "项目构建完成" } # 加载环境变量文件 load_env_file() { if [ -f ".env" ]; then log_info "加载 .env 文件..." export $(grep -v '^#' .env | xargs) log_success "环境变量已从 .env 文件加载" elif [ -f ".env.template" ]; then log_warning "发现 .env.template 文件,请复制为 .env 并配置实际值" log_info "命令: cp .env.template .env" fi } # 验证必要的环境变量 validate_env() { local missing_vars=() # 检查必须的环境变量 [ -z "$MONGODB_URL" ] && missing_vars+=("MONGODB_URL") [ -z "$TOS_ACCESS_KEY_ID" ] && missing_vars+=("TOS_ACCESS_KEY_ID") [ -z "$TOS_ACCESS_KEY_SECRET" ] && missing_vars+=("TOS_ACCESS_KEY_SECRET") [ -z "$TOS_BUCKET_NAME" ] && missing_vars+=("TOS_BUCKET_NAME") if [ ${#missing_vars[@]} -gt 0 ]; then log_error "缺少必要的环境变量:" for var in "${missing_vars[@]}"; do log_error " - $var" done log_info "请设置这些环境变量或创建 .env 文件" log_info "参考: .env.template" return 1 fi log_success "环境变量验证通过" return 0 } # 设置环境变量 (示例) setup_env() { local env_type=$1 log_info "设置环境变量..." # 先尝试加载 .env 文件 load_env_file # 基础环境变量 (如果未设置则使用默认值) export NODE_ENV=${NODE_ENV:-${env_type}} export SERVICE_ID=${SERVICE_ID:-"jimeng-api-${env_type}"} export SERVICE_NAME=${SERVICE_NAME:-"jimeng-free-api-${env_type}"} export HOST=${HOST:-"0.0.0.0"} export PORT=${PORT:-"3302"} export TOS_REGION=${TOS_REGION:-"cn-beijing"} export TOS_ENDPOINT=${TOS_ENDPOINT:-"tos-cn-beijing.volces.com"} export HEARTBEAT_ENABLED=${HEARTBEAT_ENABLED:-"true"} export HEARTBEAT_INTERVAL=${HEARTBEAT_INTERVAL:-"30"} # 验证必要的环境变量 if ! validate_env; then exit 1 fi log_success "环境变量设置完成" log_info "服务ID: $SERVICE_ID" log_info "MongoDB: ${MONGODB_URL%%\?*}" # 只显示主机部分,隐藏查询参数 log_info "TOS Region: $TOS_REGION" } # 直接启动 (开发模式) start_dev() { log_info "启动开发模式..." setup_env "development" if [ ! -d "dist" ]; then build_project fi node dist/index.js } # PM2启动 (生产模式) start_pm2() { local env_type=$1 log_info "使用PM2启动 (${env_type}模式)..." check_pm2 if [ ! -d "dist" ]; then build_project fi # 停止现有进程 pm2 delete jimeng-free-api 2>/dev/null || true # 启动新进程 if [ "$env_type" = "production" ]; then pm2 start ecosystem.config.json --env production else pm2 start ecosystem.config.json fi pm2 save log_success "PM2启动完成" } # 停止服务 stop_service() { log_info "停止服务..." # 停止PM2进程 if command -v pm2 &> /dev/null; then pm2 delete jimeng-free-api 2>/dev/null || true log_success "PM2进程已停止" fi # 停止Node.js进程 pkill -f "node dist/index.js" 2>/dev/null || true log_success "Node.js进程已停止" } # 重启服务 restart_service() { log_info "重启服务..." stop_service sleep 2 start_pm2 "production" } # 查看状态 check_status() { log_info "检查服务状态..." echo "=== PM2 进程状态 ===" if command -v pm2 &> /dev/null; then pm2 list else echo "PM2 未安装" fi echo echo "=== Node.js 进程状态 ===" ps aux | grep "node dist/index.js" | grep -v grep || echo "未找到 Node.js 进程" echo echo "=== 端口状态 ===" netstat -tlnp 2>/dev/null | grep :3302 || echo "端口 3302 未被占用" echo echo "=== 服务健康检查 ===" if curl -s http://localhost:3302/ping > /dev/null 2>&1; then log_success "API 服务正常运行" # 检查服务器信息 echo "=== 当前服务器信息 ===" curl -s http://localhost:3302/api/servers/current | jq '.data' 2>/dev/null || curl -s http://localhost:3302/api/servers/current else log_error "API 服务无法访问" fi } # 查看日志 view_logs() { log_info "查看日志..." if command -v pm2 &> /dev/null && pm2 list | grep -q jimeng-free-api; then pm2 logs jimeng-free-api --lines 50 else log_warning "PM2未运行,查看本地日志文件..." if [ -f "./logs/combined.log" ]; then tail -n 50 ./logs/combined.log else log_warning "未找到日志文件" fi fi } # 显示帮助 show_help() { echo "即梦 Free API Node.js 启动脚本" echo echo "使用方法:" echo " $0 " echo echo "命令:" echo " dev 直接启动开发模式 (Node.js)" echo " prod 使用PM2启动生产模式" echo " pm2 使用PM2启动开发模式" echo " stop 停止所有服务" echo " restart 重启PM2服务" echo " status 查看服务状态" echo " logs 查看服务日志" echo " build 仅构建项目" echo " help 显示此帮助信息" echo echo "多实例管理:" echo " ./multi-instance.sh start all production # 启动所有实例 (端口 3302, 3303, 3304)" echo " ./multi-instance.sh start 3302,3303 # 启动指定端口实例" echo " ./multi-instance.sh stop all # 停止所有实例" echo " ./multi-instance.sh status # 查看所有实例状态" echo " ./multi-instance.sh logs 3302 # 查看指定实例日志" echo echo "环境变量配置方式:" echo " 方式1: 使用 .env 文件 (推荐)" echo " cp .env.template .env" echo " # 编辑 .env 文件,填入实际配置" echo " $0 prod" echo echo " 方式2: 直接设置环境变量" echo " export MONGODB_URL='mongodb://localhost:27017/jimeng-api'" echo " export TOS_ACCESS_KEY_ID='your_key_id'" echo " # ... 其他变量" echo " $0 prod" echo echo " 方式3: PM2 ecosystem 配置" echo " # 编辑 ecosystem.config.json 中的 env 或 env_production 节点" echo " pm2 start ecosystem.config.json --env production" echo echo "必须设置的环境变量:" echo " MONGODB_URL MongoDB连接地址" echo " TOS_ACCESS_KEY_ID TOS访问密钥ID" echo " TOS_ACCESS_KEY_SECRET TOS访问密钥" echo " TOS_BUCKET_NAME TOS存储桶名称" echo echo "可选环境变量 (有默认值):" echo " NODE_ENV 运行环境 (development/production)" echo " SERVICE_ID 服务器唯一标识" echo " SERVICE_NAME 服务器名称" echo " HOST 绑定主机 (默认: 0.0.0.0)" echo " PORT 端口号 (默认: 3302)" echo " BASE_URL 服务器基础URL (自动检测)" echo " TOS_REGION TOS地区 (默认: cn-beijing)" echo " TOS_ENDPOINT TOS端点 (默认: tos-cn-beijing.volces.com)" echo " TOS_SELF_DOMAIN TOS自定义域名" echo " HEARTBEAT_ENABLED 启用心跳 (默认: true)" echo " HEARTBEAT_INTERVAL 心跳间隔秒数 (默认: 30)" echo echo "示例:" echo " # 快速开始 (使用 .env 文件)" echo " cp .env.template .env" echo " # 编辑 .env 文件后:" echo " $0 prod" echo echo " # 临时环境变量启动" echo " MONGODB_URL='mongodb://localhost:27017/jimeng-api' \\" echo " TOS_ACCESS_KEY_ID='your_key' \\" echo " TOS_ACCESS_KEY_SECRET='your_secret' \\" echo " TOS_BUCKET_NAME='your_bucket' \\" echo " $0 dev" } # 主函数 main() { local command="$1" case "$command" in dev) check_node_env start_dev ;; prod) check_node_env start_pm2 "production" ;; pm2) check_node_env start_pm2 "development" ;; stop) stop_service ;; restart) check_node_env restart_service ;; status) check_status ;; logs) view_logs ;; build) check_node_env build_project ;; help|--help|-h) show_help ;; "") log_error "请指定命令" show_help exit 1 ;; *) log_error "未知命令: $command" show_help exit 1 ;; esac } # 执行主函数 main "$@"