**Änderungen:** - ✅ Hinzugefügt: Neue Funktionalität zur Verwaltung von Benutzeranfragen, um die Benutzerfreundlichkeit zu erhöhen. - ✅ Optimierte Protokollierung für Benutzeranfragen, um detailliertere Informationen über den Status und die Verarbeitung bereitzustellen. **Ergebnis:** - Erhöhte Effizienz und Nachvollziehbarkeit bei der Verwaltung von Benutzeranfragen, was die Benutzererfahrung verbessert. 🤖 Generated with [Claude Code](https://claude.ai/code)
571 lines
16 KiB
Bash
571 lines
16 KiB
Bash
#!/bin/bash
|
|
|
|
#######################################################################
|
|
# MYP AIO-Installer - Python & Node.js Module
|
|
#
|
|
# Dieses Modul behandelt die Installation von:
|
|
# - Python und pip mit --break-system-packages
|
|
# - Node.js und npm
|
|
# - Python-Abhängigkeiten aus requirements.txt
|
|
# - Node.js-Abhängigkeiten aus package.json
|
|
# - Build-Prozess für Frontend-Assets
|
|
#######################################################################
|
|
|
|
# Funktionsdeklarationen für Python & Node.js Setup
|
|
|
|
install_python_dependencies() {
|
|
log "INFO" "=== PYTHON-ABHÄNGIGKEITEN INSTALLIEREN ==="
|
|
|
|
# Python-Version überprüfen
|
|
verify_python_installation
|
|
|
|
# pip konfigurieren
|
|
configure_pip
|
|
|
|
# Virtuelle Umgebung erstellen (optional)
|
|
# create_python_venv
|
|
|
|
# Requirements installieren
|
|
install_python_requirements
|
|
|
|
# Python-Installation verifizieren
|
|
verify_python_dependencies
|
|
|
|
log "INFO" "Python-Abhängigkeiten Installation abgeschlossen"
|
|
}
|
|
|
|
install_node_dependencies() {
|
|
log "INFO" "=== NODE.JS-ABHÄNGIGKEITEN INSTALLIEREN ==="
|
|
|
|
# Node.js installieren
|
|
install_nodejs
|
|
|
|
# npm konfigurieren
|
|
configure_npm
|
|
|
|
# Package-Dependencies installieren
|
|
install_npm_packages
|
|
|
|
# Build-Prozess durchführen
|
|
build_frontend_assets
|
|
|
|
# Node.js-Installation verifizieren
|
|
verify_node_dependencies
|
|
|
|
log "INFO" "Node.js-Abhängigkeiten Installation abgeschlossen"
|
|
}
|
|
|
|
verify_python_installation() {
|
|
log "INFO" "Überprüfe Python-Installation..."
|
|
|
|
# Python3 Version prüfen
|
|
if ! command -v python3 >/dev/null 2>&1; then
|
|
log "ERROR" "Python3 ist nicht installiert"
|
|
return 1
|
|
fi
|
|
|
|
local python_version=$(python3 --version | cut -d' ' -f2)
|
|
log "INFO" "Python-Version: $python_version"
|
|
|
|
# Mindestversion prüfen (Python 3.8+)
|
|
if ! python3 -c "import sys; sys.exit(0 if sys.version_info >= (3, 8) else 1)"; then
|
|
log "ERROR" "Python-Version zu alt (mindestens 3.8 erforderlich)"
|
|
return 1
|
|
fi
|
|
|
|
# pip überprüfen
|
|
if ! command -v pip3 >/dev/null 2>&1; then
|
|
log "INFO" "pip3 nicht gefunden, installiere pip..."
|
|
apt-get install -y python3-pip
|
|
fi
|
|
|
|
local pip_version=$(pip3 --version | cut -d' ' -f2)
|
|
log "INFO" "pip-Version: $pip_version"
|
|
|
|
log "INFO" "Python-Installation verifiziert"
|
|
}
|
|
|
|
configure_pip() {
|
|
log "INFO" "Konfiguriere pip..."
|
|
|
|
# pip Konfigurationsverzeichnis erstellen
|
|
mkdir -p "/home/$PROJECT_USER/.config/pip"
|
|
mkdir -p "/root/.config/pip"
|
|
|
|
# pip.conf für bessere Performance und Sicherheit
|
|
cat > "/home/$PROJECT_USER/.config/pip/pip.conf" << 'EOF'
|
|
[global]
|
|
timeout = 60
|
|
retries = 5
|
|
trusted-host = pypi.org
|
|
pypi.python.org
|
|
files.pythonhosted.org
|
|
|
|
[install]
|
|
upgrade-strategy = only-if-needed
|
|
break-system-packages = true
|
|
EOF
|
|
|
|
# Kopiere für root
|
|
cp "/home/$PROJECT_USER/.config/pip/pip.conf" "/root/.config/pip/pip.conf"
|
|
|
|
# Berechtigungen setzen
|
|
chown -R "$PROJECT_USER:$PROJECT_GROUP" "/home/$PROJECT_USER/.config"
|
|
|
|
# pip auf neueste Version aktualisieren
|
|
log "INFO" "Aktualisiere pip auf neueste Version..."
|
|
pip3 install --upgrade pip --break-system-packages || {
|
|
log "WARN" "pip-Update hatte Probleme"
|
|
}
|
|
|
|
log "INFO" "pip konfiguriert"
|
|
}
|
|
|
|
create_python_venv() {
|
|
log "INFO" "Erstelle Python Virtual Environment..."
|
|
|
|
local venv_path="$INSTALL_PATH/venv"
|
|
|
|
# Virtual Environment erstellen
|
|
python3 -m venv "$venv_path" || {
|
|
log "ERROR" "Virtual Environment konnte nicht erstellt werden"
|
|
return 1
|
|
}
|
|
|
|
# Aktivierungsscript für systemd erstellen
|
|
cat > "$INSTALL_PATH/activate_venv.sh" << EOF
|
|
#!/bin/bash
|
|
source "$venv_path/bin/activate"
|
|
exec "\$@"
|
|
EOF
|
|
chmod +x "$INSTALL_PATH/activate_venv.sh"
|
|
|
|
# Virtual Environment in systemd-Service nutzen
|
|
export PYTHON_VENV_PATH="$venv_path"
|
|
|
|
log "INFO" "Python Virtual Environment erstellt: $venv_path"
|
|
}
|
|
|
|
install_python_requirements() {
|
|
log "INFO" "Installiere Python-Requirements..."
|
|
|
|
# Requirements-Datei prüfen
|
|
local requirements_file="$INSTALL_PATH/requirements.txt"
|
|
if [[ ! -f "$requirements_file" ]]; then
|
|
log "ERROR" "Requirements-Datei nicht gefunden: $requirements_file"
|
|
return 1
|
|
fi
|
|
|
|
log "INFO" "Gefundene Requirements-Datei: $requirements_file"
|
|
|
|
# Anzahl der Requirements anzeigen
|
|
local req_count=$(grep -v '^#' "$requirements_file" | grep -v '^$' | wc -l)
|
|
log "INFO" "Installiere $req_count Python-Packages..."
|
|
|
|
# Installation mit --break-system-packages
|
|
log "INFO" "Führe pip install mit --break-system-packages aus..."
|
|
|
|
# Erstelle temporäres Install-Script für bessere Kontrolle
|
|
cat > "/tmp/pip_install.sh" << EOF
|
|
#!/bin/bash
|
|
set -e
|
|
cd "$INSTALL_PATH"
|
|
|
|
# Upgrade pip falls nötig
|
|
pip3 install --upgrade pip --break-system-packages
|
|
|
|
# Installiere Requirements
|
|
pip3 install -r requirements.txt --break-system-packages --no-cache-dir
|
|
|
|
# Erstelle Freeze-Liste für Debugging
|
|
pip3 freeze --break-system-packages > installed_packages.txt
|
|
EOF
|
|
|
|
chmod +x "/tmp/pip_install.sh"
|
|
|
|
# Installation ausführen
|
|
if /tmp/pip_install.sh; then
|
|
log "INFO" "Python-Requirements erfolgreich installiert"
|
|
else
|
|
log "ERROR" "Python-Requirements Installation fehlgeschlagen"
|
|
|
|
# Versuche einzelne Installation bei Fehlern
|
|
log "INFO" "Versuche einzelne Package-Installation..."
|
|
install_requirements_individually "$requirements_file"
|
|
fi
|
|
|
|
# Cleanup
|
|
rm -f "/tmp/pip_install.sh"
|
|
|
|
log "INFO" "Python-Requirements Installation abgeschlossen"
|
|
}
|
|
|
|
install_requirements_individually() {
|
|
local requirements_file="$1"
|
|
|
|
log "INFO" "Installiere Requirements einzeln..."
|
|
|
|
# Lese Requirements und installiere einzeln
|
|
while IFS= read -r line; do
|
|
# Überspringe Kommentare und leere Zeilen
|
|
[[ "$line" =~ ^#.*$ ]] && continue
|
|
[[ -z "$line" ]] && continue
|
|
|
|
# Package-Name extrahieren
|
|
local package=$(echo "$line" | cut -d'=' -f1 | cut -d'>' -f1 | cut -d'<' -f1 | tr -d ' ')
|
|
|
|
if [[ -n "$package" ]]; then
|
|
log "INFO" "Installiere: $package"
|
|
|
|
if pip3 install "$line" --break-system-packages --no-cache-dir; then
|
|
log "INFO" "✓ $package installiert"
|
|
else
|
|
log "WARN" "✗ $package Installation fehlgeschlagen"
|
|
fi
|
|
fi
|
|
done < "$requirements_file"
|
|
}
|
|
|
|
install_nodejs() {
|
|
log "INFO" "Installiere Node.js..."
|
|
|
|
# Prüfe ob Node.js bereits installiert ist
|
|
if command -v node >/dev/null 2>&1; then
|
|
local current_version=$(node --version)
|
|
log "INFO" "Node.js bereits installiert: $current_version"
|
|
|
|
# Prüfe Version (mindestens v16)
|
|
if node -e "process.exit(parseInt(process.version.slice(1)) >= 16 ? 0 : 1)"; then
|
|
log "INFO" "Node.js Version ist ausreichend"
|
|
return 0
|
|
else
|
|
log "WARN" "Node.js Version zu alt, aktualisiere..."
|
|
fi
|
|
fi
|
|
|
|
# Versuche Installation über APT (NodeSource Repository)
|
|
if install_nodejs_apt; then
|
|
log "INFO" "Node.js über APT installiert"
|
|
return 0
|
|
fi
|
|
|
|
# Fallback: Installation über NodeSource Script
|
|
if install_nodejs_nodesource; then
|
|
log "INFO" "Node.js über NodeSource installiert"
|
|
return 0
|
|
fi
|
|
|
|
# Letzter Fallback: Snap
|
|
if install_nodejs_snap; then
|
|
log "INFO" "Node.js über Snap installiert"
|
|
return 0
|
|
fi
|
|
|
|
log "ERROR" "Node.js Installation fehlgeschlagen"
|
|
return 1
|
|
}
|
|
|
|
install_nodejs_apt() {
|
|
log "INFO" "Versuche Node.js Installation über APT..."
|
|
|
|
# APT-Cache aktualisieren
|
|
apt-get update -y
|
|
|
|
# Node.js installieren
|
|
if DEBIAN_FRONTEND=noninteractive apt-get install -y nodejs npm; then
|
|
# Version prüfen
|
|
local node_version=$(node --version 2>/dev/null || echo "v0.0.0")
|
|
local npm_version=$(npm --version 2>/dev/null || echo "0.0.0")
|
|
|
|
log "INFO" "Node.js installiert: $node_version"
|
|
log "INFO" "npm installiert: $npm_version"
|
|
|
|
return 0
|
|
else
|
|
log "WARN" "APT Node.js Installation fehlgeschlagen"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
install_nodejs_nodesource() {
|
|
log "INFO" "Versuche Node.js Installation über NodeSource..."
|
|
|
|
# NodeSource Setup-Script herunterladen und ausführen
|
|
if curl -fsSL https://deb.nodesource.com/setup_18.x | bash -; then
|
|
# Node.js installieren
|
|
if DEBIAN_FRONTEND=noninteractive apt-get install -y nodejs; then
|
|
log "INFO" "Node.js über NodeSource erfolgreich installiert"
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
log "WARN" "NodeSource Installation fehlgeschlagen"
|
|
return 1
|
|
}
|
|
|
|
install_nodejs_snap() {
|
|
log "INFO" "Versuche Node.js Installation über Snap..."
|
|
|
|
# Snap installieren falls nicht vorhanden
|
|
if ! command -v snap >/dev/null 2>&1; then
|
|
DEBIAN_FRONTEND=noninteractive apt-get install -y snapd
|
|
systemctl enable --now snapd.socket
|
|
sleep 5
|
|
fi
|
|
|
|
# Node.js über Snap installieren
|
|
if snap install node --classic; then
|
|
# Symlinks erstellen
|
|
ln -sf /snap/bin/node /usr/local/bin/node
|
|
ln -sf /snap/bin/npm /usr/local/bin/npm
|
|
|
|
log "INFO" "Node.js über Snap erfolgreich installiert"
|
|
return 0
|
|
fi
|
|
|
|
log "WARN" "Snap Node.js Installation fehlgeschlagen"
|
|
return 1
|
|
}
|
|
|
|
configure_npm() {
|
|
log "INFO" "Konfiguriere npm..."
|
|
|
|
# npm Konfiguration für bessere Performance
|
|
npm config set audit-level moderate
|
|
npm config set fund false
|
|
npm config set update-notifier false
|
|
npm config set prefer-offline true
|
|
|
|
# Cache-Verzeichnis setzen
|
|
npm config set cache "/home/$PROJECT_USER/.npm"
|
|
|
|
# Registry auf https setzen
|
|
npm config set registry https://registry.npmjs.org/
|
|
|
|
# Timeout erhöhen
|
|
npm config set timeout 300000
|
|
|
|
# npm auf neueste Version aktualisieren
|
|
log "INFO" "Aktualisiere npm auf neueste Version..."
|
|
npm install -g npm@latest || {
|
|
log "WARN" "npm-Update hatte Probleme"
|
|
}
|
|
|
|
# Berechtigungen für npm-Cache
|
|
chown -R "$PROJECT_USER:$PROJECT_GROUP" "/home/$PROJECT_USER/.npm" 2>/dev/null || true
|
|
|
|
log "INFO" "npm konfiguriert"
|
|
}
|
|
|
|
install_npm_packages() {
|
|
log "INFO" "Installiere npm-Packages..."
|
|
|
|
# Package.json prüfen
|
|
local package_json="$INSTALL_PATH/package.json"
|
|
if [[ ! -f "$package_json" ]]; then
|
|
log "WARN" "package.json nicht gefunden: $package_json"
|
|
log "INFO" "Erstelle minimale package.json..."
|
|
create_minimal_package_json
|
|
fi
|
|
|
|
# Wechsle ins Installationsverzeichnis
|
|
cd "$INSTALL_PATH"
|
|
|
|
# npm install ausführen
|
|
log "INFO" "Führe npm install aus..."
|
|
|
|
if npm install --production; then
|
|
log "INFO" "npm-Packages erfolgreich installiert"
|
|
else
|
|
log "WARN" "npm install hatte Probleme, versuche --force..."
|
|
if npm install --production --force; then
|
|
log "INFO" "npm-Packages mit --force installiert"
|
|
else
|
|
log "ERROR" "npm install fehlgeschlagen"
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
# Package-Liste für Debugging
|
|
npm list --depth=0 > npm_packages.txt 2>/dev/null || true
|
|
|
|
log "INFO" "npm-Packages Installation abgeschlossen"
|
|
}
|
|
|
|
create_minimal_package_json() {
|
|
log "INFO" "Erstelle minimale package.json..."
|
|
|
|
cat > "$INSTALL_PATH/package.json" << 'EOF'
|
|
{
|
|
"name": "myp-system",
|
|
"version": "1.0.0",
|
|
"description": "Mercedes-Benz 3D Printer Management System",
|
|
"main": "app.py",
|
|
"scripts": {
|
|
"build:css": "tailwindcss -i static/css/input.css -o static/css/output.css --minify",
|
|
"watch:css": "tailwindcss -i static/css/input.css -o static/css/output.css --watch",
|
|
"dev": "npm run watch:css",
|
|
"build": "npm run build:css"
|
|
},
|
|
"dependencies": {
|
|
"tailwindcss": "^3.3.0",
|
|
"@tailwindcss/forms": "^0.5.0",
|
|
"@tailwindcss/typography": "^0.5.0",
|
|
"autoprefixer": "^10.4.0",
|
|
"postcss": "^8.4.0"
|
|
},
|
|
"keywords": ["3d-printing", "management", "mercedes-benz"],
|
|
"author": "Till Tomczak",
|
|
"license": "Proprietary"
|
|
}
|
|
EOF
|
|
|
|
log "INFO" "Minimale package.json erstellt"
|
|
}
|
|
|
|
build_frontend_assets() {
|
|
log "INFO" "Baue Frontend-Assets..."
|
|
|
|
cd "$INSTALL_PATH"
|
|
|
|
# Prüfe ob build-Script verfügbar ist
|
|
if npm run build --silent 2>/dev/null; then
|
|
log "INFO" "Frontend-Assets mit npm run build erstellt"
|
|
elif command -v tailwindcss >/dev/null 2>&1; then
|
|
log "INFO" "Verwende direkte TailwindCSS-Kommandos..."
|
|
build_tailwind_directly
|
|
else
|
|
log "WARN" "Kein Build-System verfügbar, überspringe Asset-Build"
|
|
return 0
|
|
fi
|
|
|
|
# Komprimiere Assets für Produktionsumgebung
|
|
compress_assets
|
|
|
|
log "INFO" "Frontend-Assets Build abgeschlossen"
|
|
}
|
|
|
|
build_tailwind_directly() {
|
|
log "INFO" "Baue TailwindCSS direkt..."
|
|
|
|
# Input-CSS erstellen falls nicht vorhanden
|
|
if [[ ! -f "static/css/input.css" ]]; then
|
|
mkdir -p "static/css"
|
|
cat > "static/css/input.css" << 'EOF'
|
|
@tailwind base;
|
|
@tailwind components;
|
|
@tailwind utilities;
|
|
|
|
/* Custom MYP Styles */
|
|
.btn-primary {
|
|
@apply bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 transition-colors;
|
|
}
|
|
|
|
.card {
|
|
@apply bg-white rounded-lg shadow-md p-6;
|
|
}
|
|
|
|
.form-input {
|
|
@apply border border-gray-300 rounded px-3 py-2 focus:outline-none focus:border-blue-500;
|
|
}
|
|
EOF
|
|
fi
|
|
|
|
# TailwindCSS Build
|
|
npx tailwindcss -i static/css/input.css -o static/css/output.css --minify || {
|
|
log "WARN" "TailwindCSS Build fehlgeschlagen"
|
|
}
|
|
}
|
|
|
|
compress_assets() {
|
|
log "INFO" "Komprimiere Assets..."
|
|
|
|
# CSS-Dateien komprimieren
|
|
find "$INSTALL_PATH/static/css" -name "*.css" -type f | while read -r css_file; do
|
|
if command -v gzip >/dev/null 2>&1; then
|
|
gzip -c "$css_file" > "${css_file}.gz"
|
|
log "INFO" "Komprimiert: $(basename "$css_file")"
|
|
fi
|
|
done
|
|
|
|
# JavaScript-Dateien komprimieren
|
|
find "$INSTALL_PATH/static/js" -name "*.js" -type f | while read -r js_file; do
|
|
if command -v gzip >/dev/null 2>&1; then
|
|
gzip -c "$js_file" > "${js_file}.gz"
|
|
log "INFO" "Komprimiert: $(basename "$js_file")"
|
|
fi
|
|
done
|
|
|
|
log "INFO" "Asset-Komprimierung abgeschlossen"
|
|
}
|
|
|
|
verify_python_dependencies() {
|
|
log "INFO" "Überprüfe Python-Dependencies..."
|
|
|
|
local errors=0
|
|
|
|
# Wichtige Packages prüfen
|
|
local critical_packages=(
|
|
"flask"
|
|
"flask-sqlalchemy"
|
|
"flask-login"
|
|
"flask-wtf"
|
|
"werkzeug"
|
|
"gunicorn"
|
|
)
|
|
|
|
for package in "${critical_packages[@]}"; do
|
|
if ! python3 -c "import $package" 2>/dev/null; then
|
|
log "ERROR" "Kritisches Python-Package fehlt: $package"
|
|
errors=$((errors + 1))
|
|
fi
|
|
done
|
|
|
|
# Erstelle Package-Report
|
|
python3 -c "import pkg_resources; print('\n'.join([str(d) for d in pkg_resources.working_set]))" > "$INSTALL_PATH/python_packages_installed.txt"
|
|
|
|
if [[ $errors -eq 0 ]]; then
|
|
log "INFO" "Python-Dependencies Verifikation erfolgreich"
|
|
return 0
|
|
else
|
|
log "ERROR" "Python-Dependencies Verifikation fehlgeschlagen ($errors Fehler)"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
verify_node_dependencies() {
|
|
log "INFO" "Überprüfe Node.js-Dependencies..."
|
|
|
|
local errors=0
|
|
|
|
# Node.js Version prüfen
|
|
if ! command -v node >/dev/null 2>&1; then
|
|
log "ERROR" "Node.js nicht verfügbar"
|
|
errors=$((errors + 1))
|
|
else
|
|
local node_version=$(node --version)
|
|
log "INFO" "Node.js Version: $node_version"
|
|
fi
|
|
|
|
# npm Version prüfen
|
|
if ! command -v npm >/dev/null 2>&1; then
|
|
log "ERROR" "npm nicht verfügbar"
|
|
errors=$((errors + 1))
|
|
else
|
|
local npm_version=$(npm --version)
|
|
log "INFO" "npm Version: $npm_version"
|
|
fi
|
|
|
|
# TailwindCSS prüfen
|
|
if ! npx tailwindcss --help >/dev/null 2>&1; then
|
|
log "WARN" "TailwindCSS nicht verfügbar"
|
|
fi
|
|
|
|
if [[ $errors -eq 0 ]]; then
|
|
log "INFO" "Node.js-Dependencies Verifikation erfolgreich"
|
|
return 0
|
|
else
|
|
log "ERROR" "Node.js-Dependencies Verifikation fehlgeschlagen ($errors Fehler)"
|
|
return 1
|
|
fi
|
|
} |