# Restart backend API (uvicorn) + Celery worker + Celery Beat (scheduler) # 同时确保 Redis 在运行(不会停止 Redis) # Does not stop frontend/Redis. $ErrorActionPreference = "Continue" # Repo root = two levels up from scripts/startup/ $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path $RepoRoot = Split-Path -Parent (Split-Path -Parent $ScriptDir) $Backend = Join-Path $RepoRoot "backend" $RedisExe = Join-Path $Backend "redis\redis-server.exe" $RedisPort = 6379 $ApiPort = 8037 Write-Host "== Stop API + Celery worker + Celery Beat ==" -ForegroundColor Cyan function Stop-ByCommandLine([string]$pattern, [string]$name) { $targets = Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -and $_.CommandLine -match $pattern } if (-not $targets) { Write-Host "[SKIP] ${name}: no matching process" -ForegroundColor DarkGray return } foreach ($p in $targets) { try { Stop-Process -Id $p.ProcessId -Force Write-Host "[OK] stopped ${name} PID=$($p.ProcessId)" -ForegroundColor Green } catch { Write-Host "[WARN] failed to stop ${name} PID=$($p.ProcessId)" -ForegroundColor Yellow } } } Stop-ByCommandLine "uvicorn\s+app\.main:app" "backend-api" Stop-ByCommandLine "celery\s+-A\s+app\.core\.celery_app\s+worker" "celery-worker" Stop-ByCommandLine "celery\s+-A\s+app\.core\.celery_app\s+beat" "celery-beat" Start-Sleep -Seconds 2 Write-Host "== Start API on $ApiPort + Celery worker + Celery Beat ==" -ForegroundColor Cyan # 1. API (uvicorn) Start-Process powershell -ArgumentList @( "-NoExit", "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", "Set-Location '$Backend'; .\venv\Scripts\Activate.ps1; python -m uvicorn app.main:app --host 0.0.0.0 --port $ApiPort" ) # 2. Celery worker Start-Process powershell -ArgumentList @( "-NoExit", "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", "Set-Location '$Backend'; .\venv\Scripts\Activate.ps1; python -m celery -A app.core.celery_app worker --loglevel=info --pool=threads --concurrency=8" ) # 3. Celery Beat (scheduler — 每分钟检查到期的定时任务) Start-Process powershell -ArgumentList @( "-NoExit", "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", "Set-Location '$Backend'; .\venv\Scripts\Activate.ps1; python -m celery -A app.core.celery_app beat --loglevel=info" ) Write-Host "" Write-Host "[DONE] 已在新窗口启动 API + Celery Worker + Celery Beat" -ForegroundColor Green Write-Host "API: http://127.0.0.1:$ApiPort/docs" -ForegroundColor Cyan Write-Host "Celery Beat 负责每分钟检查定时任务,如果定时推送没触发,请确认 Beat 窗口正在运行" -ForegroundColor Yellow # ── Redis 守护:确保 Redis 在运行(不会停止 Redis,只补启动)── Write-Host "" Write-Host "== Redis 守护检查 ==" -ForegroundColor Cyan $redisRunning = Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -and $_.CommandLine -match "redis-server" } if ($redisRunning) { Write-Host "[OK] Redis 已在运行" -ForegroundColor Green } else { Write-Host "[WARN] Redis 未运行,正在启动..." -ForegroundColor Yellow if (Test-Path $RedisExe) { Start-Process $RedisExe -ArgumentList "--port", $RedisPort -WindowStyle Hidden Start-Sleep -Seconds 1 $redisNow = Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -and $_.CommandLine -match "redis-server" } if ($redisNow) { Write-Host "[OK] Redis 已启动 (端口 $RedisPort)" -ForegroundColor Green } else { Write-Host "[FAIL] Redis 启动失败,请手动启动: $RedisExe --port $RedisPort" -ForegroundColor Red } } else { Write-Host "[FAIL] 未找到 redis-server.exe: $RedisExe" -ForegroundColor Red } } Start-Sleep -Seconds 2 Write-Host "" Write-Host "Port $ApiPort :" -ForegroundColor Cyan netstat -ano | findstr ":$ApiPort" Write-Host "Port $RedisPort :" -ForegroundColor Cyan netstat -ano | findstr ":$RedisPort"