后端版本服务器部署成功

This commit is contained in:
2025-09-11 15:05:23 +08:00
parent 9b7a0482e1
commit 068b7887a9
15 changed files with 575 additions and 410 deletions

View File

@@ -5,7 +5,7 @@ require('dotenv').config({ path: path.join(__dirname, '../../.env') })
const config = {
// 开发环境
development: {
port: process.env.PORT || 3200,
port: process.env.PORT || 3110,
mysql: {
host: process.env.DB_HOST || 'nj-cdb-3pwh2kz1.sql.tencentcdb.com',
port: process.env.DB_PORT || 20784,
@@ -38,7 +38,7 @@ const config = {
// 测试环境
test: {
port: process.env.PORT || 3200,
port: process.env.PORT || 3110,
mysql: {
host: process.env.DB_HOST || 'nj-cdb-3pwh2kz1.sql.tencentcdb.com',
port: process.env.DB_PORT || 20784,
@@ -62,7 +62,7 @@ const config = {
// 生产环境
production: {
port: process.env.PORT || 3200,
port: process.env.PORT || 3110,
mysql: {
host: process.env.DB_HOST || 'nj-cdb-3pwh2kz1.sql.tencentcdb.com',
port: process.env.DB_PORT || 20784,
@@ -88,7 +88,7 @@ const config = {
allowedTypes: ['image/jpeg', 'image/png', 'image/webp']
},
cors: {
origin: process.env.CORS_ORIGIN || 'https://your-domain.com',
origin: process.env.CORS_ORIGIN || 'https://www.jiebanke.com',
credentials: true
}
}

View File

@@ -9,16 +9,10 @@ const mysql = require('mysql2/promise');
const bcrypt = require('bcryptjs');
const config = require('../config/env');
// 数据库配置
const dbConfig = {
host: process.env.DB_HOST || 'mysql.jiebanke.com',
port: process.env.DB_PORT || 3306,
user: process.env.DB_USER || 'root',
password: process.env.DB_PASSWORD || '',
database: process.env.DB_NAME || 'jiebanke_dev',
charset: process.env.DB_CHARSET || 'utf8mb4',
timezone: process.env.DB_TIMEZONE || '+08:00'
};
// 引入database.js配置
const dbConfig = require('../src/config/database').pool.config;
// 数据库配置已从database.js导入
// 测试数据
const testData = {

View File

@@ -0,0 +1,37 @@
// 简化版服务器入口文件
require('dotenv').config();
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3202;
const HOST = process.env.HOST || '0.0.0.0';
// 健康检查路由
app.get('/health', (req, res) => {
res.json({
status: 'ok',
timestamp: new Date().toISOString(),
version: '1.0.0',
noDbMode: process.env.NO_DB_MODE === 'true'
});
});
// 根路由
app.get('/', (req, res) => {
res.send('简化版服务器运行中...');
});
// 启动服务器
console.log(`🔍 准备启动服务器在 http://${HOST}:${PORT}`);
const server = app.listen(PORT, HOST, () => {
console.log(`✅ 服务器启动成功!`);
console.log(`🚀 访问地址: http://${HOST}:${PORT}`);
console.log(`🔍 NODE_ENV: ${process.env.NODE_ENV}`);
console.log(`🔍 NO_DB_MODE: ${process.env.NO_DB_MODE}`);
});
// 错误处理
server.on('error', (error) => {
console.error('❌ 服务器启动错误:', error);
process.exit(1);
});

View File

@@ -8,17 +8,10 @@
const mysql = require('mysql2/promise');
const config = require('../config/env');
// 数据库配置 - 使用环境变量,优先使用开发环境配置
const dbConfig = {
host: process.env.DB_HOST || 'localhost',
port: process.env.DB_PORT || 3306,
user: process.env.DB_USER || 'root',
password: process.env.DB_PASSWORD || '',
database: process.env.DB_NAME || 'jiebanke_dev',
charset: process.env.DB_CHARSET || 'utf8mb4',
timezone: process.env.DB_TIMEZONE || '+08:00',
connectTimeout: 10000
};
// 引入database.js配置
const dbConfig = require('../src/config/database').pool.config;
// 数据库配置已从database.js导入
async function testDatabaseConnection() {
let connection;
@@ -80,9 +73,9 @@ async function testDatabaseConnection() {
// 检查连接池配置
console.log('🔍 检查连接池配置...');
console.log(`📈 连接池限制: ${config.mysql.connectionLimit || 10}`);
console.log(`🔤 字符集: ${config.mysql.charset}`);
console.log(`⏰ 时区: ${config.mysql.timezone}`);
console.log(`📈 连接池限制: ${dbConfig.connectionLimit || 10}`);
console.log(`🔤 字符集: ${dbConfig.charset}`);
console.log(`⏰ 时区: ${dbConfig.timezone}`);
console.log('\n🎉 数据库连接测试完成!');
console.log('✅ 所有配置检查通过');

View File

@@ -1,21 +1,17 @@
const mysql = require('mysql2/promise');
// 引入database.js配置
const dbConfig = require('../src/config/database').pool.config;
async function testDevConnection() {
console.log('🧪 测试开发环境数据库连接...');
const dbConfig = {
host: '192.168.0.240',
port: 3306,
user: 'root',
password: 'aiotAiot123!',
database: 'jiebandata',
connectTimeout: 10000
};
// 使用从database.js导入的配置
const config = dbConfig;
try {
console.log('🔗 尝试连接到开发服务器:', dbConfig.host + ':' + dbConfig.port);
console.log('🔗 尝试连接到开发服务器:', config.host + ':' + config.port);
const connection = await mysql.createConnection(dbConfig);
const connection = await mysql.createConnection(config);
console.log('✅ 开发环境连接成功!');
// 测试基本查询
@@ -24,10 +20,10 @@ async function testDevConnection() {
// 检查表结构
const [tables] = await connection.execute(`
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'jiebandata'
`);
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = ?
`, [config.database]);
console.log('📊 数据库中的表:', tables.map(t => t.TABLE_NAME).join(', ') || '暂无表');

View File

@@ -0,0 +1,89 @@
import mysql from 'mysql2/promise';
import 'dotenv/config';
// 引入database.js配置
import dbConfig from '../src/config/database';
// 尝试多种连接配置
async function testMySQLConnections() {
console.log('🔍 测试MySQL连接配置...\n');
// 使用database.js中的配置
const config1 = {
host: dbConfig.pool.config.host,
port: dbConfig.pool.config.port,
user: dbConfig.pool.config.user,
password: dbConfig.pool.config.password,
database: dbConfig.pool.config.database,
connectTimeout: 5000
};
// 配置2: 不指定数据库名称
const config2 = {
...config1,
database: undefined
};
const configurations = [
{ name: 'database.js配置', config: config1 },
{ name: 'database.js配置(无数据库)', config: config2 }
];
for (const { name, config } of configurations) {
console.log(`\n🎯 尝试连接: ${name}`);
console.log(`📌 配置:`, {
host: config.host,
port: config.port,
user: config.user,
database: config.database || '不指定'
});
try {
const connection = await mysql.createConnection(config);
console.log('✅ 连接成功!');
// 测试简单查询
const [rows] = await connection.execute('SELECT 1 as test');
console.log('✅ 查询测试通过:', rows);
// 如果指定了数据库,检查数据库是否存在
if (config.database) {
const [dbCheck] = await connection.execute(`SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = ?`, [config.database]);
if (dbCheck.length > 0) {
console.log('✅ 数据库存在');
} else {
console.warn('⚠️ 指定的数据库不存在');
}
}
await connection.end();
return { success: true, config };
} catch (error) {
console.error('❌ 连接失败:', error.message);
console.error('🔍 错误代码:', error.code);
if (error.code === 'ECONNREFUSED') {
console.error('💡 可能原因: MySQL服务器未启动或网络不可达');
} else if (error.code === 'ER_ACCESS_DENIED_ERROR') {
console.error('💡 可能原因: 用户名或密码错误');
} else if (error.code === 'ER_BAD_DB_ERROR') {
console.error('💡 可能原因: 数据库不存在');
}
}
}
console.log('\n❌ 所有连接配置都失败了');
console.log('💡 建议:');
console.log('1. 检查MySQL服务器是否已启动');
console.log('2. 确认用户名和密码正确');
console.log('3. 确认数据库已创建');
console.log('4. 检查网络连接');
return { success: false };
}
// 执行测试
testMySQLConnections().then(result => {
process.exit(result.success ? 0 : 1);
});

View File

@@ -1,21 +1,18 @@
const mysql = require('mysql2/promise');
// 引入database.js配置
const dbConfig = require('../src/config/database').pool.config;
async function testNetworkConnection() {
console.log('🌐 测试网络连接性...');
const dbConfig = {
host: '129.211.213.226',
port: 9527,
user: 'root',
password: 'Aiot123',
connectTimeout: 5000,
acquireTimeout: 5000
};
// 使用从database.js导入的配置
const config = dbConfig;
try {
console.log('🔗 尝试连接到:', dbConfig.host + ':' + dbConfig.port);
console.log('🔗 尝试连接到:', config.host + ':' + config.port);
const connection = await mysql.createConnection(dbConfig);
const connection = await mysql.createConnection(config);
console.log('✅ 网络连接成功!');
await connection.end();

View File

@@ -0,0 +1,34 @@
// 简单的服务器测试脚本
import express from 'express';
const app = express();
const PORT = 3201;
const HOST = '0.0.0.0';
// 基本路由
app.get('/', (req, res) => {
res.send('服务器测试成功!');
});
app.get('/health', (req, res) => {
res.json({
status: 'ok',
timestamp: new Date().toISOString(),
version: '1.0.0'
});
});
// 启动服务器
const server = app.listen(PORT, HOST, () => {
console.log(`✅ 测试服务器启动成功!`);
console.log(`🚀 访问地址: http://${HOST}:${PORT}`);
});
// 处理退出信号
process.on('SIGINT', () => {
console.log('🛑 收到退出信号,关闭测试服务器...');
server.close(() => {
console.log('✅ 测试服务器已关闭');
process.exit(0);
});
});

View File

@@ -12,13 +12,23 @@ console.log('🔧 初始化Express应用...');
const { globalErrorHandler, notFound } = require('./utils/errors');
// 路由导入
const authRoutes = require('./routes/auth');
const userRoutes = require('./routes/user');
const travelRoutes = require('./routes/travel');
const animalRoutes = require('./routes/animal');
const orderRoutes = require('./routes/order');
const adminRoutes = require('./routes/admin'); // 新增管理员路由
// 检查是否为无数据库模式
const NO_DB_MODE = process.env.NO_DB_MODE === 'true';
let authRoutes, userRoutes, travelRoutes, animalRoutes, orderRoutes, adminRoutes;
// 路由导入 - 根据是否为无数据库模式决定是否导入实际路由
if (NO_DB_MODE) {
console.log('⚠️ 无数据库模式:将使用模拟路由');
} else {
// 路由导入
authRoutes = require('./routes/auth');
userRoutes = require('./routes/user');
travelRoutes = require('./routes/travel');
animalRoutes = require('./routes/animal');
orderRoutes = require('./routes/order');
adminRoutes = require('./routes/admin'); // 新增管理员路由
}
const app = express();
@@ -88,7 +98,8 @@ app.get('/health', (req, res) => {
status: 'OK',
timestamp: new Date().toISOString(),
uptime: process.uptime(),
environment: process.env.NODE_ENV || 'development'
environment: process.env.NODE_ENV || 'development',
noDbMode: NO_DB_MODE
});
});
@@ -103,20 +114,85 @@ app.get('/system-stats', (req, res) => {
uptime: process.uptime(),
cpuCount: require('os').cpus().length,
platform: process.platform,
architecture: process.arch
architecture: process.arch,
noDbMode: NO_DB_MODE
};
res.status(200).json(stats);
});
// API路由
app.use('/api/v1/auth', authRoutes);
app.use('/api/v1/users', userRoutes);
app.use('/api/v1/travel', travelRoutes);
app.use('/api/v1/animals', animalRoutes);
app.use('/api/v1/orders', orderRoutes);
// 管理员路由
app.use('/api/v1/admin', adminRoutes);
// 无数据库模式下的模拟路由
if (NO_DB_MODE) {
// 认证路由
app.use('/api/v1/auth', (req, res) => {
if (req.method === 'POST' && req.path === '/login') {
// 模拟登录响应
res.status(200).json({
success: true,
message: '模拟登录成功',
data: {
token: 'mock-jwt-token',
user: {
id: 1,
username: 'mockuser',
email: 'mock@example.com',
role: 'user'
}
}
});
} else {
res.status(503).json({
success: false,
message: '当前为无数据库模式,该功能不可用'
});
}
});
// 其他路由的通用响应
app.use('/api/v1/users', (req, res) => {
res.status(503).json({
success: false,
message: '当前为无数据库模式,用户管理功能不可用'
});
});
app.use('/api/v1/travel', (req, res) => {
res.status(503).json({
success: false,
message: '当前为无数据库模式,旅行相关功能不可用'
});
});
app.use('/api/v1/animals', (req, res) => {
res.status(503).json({
success: false,
message: '当前为无数据库模式,动物相关功能不可用'
});
});
app.use('/api/v1/orders', (req, res) => {
res.status(503).json({
success: false,
message: '当前为无数据库模式,订单相关功能不可用'
});
});
app.use('/api/v1/admin', (req, res) => {
res.status(503).json({
success: false,
message: '当前为无数据库模式,管理员功能不可用'
});
});
} else {
// API路由
app.use('/api/v1/auth', authRoutes);
app.use('/api/v1/users', userRoutes);
app.use('/api/v1/travel', travelRoutes);
app.use('/api/v1/animals', animalRoutes);
app.use('/api/v1/orders', orderRoutes);
// 管理员路由
app.use('/api/v1/admin', adminRoutes);
}
// 404处理
app.use('*', notFound);

View File

@@ -1,16 +1,9 @@
const mysql = require('mysql2/promise');
const config = require('../../config/env');
// 数据库配置
// 数据库配置 - 使用env.js中的mysql配置
const dbConfig = {
host: process.env.DB_HOST || 'nj-cdb-3pwh2kz1.sql.tencentcdb.com',
port: process.env.DB_PORT || 20784,
user: process.env.DB_USER || 'jiebanke',
password: process.env.DB_PASSWORD || 'aiot741$12346',
database: process.env.DB_NAME || 'jbkdata',
connectionLimit: process.env.DB_CONNECTION_LIMIT || 10,
charset: process.env.DB_CHARSET || 'utf8mb4',
timezone: process.env.DB_TIMEZONE || '+08:00',
...config.mysql,
// 连接池配置
waitForConnections: true,
queueLimit: 0,
@@ -30,6 +23,22 @@ async function testConnection() {
return true;
} catch (error) {
console.error('❌ MySQL数据库连接失败:', error.message);
console.error('🔍 错误代码:', error.code);
console.error('📌 数据库配置:', {
host: dbConfig.host,
port: dbConfig.port,
database: dbConfig.database,
user: dbConfig.user
});
if (error.code === 'ECONNREFUSED') {
console.error('💡 可能原因: MySQL服务器未启动或网络不可达');
} else if (error.code === 'ER_ACCESS_DENIED_ERROR') {
console.error('💡 可能原因: 用户名或密码错误');
} else if (error.code === 'ER_BAD_DB_ERROR') {
console.error('💡 可能原因: 数据库不存在');
}
return false;
}
}

View File

@@ -1,8 +1,6 @@
require('dotenv').config()
const app = require('./app')
const { testConnection } = require('./config/database')
const redisConfig = require('./config/redis')
const rabbitMQConfig = require('./config/rabbitmq')
const { testConnection, pool } = require('./config/database')
const PORT = process.env.PORT || 3200
const HOST = process.env.HOST || '0.0.0.0'
@@ -20,8 +18,9 @@ console.log(`🔹 NODE_ENV: ${process.env.NODE_ENV || 'development'}`)
console.log(`🔹 PORT: ${PORT}`)
console.log(`🔹 HOST: ${HOST}`)
console.log(`🔹 DATABASE_URL: ${process.env.DATABASE_URL ? '已配置' : '未配置'}`)
console.log(`🔹 REDIS_URL: ${process.env.REDIS_URL ? '已配置' : '未配置'}`)
console.log(`🔹 RABBITMQ_URL: ${process.env.RABBITMQ_URL ? '已配置' : '未配置'}\n`)
console.log(`🔹 使用生产环境MySQL数据库: 是`)
console.log(`🔹 使用Redis缓存: 否`)
console.log(`🔹 使用RabbitMQ消息队列: 否\n`)
// 优雅关闭处理
process.on('uncaughtException', (err) => {
@@ -51,41 +50,20 @@ const startServer = async () => {
console.log('🔍 测试数据库连接...')
// 测试数据库连接
await testConnection()
const isConnected = await testConnection()
if (!isConnected) {
console.error('❌ 数据库连接测试失败,无法启动服务器')
process.exit(1)
}
console.log('✅ 数据库连接测试成功')
console.log('📌 数据库连接池配置:', {
host: process.env.DB_HOST,
port: process.env.DB_PORT,
database: process.env.DB_NAME,
user: process.env.DB_USER
host: pool.config.host,
port: pool.config.port,
database: pool.config.database,
user: pool.config.user
})
// 连接Redis可选
try {
console.log('\n🔍 初始化Redis连接...')
console.log(`📌 Redis配置: ${process.env.REDIS_URL || '使用默认配置'}`)
await redisConfig.connect()
console.log('✅ Redis连接成功')
const info = await redisConfig.getInfo()
console.log('📌 Redis服务器信息:', info.server)
console.log('📌 Redis内存信息:', info.memory)
} catch (error) {
console.warn('⚠️ Redis连接失败继续以无缓存模式运行')
console.warn(`🔹 错误详情: ${error.message}`)
}
// 连接RabbitMQ可选
try {
console.log('\n🔍 初始化RabbitMQ连接...')
console.log(`📌 RabbitMQ配置: ${process.env.RABBITMQ_URL || '使用默认配置'}`)
await rabbitMQConfig.connect()
console.log('✅ RabbitMQ连接成功')
const connInfo = rabbitMQConfig.getConnectionInfo()
console.log('📌 RabbitMQ连接信息:', connInfo)
} catch (error) {
console.warn('⚠️ RabbitMQ连接失败继续以无消息队列模式运行')
console.warn(`🔹 错误详情: ${error.message}`)
}
console.log('🔄 所有数据库连接已统一使用database.js配置')
// 启动HTTP服务器
console.log('\n🔍 启动HTTP服务器...')
@@ -96,8 +74,8 @@ const startServer = async () => {
console.log(`📊 环境: ${process.env.NODE_ENV || 'development'}`)
console.log(`⏰ 启动时间: ${new Date().toLocaleString()}`)
console.log('💾 数据库: MySQL')
console.log(`🔴 Redis: ${redisConfig.isConnected ? '已连接' : '未连接'}`)
console.log(`🐰 RabbitMQ: ${rabbitMQConfig.isConnected ? '已连接' : '未连接'}`)
console.log('🔴 Redis: 未使用')
console.log('🐰 RabbitMQ: 未使用')
console.log('========================================\n')
})
@@ -122,20 +100,6 @@ const startServer = async () => {
await new Promise((resolve) => server.close(resolve))
console.log('✅ HTTP服务器已关闭')
// 关闭Redis连接
if (redisConfig.isConnected()) {
console.log('🔐 关闭Redis连接...')
await redisConfig.disconnect()
console.log('✅ Redis连接已关闭')
}
// 关闭RabbitMQ连接
if (rabbitMQConfig.isConnected) {
console.log('🔐 关闭RabbitMQ连接...')
await rabbitMQConfig.close()
console.log('✅ RabbitMQ连接已关闭')
}
console.log('\n========================================')
console.log('👋 服务器已完全关闭')
console.log('========================================')

78
backend/start-production.sh Executable file
View File

@@ -0,0 +1,78 @@
#!/bin/bash
# 结伴客后端生产环境启动脚本
# 此脚本用于直接使用生产环境MySQL数据库不使用Redis和RabbitMQ
# 设置脚本执行时的选项:出错时退出,未定义变量时出错
set -euo pipefail
# 生产环境环境变量配置
export NODE_ENV="production"
export PORT="3200"
export HOST="0.0.0.0"
# MySQL数据库配置 - 生产环境
# 请根据实际情况修改以下配置
export DB_HOST="nj-cdb-3pwh2kz1.sql.tencentcdb.com"
export DB_PORT="20784"
export DB_NAME="jbkdata"
export DB_USER="jiebanke"
export DB_PASSWORD='aiot741$12346'
export DATABASE_URL="mysql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}"
# 禁用Redis缓存
export USE_REDIS="false"
export REDIS_URL=""
# 禁用RabbitMQ消息队列
export USE_RABBITMQ="false"
export RABBITMQ_URL=""
# 应用特定配置
export JWT_SECRET="your-production-jwt-secret"
export JWT_EXPIRES_IN="30d"
export CRYPTO_SECRET="your-production-crypto-secret"
# 上传文件配置
export UPLOAD_DIR="./uploads"
export MAX_FILE_SIZE="10485760" # 10MB
export ENABLE_SWAGGER="true" # 生产环境启用Swagger文档
export NO_DB_MODE="false" # 必须使用数据库
# 显示启动信息
echo "========================================"
echo "🚀 结伴客后端生产环境启动脚本"
echo "📅 时间: $(date)"
echo "========================================"
echo ""
echo "🔍 环境变量配置:"
echo "🔹 NODE_ENV: $NODE_ENV"
echo "🔹 PORT: $PORT"
echo "🔹 HOST: $HOST"
echo "🔹 DATABASE_URL: $(echo $DATABASE_URL | sed 's/:.*/:******@/')"
echo "🔹 USE_REDIS: $USE_REDIS"
echo "🔹 USE_RABBITMQ: $USE_RABBITMQ"
echo "🔹 NO_DB_MODE: $NO_DB_MODE"
echo "🔹 ENABLE_SWAGGER: $ENABLE_SWAGGER"
echo ""
# 检查是否已安装依赖
echo "🔍 检查依赖安装..."
if [ ! -d "node_modules" ]; then
echo "⚠️ 依赖未安装,开始安装..."
npm install --production
echo "✅ 依赖安装完成"
else
echo "✅ 依赖已安装"
fi
echo ""
# 启动服务器
echo "========================================"
echo "🚀 启动服务器..."
echo "========================================"
# 使用node直接启动服务器不使用PM2等进程管理器
node src/server.js

20
backend/start-without-db.sh Executable file
View File

@@ -0,0 +1,20 @@
#!/bin/bash
# 无数据库模式启动脚本
# 确保脚本可执行
echo "🔧 正在准备无数据库模式启动..."
# 设置NODE_ENV为development
export NODE_ENV=development
# 设置NO_DB_MODE为true
export NO_DB_MODE=true
# 启动服务器
echo "🚀 以无数据库模式启动服务器..."
echo "⚠️ 注意:在无数据库模式下,许多功能将不可用"
echo "📝 查看 /health 和 /system-stats 端点获取服务器状态"
echo "📚 Swagger文档可在 /api-docs 访问"
npm run dev

155
backend/start_backend_simple.sh Executable file
View File

@@ -0,0 +1,155 @@
#!/bin/bash
# 结伴客后端服务简化启动脚本
# 不依赖PM2直接使用Node.js运行
# 设置颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 配置参数
APP_DIR="$(pwd)"
NODE_ENV=${NODE_ENV:-"development"}
PORT=${PORT:-"3110"} # 使用3110端口
# 数据库配置 - 使用生产环境MySQL数据库
DB_HOST="nj-cdb-3pwh2kz1.sql.tencentcdb.com"
DB_PORT="20784"
DB_USER="jiebanke"
DB_PASSWORD='aiot741$12346'
DB_NAME="jbkdata"
DATABASE_URL="mysql://$DB_USER:$DB_PASSWORD@$DB_HOST:$DB_PORT/$DB_NAME"
# 其他配置
USE_REDIS="false"
USE_RABBITMQ="false"
ENABLE_SWAGGER="true"
# 检查Node.js环境
check_node() {
if ! command -v node &> /dev/null; then
echo -e "${RED}错误Node.js环境未安装${NC}"
exit 1
fi
echo -e "${GREEN}Node.js版本: $(node -v)${NC}"
}
# 检查npm环境
check_npm() {
if ! command -v npm &> /dev/null; then
echo -e "${RED}错误npm环境未安装${NC}"
exit 1
fi
echo -e "${GREEN}npm版本: $(npm -v)${NC}"
}
# 安装依赖
install_dependencies() {
echo -e "${BLUE}正在安装依赖...${NC}"
cd "$APP_DIR"
npm install
if [ $? -ne 0 ]; then
echo -e "${RED}依赖安装失败!${NC}"
exit 1
fi
echo -e "${GREEN}依赖安装完成!${NC}"
}
# 启动服务
start_service() {
echo -e "${BLUE}正在启动结伴客后端服务...${NC}"
cd "$APP_DIR"
# 设置环境变量
export NODE_ENV=$NODE_ENV
export PORT=$PORT
export DB_HOST=$DB_HOST
export DB_PORT=$DB_PORT
export DB_USER=$DB_USER
export DB_PASSWORD=$DB_PASSWORD
export DB_NAME=$DB_NAME
export DATABASE_URL=$DATABASE_URL
export USE_REDIS=$USE_REDIS
export USE_RABBITMQ=$USE_RABBITMQ
export ENABLE_SWAGGER=$ENABLE_SWAGGER
# 打印启动信息
echo -e "${BLUE}启动配置:${NC}"
echo -e "${BLUE} NODE_ENV: $NODE_ENV${NC}"
echo -e "${BLUE} PORT: $PORT${NC}"
echo -e "${BLUE} DB_HOST: $DB_HOST${NC}"
echo -e "${BLUE} DB_PORT: $DB_PORT${NC}"
echo -e "${BLUE} DB_NAME: $DB_NAME${NC}"
echo -e "${BLUE} USE_REDIS: $USE_REDIS${NC}"
echo -e "${BLUE} USE_RABBITMQ: $USE_RABBITMQ${NC}"
echo -e "${BLUE} ENABLE_SWAGGER: $ENABLE_SWAGGER${NC}"
# 使用node直接启动服务
node src/server.js
if [ $? -ne 0 ]; then
echo -e "${RED}服务启动失败!${NC}"
exit 1
fi
}
# 显示帮助信息
show_help() {
echo ""
echo "结伴客后端服务简化启动脚本"
echo ""
echo "用法: $0 [命令] [环境]"
echo ""
echo "命令选项:"
echo " start - 启动服务(默认)"
echo " install - 仅安装依赖"
echo " help - 显示此帮助信息"
echo ""
echo "环境选项:"
echo " development - 开发环境(默认)"
echo " production - 生产环境"
echo " test - 测试环境"
echo ""
}
# 主函数
handle_command() {
# 解析命令和环境参数
COMMAND="start"
if [ $# -ge 1 ]; then
case $1 in
start|install|help) COMMAND=$1 ;;
*) echo -e "${RED}未知命令:$1${NC}"; show_help; exit 1 ;;
esac
fi
if [ $# -ge 2 ]; then
case $2 in
development|production|test) NODE_ENV=$2 ;;
*) echo -e "${RED}未知环境:$2${NC}"; show_help; exit 1 ;;
esac
fi
# 执行相应的命令
case $COMMAND in
start)
check_node
check_npm
start_service
;;
install)
check_node
check_npm
install_dependencies
;;
help)
show_help
;;
esac
}
# 执行主函数
handle_command "$@"

View File

@@ -1,278 +0,0 @@
#!/bin/bash
# 结伴客后端服务启动脚本 - 在CentOS服务器上运行
# 使用PM2管理Node.js应用
# 设置颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 配置参数
APP_DIR="$(pwd)"
NODE_ENV=${NODE_ENV:-"production"}
PORT=${PORT:-"3200"}
# 检查Node.js环境
check_node() {
if ! command -v node &> /dev/null; then
echo -e "${RED}错误Node.js环境未安装${NC}"
echo -e "${YELLOW}请先安装Node.js: curl -sL https://rpm.nodesource.com/setup_16.x | sudo bash - && sudo yum install -y nodejs${NC}"
exit 1
fi
echo -e "${GREEN}Node.js版本: $(node -v)${NC}"
}
# 检查PM2是否安装
check_pm2() {
if ! command -v pm2 &> /dev/null; then
echo -e "${YELLOW}PM2未安装正在全局安装...${NC}"
npm install -g pm2
if [ $? -ne 0 ]; then
echo -e "${RED}PM2安装失败${NC}"
exit 1
fi
fi
echo -e "${GREEN}PM2版本: $(pm2 -v)${NC}"
}
# 检查环境变量文件
check_env() {
if [ ! -f "$APP_DIR/.env" ]; then
echo -e "${RED}错误:未找到.env文件${NC}"
echo -e "${YELLOW}请确保.env文件已正确配置包含必要的数据库连接信息和其他配置。${NC}"
exit 1
fi
echo -e "${GREEN}已找到.env文件${NC}"
}
# 检查ecosystem.config.js文件
check_ecosystem() {
if [ ! -f "$APP_DIR/ecosystem.config.js" ]; then
echo -e "${YELLOW}未找到ecosystem.config.js文件正在创建默认配置...${NC}"
cat > "$APP_DIR/ecosystem.config.js" << EOF
module.exports = {
apps: [{
name: 'jiebanke-backend',
script: './src/server.js',
instances: 'max',
exec_mode: 'cluster',
env: {
NODE_ENV: 'development',
PORT: $PORT,
WATCH: true
},
env_production: {
NODE_ENV: 'production',
PORT: $PORT,
WATCH: false
},
log_file: '$APP_DIR/logs/combined.log',
out_file: '$APP_DIR/logs/out.log',
error_file: '$APP_DIR/logs/error.log',
max_memory_restart: '1G',
kill_timeout: 3000,
wait_ready: true,
listen_timeout: 3000,
autorestart: true,
max_restarts: 10,
restart_delay: 4000,
ignore_watch: [
'node_modules',
'logs',
'.git',
'uploads'
]
}]
};
EOF
echo -e "${GREEN}ecosystem.config.js文件已创建${NC}"
fi
}
# 安装依赖
install_dependencies() {
echo -e "${BLUE}正在安装生产依赖...${NC}"
cd "$APP_DIR"
npm install --production
if [ $? -ne 0 ]; then
echo -e "${RED}依赖安装失败!${NC}"
exit 1
fi
echo -e "${GREEN}依赖安装完成!${NC}"
}
# 创建日志和上传目录
create_directories() {
echo -e "${BLUE}正在创建必要的目录...${NC}"
mkdir -p "$APP_DIR/logs" "$APP_DIR/uploads"
chmod 755 "$APP_DIR/logs" "$APP_DIR/uploads"
echo -e "${GREEN}目录创建完成!${NC}"
}
# 启动服务
start_service() {
echo -e "${BLUE}正在使用PM2启动结伴客后端服务...${NC}"
cd "$APP_DIR"
# 设置NODE_ENV环境变量
export NODE_ENV=$NODE_ENV
# 使用PM2启动应用
pm2 start ecosystem.config.js --env $NODE_ENV
if [ $? -ne 0 ]; then
echo -e "${RED}服务启动失败!${NC}"
exit 1
fi
echo -e "${GREEN}服务启动成功!${NC}"
echo -e "${BLUE}应用名称: jiebanke-backend${NC}"
echo -e "${BLUE}环境: $NODE_ENV${NC}"
echo -e "${BLUE}端口: $PORT${NC}"
echo -e "${YELLOW}提示:使用 pm2 logs jiebanke-backend 查看日志${NC}"
echo -e "${YELLOW}提示:使用 pm2 monit 监控应用状态${NC}"
}
# 设置PM2开机自启
setup_autostart() {
echo -e "${BLUE}正在配置PM2开机自启...${NC}"
pm2 startup
if [ $? -ne 0 ]; then
echo -e "${RED}PM2开机自启配置失败${NC}"
else
pm2 save
echo -e "${GREEN}PM2开机自启配置完成${NC}"
fi
}
# 显示帮助信息
show_help() {
echo ""
echo "结伴客后端服务管理脚本"
echo ""
echo "用法: $0 [命令] [环境]"
echo ""
echo "命令选项:"
echo " start - 启动服务(默认)"
echo " stop - 停止服务"
echo " restart - 重启服务"
echo " status - 查看服务状态"
echo " logs - 查看服务日志"
echo " install - 仅安装依赖"
echo " setup - 配置PM2开机自启"
echo " help - 显示此帮助信息"
echo ""
echo "环境选项:"
echo " production - 生产环境(默认)"
echo " development - 开发环境"
echo " test - 测试环境"
echo ""
echo "示例:"
echo " $0 start production # 在生产环境启动服务"
echo " $0 restart development # 在开发环境重启服务"
echo " $0 logs # 查看服务日志"
echo ""
}
# 停止服务
stop_service() {
echo -e "${BLUE}正在停止结伴客后端服务...${NC}"
pm2 stop jiebanke-backend
if [ $? -ne 0 ]; then
echo -e "${YELLOW}服务可能未在运行!${NC}"
else
echo -e "${GREEN}服务已停止!${NC}"
fi
}
# 重启服务
restart_service() {
echo -e "${BLUE}正在重启结伴客后端服务...${NC}"
export NODE_ENV=$NODE_ENV
pm2 restart ecosystem.config.js --env $NODE_ENV
if [ $? -ne 0 ]; then
echo -e "${RED}服务重启失败!${NC}"
exit 1
fi
echo -e "${GREEN}服务重启成功!${NC}"
}
# 查看服务状态
status_service() {
echo -e "${BLUE}正在查看结伴客后端服务状态...${NC}"
pm2 status jiebanke-backend
}
# 查看服务日志
logs_service() {
echo -e "${BLUE}正在查看结伴客后端服务日志...${NC}"
pm2 logs jiebanke-backend
}
# 主函数
handle_command() {
# 解析命令和环境参数
COMMAND="start"
if [ $# -ge 1 ]; then
case $1 in
start|stop|restart|status|logs|install|setup|help) COMMAND=$1 ;;
*) echo -e "${RED}未知命令:$1${NC}"; show_help; exit 1 ;;
esac
fi
if [ $# -ge 2 ]; then
case $2 in
production|development|test) NODE_ENV=$2 ;;
*) echo -e "${RED}未知环境:$2${NC}"; show_help; exit 1 ;;
esac
fi
# 执行相应的命令
case $COMMAND in
start)
check_node
check_pm2
check_env
check_ecosystem
install_dependencies
create_directories
start_service
;;
stop)
check_pm2
stop_service
;;
restart)
check_node
check_pm2
check_env
install_dependencies
restart_service
;;
status)
check_pm2
status_service
;;
logs)
check_pm2
logs_service
;;
install)
check_node
install_dependencies
;;
setup)
check_pm2
setup_autostart
;;
help)
show_help
;;
esac
}
# 执行主函数
handle_command "$@"

1
backend/start_server.sh Symbolic link
View File

@@ -0,0 +1 @@
start_server.sh