# Node.js 服务管理脚本 - 宁夏智慧养殖监管平台后端 (Windows版本) # 使用方法: .\node_manager.ps1 [start|stop|restart|status] param( [Parameter(Mandatory=$false)] [ValidateSet('start','stop','restart','status','logs')] [string]$Action = 'status' ) # 配置区域 $APP_NAME = "nxxmdata-backend" $ENTRY_FILE = "server.js" $APP_PORT = 5350 $LOG_DIR = "logs" $LOG_FILE = Join-Path $LOG_DIR "$APP_NAME.log" $PID_FILE = "pid.$APP_NAME" $NODE_ENV = "production" # 创建日志目录 if (-not (Test-Path $LOG_DIR)) { New-Item -ItemType Directory -Path $LOG_DIR | Out-Null Write-Host "已创建日志目录: $LOG_DIR" -ForegroundColor Green } # 检查 Node.js 是否安装 try { $nodeVersion = node --version Write-Host "Node.js 版本: $nodeVersion" -ForegroundColor Green } catch { Write-Host "错误: Node.js 未安装或不在 PATH 中" -ForegroundColor Red exit 1 } # 检查入口文件是否存在 if (-not (Test-Path $ENTRY_FILE)) { Write-Host "错误: 入口文件 $ENTRY_FILE 不存在" -ForegroundColor Red exit 1 } # 停止服务函数 function Stop-App { Write-Host "正在停止服务: $APP_NAME" -ForegroundColor Yellow # 查找占用端口的进程 $processes = Get-NetTCPConnection -LocalPort $APP_PORT -ErrorAction SilentlyContinue | Select-Object -ExpandProperty OwningProcess -Unique if ($processes) { foreach ($pid in $processes) { try { $process = Get-Process -Id $pid -ErrorAction SilentlyContinue if ($process -and $process.ProcessName -eq "node") { Write-Host "找到进程 PID: $pid,正在停止..." -ForegroundColor Yellow Stop-Process -Id $pid -Force Write-Host "服务已停止 (PID: $pid)" -ForegroundColor Green } } catch { Write-Host "停止进程失败: $_" -ForegroundColor Red } } # 清理 PID 文件 if (Test-Path $PID_FILE) { Remove-Item $PID_FILE -Force } } else { Write-Host "未找到运行中的服务 (端口 $APP_PORT 未被占用)" -ForegroundColor Yellow } } # 启动服务函数 function Start-App { Write-Host "正在启动服务: $APP_NAME" -ForegroundColor Yellow # 检查端口是否被占用 $portCheck = Get-NetTCPConnection -LocalPort $APP_PORT -ErrorAction SilentlyContinue if ($portCheck) { $pid = $portCheck | Select-Object -First 1 -ExpandProperty OwningProcess Write-Host "错误: 端口 $APP_PORT 已被占用 (PID: $pid)" -ForegroundColor Red Write-Host "请先停止占用端口的进程或使用 restart 命令" -ForegroundColor Yellow return } # 检查 .env 文件是否存在 if (-not (Test-Path ".env")) { Write-Host "警告: .env 文件不存在,将使用默认配置" -ForegroundColor Yellow Write-Host "建议从 env.example 复制并配置 .env 文件" -ForegroundColor Yellow } # 检查 node_modules 是否存在 if (-not (Test-Path "node_modules")) { Write-Host "错误: node_modules 目录不存在" -ForegroundColor Red Write-Host "请先运行: npm install" -ForegroundColor Yellow return } # 启动 Node.js 应用 Write-Host "启动命令: node $ENTRY_FILE" -ForegroundColor Cyan # 设置环境变量并启动 $env:NODE_ENV = $NODE_ENV # 使用 Start-Process 启动后台进程 $processInfo = Start-Process -FilePath "node" ` -ArgumentList $ENTRY_FILE ` -RedirectStandardOutput $LOG_FILE ` -RedirectStandardError $LOG_FILE ` -WindowStyle Hidden ` -PassThru if ($processInfo) { $PID = $processInfo.Id $PID | Out-File -FilePath $PID_FILE -Encoding ASCII Write-Host "等待服务启动..." -ForegroundColor Yellow Start-Sleep -Seconds 3 # 验证启动是否成功 if (Get-Process -Id $PID -ErrorAction SilentlyContinue) { Write-Host "========================================" -ForegroundColor Green Write-Host "服务启动成功!" -ForegroundColor Green Write-Host "========================================" -ForegroundColor Green Write-Host "应用名称: $APP_NAME" Write-Host "进程 ID: $PID" Write-Host "监听端口: $APP_PORT" Write-Host "日志文件: $LOG_FILE" Write-Host "PID 文件: $PID_FILE" Write-Host "环境变量: NODE_ENV=$NODE_ENV" Write-Host "API 文档: http://localhost:${APP_PORT}/api-docs" -ForegroundColor Cyan # 检查端口监听状态 Start-Sleep -Seconds 2 $portCheck = Get-NetTCPConnection -LocalPort $APP_PORT -ErrorAction SilentlyContinue if ($portCheck) { Write-Host "✓ 端口 $APP_PORT 正在监听" -ForegroundColor Green } else { Write-Host "⚠ 端口 $APP_PORT 尚未监听,请检查日志" -ForegroundColor Yellow } # 显示最近的日志 Write-Host "" Write-Host "最近的启动日志:" -ForegroundColor Yellow Write-Host "------------------------" if (Test-Path $LOG_FILE) { Get-Content $LOG_FILE -Tail 20 -ErrorAction SilentlyContinue } } else { Write-Host "========================================" -ForegroundColor Red Write-Host "服务启动失败!" -ForegroundColor Red Write-Host "========================================" -ForegroundColor Red Write-Host "请检查日志文件: $LOG_FILE" -ForegroundColor Yellow if (Test-Path $LOG_FILE) { Write-Host "" Write-Host "最近的错误日志:" -ForegroundColor Yellow Write-Host "------------------------" Get-Content $LOG_FILE -Tail 30 -ErrorAction SilentlyContinue } if (Test-Path $PID_FILE) { Remove-Item $PID_FILE -Force } exit 1 } } else { Write-Host "启动进程失败!" -ForegroundColor Red exit 1 } } # 重启服务函数 function Restart-App { Write-Host "正在重启服务: $APP_NAME" -ForegroundColor Yellow Stop-App Start-Sleep -Seconds 2 Start-App } # 状态检查函数 function Get-AppStatus { Write-Host "检查服务状态: $APP_NAME" -ForegroundColor Yellow Write-Host "========================================" # 检查端口占用 $portCheck = Get-NetTCPConnection -LocalPort $APP_PORT -ErrorAction SilentlyContinue if ($portCheck) { $pid = $portCheck | Select-Object -First 1 -ExpandProperty OwningProcess $process = Get-Process -Id $pid -ErrorAction SilentlyContinue if ($process -and $process.ProcessName -eq "node") { Write-Host "✓ 服务正在运行" -ForegroundColor Green Write-Host "----------------------------------------" Write-Host "进程 ID: $pid" Write-Host "进程名称: $($process.ProcessName)" Write-Host "应用名称: $APP_NAME" Write-Host "监听端口: $APP_PORT" Write-Host "启动时间: $($process.StartTime)" # 内存使用 (转换为 MB) $memoryMB = [math]::Round($process.WorkingSet64 / 1MB, 2) Write-Host "内存使用: $memoryMB MB" # CPU时间 Write-Host "CPU 时间: $($process.CPU) 秒" # 端口状态 Write-Host "端口状态: 监听中 ($APP_PORT)" -ForegroundColor Green # 日志文件信息 if (Test-Path $LOG_FILE) { $logSize = [math]::Round((Get-Item $LOG_FILE).Length / 1KB, 2) Write-Host "日志大小: $logSize KB" Write-Host "日志文件: $LOG_FILE" } Write-Host "" Write-Host "最近的日志 (最后10行):" -ForegroundColor Yellow Write-Host "----------------------------------------" if (Test-Path $LOG_FILE) { Get-Content $LOG_FILE -Tail 10 -ErrorAction SilentlyContinue } else { Write-Host "无法读取日志文件" } } else { Write-Host "⚠ 端口 $APP_PORT 被其他进程占用 (PID: $pid)" -ForegroundColor Yellow Write-Host "进程名称: $($process.ProcessName)" } } else { Write-Host "✗ 服务未运行" -ForegroundColor Red Write-Host "使用以下命令启动: .\node_manager.ps1 start" } Write-Host "========================================" } # 查看日志函数 function View-Logs { if (Test-Path $LOG_FILE) { Write-Host "实时查看日志 (Ctrl+C 退出):" -ForegroundColor Yellow Get-Content $LOG_FILE -Wait -Tail 20 } else { Write-Host "日志文件不存在: $LOG_FILE" -ForegroundColor Red } } # 主逻辑 switch ($Action.ToLower()) { 'start' { Start-App } 'stop' { Stop-App } 'restart' { Restart-App } 'status' { Get-AppStatus } 'logs' { View-Logs } default { Write-Host "========================================" Write-Host "宁夏智慧养殖监管平台 - 服务管理脚本 (Windows)" Write-Host "========================================" Write-Host "使用方法: .\node_manager.ps1 [start|stop|restart|status|logs]" Write-Host "" Write-Host "命令说明:" Write-Host " start - 启动服务" Write-Host " stop - 停止服务" Write-Host " restart - 重启服务" Write-Host " status - 查看服务状态" Write-Host " logs - 实时查看日志" Write-Host "" Write-Host "配置信息:" Write-Host " 应用名称: $APP_NAME" Write-Host " 入口文件: $ENTRY_FILE" Write-Host " 监听端口: $APP_PORT" Write-Host " 日志文件: $LOG_FILE" Write-Host "" Write-Host "示例:" Write-Host " .\node_manager.ps1 start # 启动服务" Write-Host " .\node_manager.ps1 status # 查看状态" Write-Host " .\node_manager.ps1 logs # 查看日志" } }