372 lines
12 KiB
PowerShell
372 lines
12 KiB
PowerShell
# MYP Backend - Windows PowerShell Server Start
|
|
# Startet den Backend-Server vollstaendig unabhaengig vom Frontend
|
|
|
|
param(
|
|
[switch]$Production,
|
|
[switch]$Development,
|
|
[switch]$Logs,
|
|
[switch]$Help
|
|
)
|
|
|
|
# Farben fuer PowerShell
|
|
$Red = "Red"
|
|
$Green = "Green"
|
|
$Yellow = "Yellow"
|
|
$Blue = "Cyan"
|
|
|
|
function Write-Log {
|
|
param([string]$Message, [string]$Color = "White")
|
|
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
|
Write-Host "[$timestamp] $Message" -ForegroundColor $Color
|
|
}
|
|
|
|
function Write-Success {
|
|
param([string]$Message)
|
|
Write-Log "SUCCESS: $Message" -Color $Green
|
|
}
|
|
|
|
function Write-Warning {
|
|
param([string]$Message)
|
|
Write-Log "WARNING: $Message" -Color $Yellow
|
|
}
|
|
|
|
function Write-Error {
|
|
param([string]$Message)
|
|
Write-Log "FEHLER: $Message" -Color $Red
|
|
}
|
|
|
|
# Banner
|
|
Write-Host "========================================" -ForegroundColor $Blue
|
|
Write-Host "MYP Backend - Standalone Server Start" -ForegroundColor $Blue
|
|
Write-Host "========================================" -ForegroundColor $Blue
|
|
|
|
if ($Help) {
|
|
Write-Host "Verwendung: .\start-backend-server.ps1 [OPTIONEN]"
|
|
Write-Host ""
|
|
Write-Host "OPTIONEN:"
|
|
Write-Host " -Production Produktionsmodus (Gunicorn)"
|
|
Write-Host " -Development Entwicklungsmodus (Flask Dev Server)"
|
|
Write-Host " -Logs Zeige Live-Logs"
|
|
Write-Host " -Help Zeige diese Hilfe"
|
|
Write-Host ""
|
|
Write-Host "BEISPIELE:"
|
|
Write-Host " .\start-backend-server.ps1 -Development"
|
|
Write-Host " .\start-backend-server.ps1 -Production"
|
|
Write-Host " .\start-backend-server.ps1 -Development -Logs"
|
|
exit 0
|
|
}
|
|
|
|
# Bestimme Ausfuehrungsmodus
|
|
$RunMode = "development"
|
|
if ($Production) {
|
|
$RunMode = "production"
|
|
Write-Log "Produktionsmodus aktiviert" -Color $Blue
|
|
} elseif ($Development) {
|
|
$RunMode = "development"
|
|
Write-Log "Entwicklungsmodus aktiviert" -Color $Blue
|
|
} else {
|
|
$RunMode = "development"
|
|
Write-Log "Standard-Entwicklungsmodus aktiviert" -Color $Blue
|
|
}
|
|
|
|
# Arbeitsverzeichnis pruefen
|
|
$CurrentDir = Get-Location
|
|
Write-Log "Arbeitsverzeichnis: $CurrentDir"
|
|
|
|
if (-not (Test-Path "app.py")) {
|
|
Write-Error "app.py nicht gefunden! Bitte im Backend-Verzeichnis ausfuehren."
|
|
exit 1
|
|
}
|
|
|
|
# Python-Installation pruefen
|
|
Write-Log "Pruefe Python-Installation..." -Color $Blue
|
|
|
|
try {
|
|
$PythonVersion = python --version 2>&1
|
|
Write-Log "Python-Version: $PythonVersion"
|
|
Write-Success "Python-Installation verifiziert"
|
|
} catch {
|
|
Write-Error "Python ist nicht installiert oder nicht im PATH!"
|
|
exit 1
|
|
}
|
|
|
|
# Verbesserte Funktion zum Parsen der Umgebungsvariablen
|
|
function Set-EnvironmentFromFile {
|
|
param([string]$FilePath)
|
|
|
|
if (-not (Test-Path $FilePath)) {
|
|
Write-Warning "$FilePath nicht gefunden"
|
|
return
|
|
}
|
|
|
|
Write-Log "Lade Backend-Umgebungsvariablen aus $FilePath..." -Color $Blue
|
|
|
|
try {
|
|
$EnvContent = Get-Content $FilePath -Raw
|
|
$Lines = $EnvContent -split "`r?`n"
|
|
|
|
foreach ($Line in $Lines) {
|
|
# Ueberspringe leere Zeilen und Kommentare
|
|
if ([string]::IsNullOrWhiteSpace($Line) -or $Line.TrimStart().StartsWith('#')) {
|
|
continue
|
|
}
|
|
|
|
# Finde den ersten = Zeichen
|
|
$EqualIndex = $Line.IndexOf('=')
|
|
if ($EqualIndex -le 0) {
|
|
continue
|
|
}
|
|
|
|
# Extrahiere Key und Value
|
|
$Key = $Line.Substring(0, $EqualIndex).Trim()
|
|
$Value = $Line.Substring($EqualIndex + 1).Trim()
|
|
|
|
# Entferne umgebende Anfuehrungszeichen, falls vorhanden
|
|
if (($Value.StartsWith('"') -and $Value.EndsWith('"')) -or
|
|
($Value.StartsWith("'") -and $Value.EndsWith("'"))) {
|
|
$Value = $Value.Substring(1, $Value.Length - 2)
|
|
}
|
|
|
|
# Setze Umgebungsvariable
|
|
if (-not [string]::IsNullOrWhiteSpace($Key)) {
|
|
[Environment]::SetEnvironmentVariable($Key, $Value, "Process")
|
|
Write-Log "Geladen: $Key" -Color $Blue
|
|
}
|
|
}
|
|
|
|
# Ueberschreibe FLASK_ENV mit dem gewaehlten Modus
|
|
[Environment]::SetEnvironmentVariable("FLASK_ENV", $RunMode, "Process")
|
|
Write-Success "Umgebungsvariablen erfolgreich geladen"
|
|
|
|
} catch {
|
|
Write-Error "Fehler beim Laden der Umgebungsvariablen: $_"
|
|
Write-Warning "Verwende Standard-Umgebungsvariablen"
|
|
}
|
|
}
|
|
|
|
# Umgebungsvariablen laden
|
|
Set-EnvironmentFromFile "env.backend"
|
|
|
|
# Notwendige Verzeichnisse erstellen
|
|
Write-Log "Pruefe Verzeichnisse..." -Color $Blue
|
|
|
|
$Directories = @("instance", "logs", "uploads")
|
|
foreach ($Dir in $Directories) {
|
|
if (-not (Test-Path $Dir)) {
|
|
New-Item -ItemType Directory -Path $Dir | Out-Null
|
|
Write-Log "Verzeichnis erstellt: $Dir"
|
|
}
|
|
}
|
|
|
|
# Dependencies pruefen
|
|
Write-Log "Pruefe Python-Dependencies..." -Color $Blue
|
|
|
|
if (Test-Path "requirements.txt") {
|
|
try {
|
|
pip install -r requirements.txt --quiet
|
|
Write-Success "Dependencies aktualisiert"
|
|
} catch {
|
|
Write-Warning "Fehler beim Aktualisieren der Dependencies: $_"
|
|
}
|
|
} else {
|
|
Write-Warning "requirements.txt nicht gefunden"
|
|
}
|
|
|
|
# Datenbank initialisieren
|
|
Write-Log "Initialisiere Datenbank..." -Color $Blue
|
|
|
|
try {
|
|
$env:FLASK_APP = "app.py"
|
|
|
|
# Erstelle temporaere Python-Datei fuer Datenbank-Initialisierung
|
|
$TempInitFile = "temp_init.py"
|
|
$InitCode = "from app import create_app, init_db`n"
|
|
$InitCode += "app = create_app('$RunMode')`n"
|
|
$InitCode += "with app.app_context():`n"
|
|
$InitCode += " init_db()`n"
|
|
$InitCode += " print('Datenbank initialisiert')"
|
|
|
|
$InitCode | Out-File -FilePath $TempInitFile -Encoding UTF8
|
|
python $TempInitFile
|
|
Remove-Item $TempInitFile -Force
|
|
|
|
Write-Success "Datenbank initialisiert"
|
|
} catch {
|
|
Write-Error "Fehler bei der Datenbank-Initialisierung: $_"
|
|
if (Test-Path $TempInitFile) {
|
|
Remove-Item $TempInitFile -Force
|
|
}
|
|
exit 1
|
|
}
|
|
|
|
# Port pruefen
|
|
$Port = 5000
|
|
if ($env:PORT) {
|
|
$Port = [int]$env:PORT
|
|
}
|
|
|
|
$PortInUse = Get-NetTCPConnection -LocalPort $Port -ErrorAction SilentlyContinue
|
|
if ($PortInUse) {
|
|
Write-Warning "Port $Port ist bereits belegt!"
|
|
$Port = 5001
|
|
Write-Log "Verwende alternativen Port $Port..."
|
|
}
|
|
|
|
# Server starten basierend auf Modus
|
|
if ($RunMode -eq "production") {
|
|
Write-Log "Starte Backend-Server im Produktionsmodus..." -Color $Blue
|
|
|
|
# Pruefe Gunicorn
|
|
try {
|
|
gunicorn --version | Out-Null
|
|
Write-Log "Verwende Gunicorn fuer Produktionsbetrieb"
|
|
} catch {
|
|
Write-Error "Gunicorn ist nicht installiert! Installiere mit: pip install gunicorn"
|
|
exit 1
|
|
}
|
|
|
|
# Gunicorn Konfiguration
|
|
$Workers = if ($env:WORKERS) { $env:WORKERS } else { 4 }
|
|
$BindAddress = if ($env:BIND_ADDRESS) { $env:BIND_ADDRESS } else { "0.0.0.0:$Port" }
|
|
$Timeout = if ($env:TIMEOUT) { $env:TIMEOUT } else { 30 }
|
|
|
|
Write-Log "Backend-Server startet auf $BindAddress mit $Workers Workern..."
|
|
|
|
# Starte Gunicorn
|
|
$GunicornCmd = "gunicorn --bind $BindAddress --workers $Workers --timeout $Timeout wsgi:application"
|
|
|
|
if ($Logs) {
|
|
Write-Log "Starte mit Live-Logs..." -Color $Blue
|
|
Invoke-Expression $GunicornCmd
|
|
} else {
|
|
Write-Log "Starte im Hintergrund..." -Color $Blue
|
|
Start-Process -FilePath "gunicorn" -ArgumentList "--bind", $BindAddress, "--workers", $Workers, "--timeout", $Timeout, "wsgi:application" -NoNewWindow
|
|
|
|
# Warte auf Server-Start
|
|
Write-Log "Warte auf Backend-Service..." -Color $Blue
|
|
$Counter = 0
|
|
$TimeoutSeconds = 60
|
|
|
|
do {
|
|
Start-Sleep -Seconds 1
|
|
$Counter++
|
|
|
|
try {
|
|
$Response = Invoke-WebRequest -Uri "http://localhost:$Port/monitoring/health/simple" -Method GET -TimeoutSec 5 -UseBasicParsing
|
|
if ($Response.StatusCode -eq 200) {
|
|
Write-Success "Backend-Server ist bereit!"
|
|
break
|
|
}
|
|
} catch {
|
|
# Ignoriere Fehler waehrend der Startphase
|
|
}
|
|
|
|
if ($Counter % 10 -eq 0) {
|
|
$StatusMessage = "Warte auf Backend-Service... ($Counter/$TimeoutSeconds Sekunden)"
|
|
Write-Log $StatusMessage
|
|
}
|
|
} while ($Counter -lt $TimeoutSeconds)
|
|
|
|
if ($Counter -eq $TimeoutSeconds) {
|
|
Write-Error "Backend-Service konnte nicht gestartet werden!"
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
} else {
|
|
Write-Log "Starte Backend-Server im Entwicklungsmodus..." -Color $Blue
|
|
|
|
# Flask-Entwicklungsserver
|
|
$env:FLASK_APP = "app.py"
|
|
$env:FLASK_ENV = "development"
|
|
$env:FLASK_DEBUG = "1"
|
|
|
|
Write-Log "Backend-Server startet auf Port $Port..."
|
|
|
|
if ($Logs) {
|
|
Write-Log "Starte mit Live-Logs..." -Color $Blue
|
|
python -m flask run --host=0.0.0.0 --port=$Port
|
|
} else {
|
|
Write-Log "Starte im Hintergrund..." -Color $Blue
|
|
$FlaskProcess = Start-Process -FilePath "python" -ArgumentList "-m", "flask", "run", "--host=0.0.0.0", "--port=$Port" -NoNewWindow -PassThru
|
|
|
|
# Warte auf Server-Start
|
|
Write-Log "Warte auf Backend-Service..." -Color $Blue
|
|
$Counter = 0
|
|
$TimeoutSeconds = 60
|
|
|
|
do {
|
|
Start-Sleep -Seconds 1
|
|
$Counter++
|
|
|
|
try {
|
|
$Response = Invoke-WebRequest -Uri "http://localhost:$Port/monitoring/health/simple" -Method GET -TimeoutSec 5 -UseBasicParsing
|
|
if ($Response.StatusCode -eq 200) {
|
|
Write-Success "Backend-Server ist bereit!"
|
|
break
|
|
}
|
|
} catch {
|
|
# Ignoriere Fehler waehrend der Startphase
|
|
}
|
|
|
|
if ($Counter % 10 -eq 0) {
|
|
$StatusMessage = "Warte auf Backend-Service... ($Counter/$TimeoutSeconds Sekunden)"
|
|
Write-Log $StatusMessage
|
|
}
|
|
} while ($Counter -lt $TimeoutSeconds)
|
|
|
|
if ($Counter -eq $TimeoutSeconds) {
|
|
Write-Error "Backend-Service konnte nicht gestartet werden!"
|
|
if ($FlaskProcess -and !$FlaskProcess.HasExited) {
|
|
$FlaskProcess.Kill()
|
|
}
|
|
exit 1
|
|
}
|
|
}
|
|
}
|
|
|
|
# URLs anzeigen
|
|
Write-Host ""
|
|
Write-Success "Backend-Server erfolgreich gestartet!"
|
|
Write-Host ""
|
|
Write-Host "Backend-API: http://localhost:$Port" -ForegroundColor $Green
|
|
Write-Host "Backend-Health: http://localhost:$Port/monitoring/health/simple" -ForegroundColor $Green
|
|
Write-Host "Backend-Test: http://localhost:$Port/api/test" -ForegroundColor $Green
|
|
Write-Host ""
|
|
|
|
if ($RunMode -eq "development") {
|
|
Write-Host "Entwicklungsmodus aktiv:" -ForegroundColor $Blue
|
|
Write-Host "- Debug-Modus ist aktiviert" -ForegroundColor $White
|
|
Write-Host "- Automatisches Neuladen bei Aenderungen" -ForegroundColor $White
|
|
Write-Host "- Detaillierte Fehlermeldungen" -ForegroundColor $White
|
|
} else {
|
|
Write-Host "Produktionsmodus aktiv:" -ForegroundColor $Blue
|
|
Write-Host "- Gunicorn mit $Workers Workern" -ForegroundColor $White
|
|
Write-Host "- Optimiert fuer Performance" -ForegroundColor $White
|
|
Write-Host "- Logging aktiviert" -ForegroundColor $White
|
|
}
|
|
|
|
Write-Host ""
|
|
|
|
# Logs anzeigen (optional)
|
|
if ($Logs -and $RunMode -eq "development") {
|
|
Write-Log "Zeige Backend-Logs (Strg+C zum Beenden):" -Color $Blue
|
|
if (Test-Path "logs\myp.log") {
|
|
Get-Content "logs\myp.log" -Wait
|
|
} else {
|
|
Write-Warning "Keine Log-Datei gefunden"
|
|
}
|
|
}
|
|
|
|
if (!$Logs) {
|
|
Write-Log "Verwende Strg+C um den Server zu stoppen" -Color $Blue
|
|
|
|
# Warte auf Benutzereingabe
|
|
try {
|
|
while ($true) {
|
|
Start-Sleep -Seconds 1
|
|
}
|
|
} catch {
|
|
Write-Log "Server wird beendet..." -Color $Yellow
|
|
}
|
|
} |