96 lines
3.5 KiB
PowerShell
96 lines
3.5 KiB
PowerShell
[CmdletBinding()]
|
||
param(
|
||
[switch]$Restart
|
||
)
|
||
|
||
$ErrorActionPreference = "Stop"
|
||
$ProjectRoot = $PSScriptRoot
|
||
$BackendDir = Join-Path $ProjectRoot "backend"
|
||
$EnvFile = Join-Path $ProjectRoot ".env"
|
||
|
||
function Get-MatchingProcesses {
|
||
param([string]$Pattern)
|
||
|
||
return @(Get-CimInstance Win32_Process | Where-Object {
|
||
$_.CommandLine -and $_.CommandLine -match $Pattern
|
||
})
|
||
}
|
||
|
||
function Stop-MatchingProcesses {
|
||
param([string]$Name, [string]$Pattern)
|
||
|
||
$processes = Get-MatchingProcesses -Pattern $Pattern
|
||
if (-not $processes) {
|
||
return
|
||
}
|
||
$hasStaleEnvironment = @($processes | Where-Object {
|
||
$_.CreationDate -lt $script:EnvLastWriteTime
|
||
}).Count -gt 0
|
||
if (-not $Restart -and -not $hasStaleEnvironment) {
|
||
Write-Host "[skip] $Name 已运行" -ForegroundColor Yellow
|
||
return
|
||
}
|
||
foreach ($process in $processes) {
|
||
Stop-Process -Id $process.ProcessId -Force -ErrorAction SilentlyContinue
|
||
}
|
||
$reason = if ($Restart) { "显式重启" } else { ".env 晚于进程启动时间" }
|
||
Write-Host "[restart] 已停止旧 $Name 进程($reason)" -ForegroundColor Yellow
|
||
}
|
||
|
||
function Start-PythonProcess {
|
||
param(
|
||
[string]$Name,
|
||
[string]$Pattern,
|
||
[string]$Command
|
||
)
|
||
|
||
if (Get-MatchingProcesses -Pattern $Pattern) {
|
||
return
|
||
}
|
||
$escapedDirectory = $BackendDir.Replace("'", "''")
|
||
$windowCommand = "Set-Location -LiteralPath '$escapedDirectory'; `$Host.UI.RawUI.WindowTitle = '$Name'; $Command"
|
||
Start-Process powershell.exe -ArgumentList @("-NoExit", "-Command", $windowCommand)
|
||
Write-Host "[start] $Name" -ForegroundColor Green
|
||
}
|
||
|
||
if (-not (Test-Path -LiteralPath $EnvFile)) {
|
||
throw "未找到 $EnvFile,请先复制 .env.example 并完成配置。"
|
||
}
|
||
if (-not (Get-Command python -ErrorAction SilentlyContinue)) {
|
||
throw "未找到 python,请先安装 Python 3.12 并加入 PATH。"
|
||
}
|
||
$script:EnvLastWriteTime = (Get-Item -LiteralPath $EnvFile).LastWriteTime
|
||
|
||
Push-Location $ProjectRoot
|
||
try {
|
||
python -c "from cryptography.fernet import Fernet; from dotenv import dotenv_values; key=dotenv_values('.env').get('AI_CREDENTIAL_ENCRYPTION_KEY',''); Fernet(key.encode()); print('[ok] AI credential encryption key is valid')"
|
||
if ($LASTEXITCODE -ne 0) {
|
||
throw ".env 中的 AI_CREDENTIAL_ENCRYPTION_KEY 缺失或不是有效 Fernet 密钥。"
|
||
}
|
||
|
||
Stop-MatchingProcesses -Name "Django API" -Pattern "manage\.py runserver 0\.0\.0\.0:8000"
|
||
Stop-MatchingProcesses -Name "Celery Worker" -Pattern "celery.*-A config\.celery worker"
|
||
Stop-MatchingProcesses -Name "Celery Beat" -Pattern "celery.*-A config\.celery beat"
|
||
|
||
Start-PythonProcess -Name "AI Ticket - Django API" `
|
||
-Pattern "manage\.py runserver 0\.0\.0\.0:8000" `
|
||
-Command "python manage.py runserver 0.0.0.0:8000"
|
||
Start-PythonProcess -Name "AI Ticket - Celery Worker" `
|
||
-Pattern "celery.*-A config\.celery worker" `
|
||
-Command "python -m celery -A config.celery worker -l info -P solo"
|
||
Start-PythonProcess -Name "AI Ticket - Celery Beat" `
|
||
-Pattern "celery.*-A config\.celery beat" `
|
||
-Command "python -m celery -A config.celery beat -l info"
|
||
|
||
Write-Host ""
|
||
Write-Host "Python 后端程序已启动:" -ForegroundColor Cyan
|
||
Write-Host " Django API http://localhost:8000/api/docs"
|
||
Write-Host " Celery Worker 已启动"
|
||
Write-Host " Celery Beat 已启动"
|
||
Write-Host ""
|
||
Write-Host "修改 .env 后可执行:.\start-backend.ps1 -Restart" -ForegroundColor Yellow
|
||
}
|
||
finally {
|
||
Pop-Location
|
||
}
|