# 静默后台启动脚本(无弹窗,日志写文件) # 用于 Windows 任务计划程序开机自启 $ErrorActionPreference = "Continue" $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path $RepoRoot = Split-Path -Parent (Split-Path -Parent $ScriptDir) $Backend = Join-Path $RepoRoot "backend" $Frontend = Join-Path $RepoRoot "frontend" $RedisDir = Join-Path $Backend "redis" $RedisExe = Join-Path $RedisDir "redis-server.exe" $RedisCli = Join-Path $RedisDir "redis-cli.exe" $LogDir = Join-Path $RepoRoot "logs" $LogFile = Join-Path $LogDir "autostart_$(Get-Date -Format 'yyyyMMdd_HHmmss').log" if (-not (Test-Path $LogDir)) { New-Item -ItemType Directory -Path $LogDir -Force | Out-Null } function Write-Log($msg) { $ts = Get-Date -Format "yyyy-MM-dd HH:mm:ss" "$ts $msg" | Out-File -Append -FilePath $LogFile -Encoding UTF8 } Write-Log "========== AIAgent background start ==========" Write-Log "Repo: $RepoRoot" # ── 1) Redis ────────────────────────────────── $redisPort = 6379 $redisListening = netstat -ano | Select-String ":$redisPort\s+.*LISTENING" if ($redisListening) { Write-Log "Redis already listening on $redisPort" } else { if (-not (Test-Path $RedisExe)) { Write-Log "ERROR: Redis not found at $RedisExe" } else { Write-Log "Starting Redis on $redisPort ..." $redisProc = Start-Process -FilePath $RedisExe ` -ArgumentList "--port $redisPort" ` -WorkingDirectory $RedisDir ` -WindowStyle Hidden ` -PassThru Start-Sleep -Seconds 2 if (Test-Path $RedisCli) { & $RedisCli -p $redisPort ping 2>&1 | Out-File -Append $LogFile -Encoding UTF8 } Write-Log "Redis PID=$($redisProc.Id) started" } } # ── 2) Backend API ──────────────────────────── $apiPort = 8037 $apiListening = netstat -ano | Select-String ":$apiPort\s+.*LISTENING" if ($apiListening) { Write-Log "Backend API already listening on $apiPort" } else { Write-Log "Starting backend API on $apiPort ..." $apiLog = Join-Path $LogDir "api.log" Start-Process powershell ` -WindowStyle Hidden ` -ArgumentList @( "-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>&1 | Out-File -Append '$apiLog' -Encoding UTF8" ) Write-Log "Backend API starting (log: $apiLog)" } # ── 3) Celery Worker ────────────────────────── Write-Log "Starting Celery worker ..." $celeryLog = Join-Path $LogDir "celery.log" Start-Process powershell ` -WindowStyle Hidden ` -ArgumentList @( "-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 2>&1 | Out-File -Append '$celeryLog' -Encoding UTF8" ) Write-Log "Celery worker starting (log: $celeryLog)" # ── 3.5) Celery Beat (scheduler) ────────────── Write-Log "Starting Celery Beat ..." $beatLog = Join-Path $LogDir "celery_beat.log" Start-Process powershell ` -WindowStyle Hidden ` -ArgumentList @( "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", "Set-Location '$Backend'; .\venv\Scripts\Activate.ps1; python -m celery -A app.core.celery_app beat --loglevel=info 2>&1 | Out-File -Append '$beatLog' -Encoding UTF8" ) Write-Log "Celery Beat starting (log: $beatLog)" # ── 4) Frontend (pnpm dev) ──────────────────── $frontendPort = 3001 $frontendListening = netstat -ano | Select-String ":$frontendPort\s+.*LISTENING" if ($frontendListening) { Write-Log "Frontend already listening on $frontendPort" } else { Write-Log "Starting frontend on $frontendPort ..." $frontendLog = Join-Path $LogDir "frontend.log" Start-Process powershell ` -WindowStyle Hidden ` -ArgumentList @( "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", "`$env:AIAGENT_API_PROXY='http://127.0.0.1:$apiPort'; Set-Location '$Frontend'; pnpm dev --port $frontendPort 2>&1 | Out-File -Append '$frontendLog' -Encoding UTF8" ) Write-Log "Frontend starting (log: $frontendLog)" } Write-Log "========== All services issued ==========" Write-Log "Frontend: http://localhost:$frontendPort" Write-Log "API docs: http://127.0.0.1:$apiPort/docs"