Add production build optimizations to Vite configuration; set target, output directory, and minification options for improved performance
This commit is contained in:
345
scripts/README.md
Normal file
345
scripts/README.md
Normal file
@@ -0,0 +1,345 @@
|
||||
# TimeClock v3 - Server-Management Scripts
|
||||
|
||||
Dieses Verzeichnis enthält hilfreiche Wartungs- und Management-Scripts für den Produktions-Server.
|
||||
|
||||
## Übersicht
|
||||
|
||||
| Script | Beschreibung | Verwendung |
|
||||
|--------|--------------|------------|
|
||||
| `backup-timeclock.sh` | Erstellt automatische Datenbank-Backups | Täglich per Cronjob |
|
||||
| `health-check.sh` | Überwacht API-Verfügbarkeit | Alle 5 Min per Cronjob |
|
||||
| `restore-backup.sh` | Stellt Datenbank-Backup wieder her | Manuell bei Bedarf |
|
||||
|
||||
---
|
||||
|
||||
## 1. backup-timeclock.sh
|
||||
|
||||
Erstellt automatische komprimierte Backups der MySQL-Datenbank.
|
||||
|
||||
### Installation
|
||||
|
||||
```bash
|
||||
# Auf den Server kopieren
|
||||
sudo cp scripts/backup-timeclock.sh /usr/local/bin/
|
||||
sudo chmod +x /usr/local/bin/backup-timeclock.sh
|
||||
|
||||
# Cronjob einrichten (täglich um 2 Uhr)
|
||||
sudo crontab -e
|
||||
```
|
||||
|
||||
Füge folgende Zeile hinzu:
|
||||
```cron
|
||||
0 2 * * * /usr/local/bin/backup-timeclock.sh >> /var/log/timeclock/backup.log 2>&1
|
||||
```
|
||||
|
||||
### Manuell ausführen
|
||||
|
||||
```bash
|
||||
/usr/local/bin/backup-timeclock.sh
|
||||
```
|
||||
|
||||
### Features
|
||||
|
||||
- ✅ Automatische Datenbank-Backups mit Kompression
|
||||
- ✅ Konfigurierbare Retention (Standard: 30 Tage)
|
||||
- ✅ Optional: Code-Backups
|
||||
- ✅ Optional: Remote-Backup per rsync
|
||||
- ✅ Optional: E-Mail-Benachrichtigungen
|
||||
- ✅ Backup-Statistiken
|
||||
|
||||
### Konfiguration
|
||||
|
||||
Bearbeite die Variablen am Anfang des Scripts:
|
||||
|
||||
```bash
|
||||
BACKUP_DIR="/var/backups/timeclock"
|
||||
RETENTION_DAYS=30
|
||||
BACKUP_CODE=false # true für Code-Backups
|
||||
REMOTE_BACKUP=false # true für Remote-Backup
|
||||
SEND_EMAIL=false # true für E-Mail-Benachrichtigung
|
||||
```
|
||||
|
||||
### Backup-Dateien
|
||||
|
||||
Backups werden gespeichert unter:
|
||||
- Datenbank: `/var/backups/timeclock/timeclock_db_YYYYMMDD_HHMMSS.sql.gz`
|
||||
- Code: `/var/backups/timeclock/timeclock_code_YYYYMMDD_HHMMSS.tar.gz`
|
||||
|
||||
---
|
||||
|
||||
## 2. health-check.sh
|
||||
|
||||
Überwacht die Verfügbarkeit des Backend-API und startet den Service bei Bedarf automatisch neu.
|
||||
|
||||
### Installation
|
||||
|
||||
```bash
|
||||
# Auf den Server kopieren
|
||||
sudo cp scripts/health-check.sh /usr/local/bin/
|
||||
sudo chmod +x /usr/local/bin/health-check.sh
|
||||
|
||||
# Cronjob einrichten (alle 5 Minuten)
|
||||
crontab -e
|
||||
```
|
||||
|
||||
Füge folgende Zeile hinzu:
|
||||
```cron
|
||||
*/5 * * * * /usr/local/bin/health-check.sh >> /var/log/timeclock/health-check.log 2>&1
|
||||
```
|
||||
|
||||
### Manuell ausführen
|
||||
|
||||
```bash
|
||||
/usr/local/bin/health-check.sh
|
||||
```
|
||||
|
||||
### Features
|
||||
|
||||
- ✅ Prüft `/api/health` Endpunkt
|
||||
- ✅ Automatischer Neustart bei Ausfall
|
||||
- ✅ Mehrere Retry-Versuche (Standard: 3)
|
||||
- ✅ Unterstützt PM2 und systemd
|
||||
- ✅ Optional: E-Mail/Webhook-Benachrichtigungen
|
||||
- ✅ Ressourcen-Monitoring (CPU/RAM/Disk)
|
||||
|
||||
### Konfiguration
|
||||
|
||||
```bash
|
||||
API_URL="http://localhost:3010/api/health"
|
||||
USE_PM2=true # false für systemd
|
||||
MAX_RETRIES=3
|
||||
RETRY_DELAY=5
|
||||
SEND_EMAIL=false # true für E-Mail-Benachrichtigung
|
||||
```
|
||||
|
||||
### Benachrichtigungen
|
||||
|
||||
Das Script kann bei Ausfällen Benachrichtigungen senden via:
|
||||
- E-Mail (benötigt `mail` command)
|
||||
- Webhook (Discord, Slack, etc.)
|
||||
|
||||
Konfiguriere die entsprechenden Variablen im Script:
|
||||
|
||||
```bash
|
||||
SEND_EMAIL=true
|
||||
EMAIL_TO="admin@tsschulz.de"
|
||||
|
||||
WEBHOOK_URL="https://discord.com/api/webhooks/..."
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. restore-backup.sh
|
||||
|
||||
Interaktives Script zum Wiederherstellen von Datenbank-Backups.
|
||||
|
||||
### Verwendung
|
||||
|
||||
```bash
|
||||
# Interaktive Auswahl
|
||||
sudo /var/www/timeclock/scripts/restore-backup.sh
|
||||
|
||||
# Spezifisches Backup wiederherstellen
|
||||
sudo /var/www/timeclock/scripts/restore-backup.sh timeclock_db_20251018_020000.sql.gz
|
||||
|
||||
# Mit vollständigem Pfad
|
||||
sudo /var/www/timeclock/scripts/restore-backup.sh /var/backups/timeclock/timeclock_db_20251018_020000.sql.gz
|
||||
```
|
||||
|
||||
### Features
|
||||
|
||||
- ✅ Interaktive Backup-Auswahl
|
||||
- ✅ Sicherheitskopie vor Restore
|
||||
- ✅ Konfirmations-Prompts
|
||||
- ✅ Automatisches Service-Neustart (optional)
|
||||
- ✅ Datenbank-Statistiken nach Restore
|
||||
|
||||
### Ablauf
|
||||
|
||||
1. Zeigt Liste verfügbarer Backups
|
||||
2. Erstellt Sicherheitskopie der aktuellen DB
|
||||
3. Bestätigung erforderlich
|
||||
4. Restore durchführen
|
||||
5. Optional: Service neu starten
|
||||
|
||||
### ⚠️ WARNUNG
|
||||
|
||||
Das Restore überschreibt die aktuelle Datenbank! Eine Sicherheitskopie wird automatisch erstellt, aber sei vorsichtig!
|
||||
|
||||
---
|
||||
|
||||
## Logs
|
||||
|
||||
Alle Scripts loggen nach:
|
||||
- `/var/log/timeclock/backup.log` - Backup-Logs
|
||||
- `/var/log/timeclock/health-check.log` - Health-Check-Logs
|
||||
|
||||
### Logs ansehen
|
||||
|
||||
```bash
|
||||
# Backup-Logs
|
||||
tail -f /var/log/timeclock/backup.log
|
||||
|
||||
# Health-Check-Logs
|
||||
tail -f /var/log/timeclock/health-check.log
|
||||
|
||||
# Alle Logs
|
||||
tail -f /var/log/timeclock/*.log
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Cronjob-Übersicht
|
||||
|
||||
Empfohlene Cronjob-Konfiguration:
|
||||
|
||||
```cron
|
||||
# TimeClock Maintenance Jobs
|
||||
|
||||
# Backup: Täglich um 2 Uhr morgens
|
||||
0 2 * * * /usr/local/bin/backup-timeclock.sh >> /var/log/timeclock/backup.log 2>&1
|
||||
|
||||
# Health-Check: Alle 5 Minuten
|
||||
*/5 * * * * /usr/local/bin/health-check.sh >> /var/log/timeclock/health-check.log 2>&1
|
||||
|
||||
# Optional: Log-Rotation - Alte Logs löschen (älter als 90 Tage)
|
||||
0 3 * * 0 find /var/log/timeclock -name "*.log" -mtime +90 -delete
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Weitere nützliche Commands
|
||||
|
||||
### Backup-Verwaltung
|
||||
|
||||
```bash
|
||||
# Liste aller Backups
|
||||
ls -lh /var/backups/timeclock/
|
||||
|
||||
# Anzahl der Backups
|
||||
ls -1 /var/backups/timeclock/timeclock_db_*.sql.gz | wc -l
|
||||
|
||||
# Gesamtgröße der Backups
|
||||
du -sh /var/backups/timeclock/
|
||||
|
||||
# Ältestes Backup
|
||||
ls -t /var/backups/timeclock/timeclock_db_*.sql.gz | tail -1
|
||||
|
||||
# Neuestes Backup
|
||||
ls -t /var/backups/timeclock/timeclock_db_*.sql.gz | head -1
|
||||
|
||||
# Manuell alte Backups löschen (älter als 30 Tage)
|
||||
find /var/backups/timeclock -name "timeclock_db_*.sql.gz" -mtime +30 -delete
|
||||
```
|
||||
|
||||
### Service-Management
|
||||
|
||||
```bash
|
||||
# Mit PM2
|
||||
pm2 status
|
||||
pm2 logs timeclock-backend
|
||||
pm2 restart timeclock-backend
|
||||
pm2 monit
|
||||
|
||||
# Mit systemd
|
||||
sudo systemctl status timeclock
|
||||
sudo journalctl -u timeclock -f
|
||||
sudo systemctl restart timeclock
|
||||
```
|
||||
|
||||
### API-Tests
|
||||
|
||||
```bash
|
||||
# Health-Check
|
||||
curl http://localhost:3010/api/health
|
||||
|
||||
# Mit Details
|
||||
curl -s http://localhost:3010/api/health | jq
|
||||
|
||||
# Response-Zeit messen
|
||||
time curl -s http://localhost:3010/api/health > /dev/null
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Script läuft nicht
|
||||
|
||||
```bash
|
||||
# Berechtigungen prüfen
|
||||
ls -l /usr/local/bin/backup-timeclock.sh
|
||||
|
||||
# Ausführbar machen
|
||||
sudo chmod +x /usr/local/bin/backup-timeclock.sh
|
||||
|
||||
# Script-Fehler debuggen
|
||||
bash -x /usr/local/bin/backup-timeclock.sh
|
||||
```
|
||||
|
||||
### Cronjob läuft nicht
|
||||
|
||||
```bash
|
||||
# Cronjobs anzeigen
|
||||
crontab -l
|
||||
|
||||
# Cron-Logs prüfen
|
||||
sudo grep CRON /var/log/syslog
|
||||
|
||||
# Cronjob manuell testen
|
||||
/usr/local/bin/backup-timeclock.sh
|
||||
```
|
||||
|
||||
### Backup schlägt fehl
|
||||
|
||||
```bash
|
||||
# DB-Verbindung testen
|
||||
mysql -u timeclock -p -e "SHOW DATABASES;"
|
||||
|
||||
# .env Datei prüfen
|
||||
cat /var/www/timeclock/backend/.env
|
||||
|
||||
# Backup-Verzeichnis prüfen
|
||||
ls -ld /var/backups/timeclock
|
||||
|
||||
# Schreibrechte prüfen
|
||||
touch /var/backups/timeclock/test.txt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Regelmäßige Backups testen**
|
||||
- Teste mindestens monatlich ein Restore
|
||||
- Verifiziere Backup-Integrität
|
||||
|
||||
2. **Monitoring einrichten**
|
||||
- Health-Checks aktivieren
|
||||
- E-Mail-Benachrichtigungen konfigurieren
|
||||
|
||||
3. **Logs überwachen**
|
||||
- Prüfe regelmäßig die Log-Dateien
|
||||
- Implementiere Log-Rotation
|
||||
|
||||
4. **Off-Site Backups**
|
||||
- Aktiviere Remote-Backup in `backup-timeclock.sh`
|
||||
- Speichere Backups an einem anderen Ort
|
||||
|
||||
5. **Sicherheit**
|
||||
- Schütze Backup-Dateien (enthalten sensible Daten!)
|
||||
- Setze restriktive Berechtigungen
|
||||
|
||||
---
|
||||
|
||||
## Support
|
||||
|
||||
Bei Problemen:
|
||||
1. Prüfe die Log-Dateien
|
||||
2. Teste Scripts manuell
|
||||
3. Siehe Haupt-Dokumentation: `../DEPLOYMENT.md`
|
||||
|
||||
---
|
||||
|
||||
**Automatisierte Wartung für sorgenfreien Betrieb! 🚀**
|
||||
|
||||
223
scripts/backup-timeclock.sh
Executable file
223
scripts/backup-timeclock.sh
Executable file
@@ -0,0 +1,223 @@
|
||||
#!/bin/bash
|
||||
|
||||
# =============================================================================
|
||||
# TimeClock v3 - Automatisches Backup-Script
|
||||
# =============================================================================
|
||||
# Erstellt tägliche Backups der Datenbank und optional des Codes
|
||||
#
|
||||
# Installation:
|
||||
# sudo cp backup-timeclock.sh /usr/local/bin/
|
||||
# sudo chmod +x /usr/local/bin/backup-timeclock.sh
|
||||
#
|
||||
# Cronjob einrichten (täglich um 2 Uhr):
|
||||
# sudo crontab -e
|
||||
# 0 2 * * * /usr/local/bin/backup-timeclock.sh >> /var/log/timeclock/backup.log 2>&1
|
||||
#
|
||||
# Manuell ausführen:
|
||||
# /usr/local/bin/backup-timeclock.sh
|
||||
# =============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
# Konfiguration
|
||||
BACKUP_DIR="/var/backups/timeclock"
|
||||
PROJECT_DIR="/var/www/timeclock"
|
||||
ENV_FILE="$PROJECT_DIR/backend/.env"
|
||||
RETENTION_DAYS=30 # Backups älter als X Tage werden gelöscht
|
||||
|
||||
# Datum
|
||||
DATE=$(date +%Y%m%d_%H%M%S)
|
||||
DATE_READABLE=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
|
||||
# Logging
|
||||
log() {
|
||||
echo "[${DATE_READABLE}] $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo "[${DATE_READABLE}] ERROR: $1" >&2
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Voraussetzungen prüfen
|
||||
# =============================================================================
|
||||
|
||||
if [ ! -f "$ENV_FILE" ]; then
|
||||
log_error ".env Datei nicht gefunden: $ENV_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Backup-Verzeichnis erstellen
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
|
||||
# =============================================================================
|
||||
# Datenbank-Credentials aus .env lesen
|
||||
# =============================================================================
|
||||
|
||||
log "Lese Datenbank-Konfiguration..."
|
||||
|
||||
# Funktion zum Auslesen von .env Werten
|
||||
get_env_value() {
|
||||
grep "^$1=" "$ENV_FILE" | cut -d '=' -f2- | tr -d '"' | tr -d "'"
|
||||
}
|
||||
|
||||
DB_HOST=$(get_env_value "DB_HOST")
|
||||
DB_PORT=$(get_env_value "DB_PORT")
|
||||
DB_NAME=$(get_env_value "DB_NAME")
|
||||
DB_USER=$(get_env_value "DB_USER")
|
||||
DB_PASSWORD=$(get_env_value "DB_PASSWORD")
|
||||
|
||||
# Defaults setzen
|
||||
DB_HOST=${DB_HOST:-localhost}
|
||||
DB_PORT=${DB_PORT:-3306}
|
||||
|
||||
if [ -z "$DB_NAME" ] || [ -z "$DB_USER" ] || [ -z "$DB_PASSWORD" ]; then
|
||||
log_error "Datenbank-Credentials unvollständig in .env"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "Datenbank: $DB_USER@$DB_HOST:$DB_PORT/$DB_NAME"
|
||||
|
||||
# =============================================================================
|
||||
# Datenbank-Backup erstellen
|
||||
# =============================================================================
|
||||
|
||||
log "Erstelle Datenbank-Backup..."
|
||||
|
||||
BACKUP_FILE="$BACKUP_DIR/timeclock_db_$DATE.sql.gz"
|
||||
|
||||
# mysqldump mit Kompression
|
||||
if mysqldump \
|
||||
--host="$DB_HOST" \
|
||||
--port="$DB_PORT" \
|
||||
--user="$DB_USER" \
|
||||
--password="$DB_PASSWORD" \
|
||||
--single-transaction \
|
||||
--routines \
|
||||
--triggers \
|
||||
--events \
|
||||
--add-drop-database \
|
||||
--databases "$DB_NAME" \
|
||||
| gzip > "$BACKUP_FILE"; then
|
||||
|
||||
# Dateigröße ermitteln
|
||||
SIZE=$(du -h "$BACKUP_FILE" | cut -f1)
|
||||
log "✅ Datenbank-Backup erfolgreich erstellt: $BACKUP_FILE ($SIZE)"
|
||||
else
|
||||
log_error "Datenbank-Backup fehlgeschlagen!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# Code-Backup erstellen (optional)
|
||||
# =============================================================================
|
||||
|
||||
BACKUP_CODE=false # Auf true setzen für Code-Backups
|
||||
|
||||
if [ "$BACKUP_CODE" = true ]; then
|
||||
log "Erstelle Code-Backup..."
|
||||
|
||||
CODE_BACKUP_FILE="$BACKUP_DIR/timeclock_code_$DATE.tar.gz"
|
||||
|
||||
if tar -czf "$CODE_BACKUP_FILE" \
|
||||
-C "$(dirname $PROJECT_DIR)" \
|
||||
--exclude="node_modules" \
|
||||
--exclude="dist" \
|
||||
--exclude=".git" \
|
||||
--exclude="*.log" \
|
||||
"$(basename $PROJECT_DIR)"; then
|
||||
|
||||
SIZE=$(du -h "$CODE_BACKUP_FILE" | cut -f1)
|
||||
log "✅ Code-Backup erfolgreich erstellt: $CODE_BACKUP_FILE ($SIZE)"
|
||||
else
|
||||
log_error "Code-Backup fehlgeschlagen!"
|
||||
fi
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# Alte Backups löschen
|
||||
# =============================================================================
|
||||
|
||||
log "Lösche alte Backups (älter als $RETENTION_DAYS Tage)..."
|
||||
|
||||
# Datenbank-Backups
|
||||
DELETED_DB=$(find "$BACKUP_DIR" -name "timeclock_db_*.sql.gz" -mtime +$RETENTION_DAYS -type f -delete -print | wc -l)
|
||||
if [ "$DELETED_DB" -gt 0 ]; then
|
||||
log "🗑️ $DELETED_DB alte Datenbank-Backups gelöscht"
|
||||
fi
|
||||
|
||||
# Code-Backups
|
||||
if [ "$BACKUP_CODE" = true ]; then
|
||||
DELETED_CODE=$(find "$BACKUP_DIR" -name "timeclock_code_*.tar.gz" -mtime +$RETENTION_DAYS -type f -delete -print | wc -l)
|
||||
if [ "$DELETED_CODE" -gt 0 ]; then
|
||||
log "🗑️ $DELETED_CODE alte Code-Backups gelöscht"
|
||||
fi
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# Backup-Statistik
|
||||
# =============================================================================
|
||||
|
||||
log "Backup-Statistik:"
|
||||
log " 📊 Gesamt-Backups: $(ls -1 $BACKUP_DIR/timeclock_db_*.sql.gz 2>/dev/null | wc -l)"
|
||||
log " 💾 Gesamtgröße: $(du -sh $BACKUP_DIR | cut -f1)"
|
||||
log " 📅 Ältestes Backup: $(ls -t $BACKUP_DIR/timeclock_db_*.sql.gz 2>/dev/null | tail -1 | xargs basename)"
|
||||
log " 📅 Neuestes Backup: $(ls -t $BACKUP_DIR/timeclock_db_*.sql.gz 2>/dev/null | head -1 | xargs basename)"
|
||||
|
||||
# =============================================================================
|
||||
# Optional: Backup an Remote-Server senden
|
||||
# =============================================================================
|
||||
|
||||
REMOTE_BACKUP=false # Auf true setzen für Remote-Backup
|
||||
REMOTE_USER="backup"
|
||||
REMOTE_HOST="backup.example.com"
|
||||
REMOTE_PATH="/backups/timeclock"
|
||||
|
||||
if [ "$REMOTE_BACKUP" = true ]; then
|
||||
log "Sende Backup an Remote-Server..."
|
||||
|
||||
if rsync -az --progress "$BACKUP_FILE" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_PATH/"; then
|
||||
log "✅ Remote-Backup erfolgreich"
|
||||
else
|
||||
log_error "Remote-Backup fehlgeschlagen!"
|
||||
fi
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# Optional: Backup-Benachrichtigung per E-Mail
|
||||
# =============================================================================
|
||||
|
||||
SEND_EMAIL=false # Auf true setzen für E-Mail-Benachrichtigung
|
||||
EMAIL_TO="admin@tsschulz.de"
|
||||
|
||||
if [ "$SEND_EMAIL" = true ] && command -v mail &> /dev/null; then
|
||||
log "Sende E-Mail-Benachrichtigung..."
|
||||
|
||||
SIZE=$(du -h "$BACKUP_FILE" | cut -f1)
|
||||
|
||||
echo "TimeClock Backup erfolgreich erstellt
|
||||
|
||||
Datum: $DATE_READABLE
|
||||
Datei: $BACKUP_FILE
|
||||
Größe: $SIZE
|
||||
Datenbank: $DB_NAME
|
||||
|
||||
Backup-Verzeichnis: $BACKUP_DIR
|
||||
Anzahl Backups: $(ls -1 $BACKUP_DIR/timeclock_db_*.sql.gz 2>/dev/null | wc -l)
|
||||
Gesamtgröße: $(du -sh $BACKUP_DIR | cut -f1)
|
||||
|
||||
--
|
||||
TimeClock v3 Backup System
|
||||
" | mail -s "✅ TimeClock Backup erfolgreich ($DATE)" "$EMAIL_TO"
|
||||
|
||||
log "📧 E-Mail gesendet an $EMAIL_TO"
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# Fertig
|
||||
# =============================================================================
|
||||
|
||||
log "✅ Backup-Prozess abgeschlossen!"
|
||||
|
||||
exit 0
|
||||
|
||||
210
scripts/health-check.sh
Executable file
210
scripts/health-check.sh
Executable file
@@ -0,0 +1,210 @@
|
||||
#!/bin/bash
|
||||
|
||||
# =============================================================================
|
||||
# TimeClock v3 - Health-Check Script
|
||||
# =============================================================================
|
||||
# Überwacht die Verfügbarkeit des Backend-API und startet bei Bedarf neu
|
||||
#
|
||||
# Installation:
|
||||
# sudo cp health-check.sh /usr/local/bin/
|
||||
# sudo chmod +x /usr/local/bin/health-check.sh
|
||||
#
|
||||
# Cronjob einrichten (alle 5 Minuten):
|
||||
# crontab -e
|
||||
# */5 * * * * /usr/local/bin/health-check.sh >> /var/log/timeclock/health-check.log 2>&1
|
||||
#
|
||||
# Manuell ausführen:
|
||||
# /usr/local/bin/health-check.sh
|
||||
# =============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
# Konfiguration
|
||||
API_URL="http://localhost:3010/api/health"
|
||||
SERVICE_NAME="timeclock-backend"
|
||||
USE_PM2=true # true für PM2, false für systemd
|
||||
LOG_FILE="/var/log/timeclock/health-check.log"
|
||||
MAX_RETRIES=3
|
||||
RETRY_DELAY=5 # Sekunden zwischen Versuchen
|
||||
|
||||
# Datum
|
||||
DATE=$(date '+%Y-%m-%d %H:%M:%S')
|
||||
|
||||
# Logging
|
||||
log() {
|
||||
echo "[$DATE] $1" | tee -a "$LOG_FILE"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo "[$DATE] ERROR: $1" | tee -a "$LOG_FILE" >&2
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Health-Check durchführen
|
||||
# =============================================================================
|
||||
|
||||
check_health() {
|
||||
# Versuche Health-Endpunkt zu erreichen
|
||||
if curl -sf "$API_URL" > /dev/null 2>&1; then
|
||||
return 0 # Erfolg
|
||||
else
|
||||
return 1 # Fehler
|
||||
fi
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Service neu starten
|
||||
# =============================================================================
|
||||
|
||||
restart_service() {
|
||||
log "⚠️ Versuche Service neu zu starten..."
|
||||
|
||||
if [ "$USE_PM2" = true ]; then
|
||||
# PM2
|
||||
if command -v pm2 &> /dev/null; then
|
||||
if pm2 restart "$SERVICE_NAME" > /dev/null 2>&1; then
|
||||
log "✅ Service mit PM2 neu gestartet"
|
||||
return 0
|
||||
else
|
||||
log_error "PM2-Neustart fehlgeschlagen!"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
log_error "PM2 nicht gefunden!"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
# systemd
|
||||
if sudo systemctl restart "$SERVICE_NAME"; then
|
||||
log "✅ Service mit systemd neu gestartet"
|
||||
return 0
|
||||
else
|
||||
log_error "systemd-Neustart fehlgeschlagen!"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Benachrichtigung senden
|
||||
# =============================================================================
|
||||
|
||||
send_notification() {
|
||||
local status=$1
|
||||
local message=$2
|
||||
|
||||
# Optional: E-Mail-Benachrichtigung
|
||||
SEND_EMAIL=false
|
||||
EMAIL_TO="admin@tsschulz.de"
|
||||
|
||||
if [ "$SEND_EMAIL" = true ] && command -v mail &> /dev/null; then
|
||||
echo "$message
|
||||
|
||||
Zeitpunkt: $DATE
|
||||
API-URL: $API_URL
|
||||
Service: $SERVICE_NAME
|
||||
|
||||
--
|
||||
TimeClock v3 Health-Check System
|
||||
" | mail -s "$status TimeClock Backend" "$EMAIL_TO"
|
||||
fi
|
||||
|
||||
# Optional: Webhook-Benachrichtigung (z.B. Discord, Slack)
|
||||
WEBHOOK_URL=""
|
||||
|
||||
if [ -n "$WEBHOOK_URL" ]; then
|
||||
curl -X POST "$WEBHOOK_URL" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"content\": \"$status $message\"}" \
|
||||
> /dev/null 2>&1
|
||||
fi
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Hauptlogik
|
||||
# =============================================================================
|
||||
|
||||
# Erstelle Log-Verzeichnis falls nicht vorhanden
|
||||
mkdir -p "$(dirname $LOG_FILE)"
|
||||
|
||||
# Prüfe ob Service läuft
|
||||
if [ "$USE_PM2" = true ]; then
|
||||
if ! pm2 list | grep -q "$SERVICE_NAME.*online"; then
|
||||
log_error "⚠️ Service läuft nicht (PM2)!"
|
||||
restart_service
|
||||
sleep 10
|
||||
fi
|
||||
else
|
||||
if ! systemctl is-active --quiet "$SERVICE_NAME"; then
|
||||
log_error "⚠️ Service läuft nicht (systemd)!"
|
||||
restart_service
|
||||
sleep 10
|
||||
fi
|
||||
fi
|
||||
|
||||
# Health-Check mit Retries
|
||||
SUCCESS=false
|
||||
|
||||
for i in $(seq 1 $MAX_RETRIES); do
|
||||
if check_health; then
|
||||
# Nur beim ersten Check des Tages loggen (um Log-Spam zu vermeiden)
|
||||
CURRENT_HOUR=$(date +%H)
|
||||
CURRENT_MINUTE=$(date +%M)
|
||||
|
||||
if [ "$CURRENT_HOUR" = "00" ] && [ "$CURRENT_MINUTE" -lt 6 ]; then
|
||||
log "✅ Health-Check erfolgreich"
|
||||
fi
|
||||
|
||||
SUCCESS=true
|
||||
break
|
||||
else
|
||||
if [ $i -lt $MAX_RETRIES ]; then
|
||||
log "⚠️ Health-Check fehlgeschlagen (Versuch $i/$MAX_RETRIES), warte $RETRY_DELAY Sekunden..."
|
||||
sleep $RETRY_DELAY
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Wenn alle Versuche fehlschlagen
|
||||
if [ "$SUCCESS" = false ]; then
|
||||
log_error "❌ Health-Check fehlgeschlagen nach $MAX_RETRIES Versuchen!"
|
||||
|
||||
# Service neu starten
|
||||
if restart_service; then
|
||||
# Nach Neustart erneut prüfen
|
||||
sleep 10
|
||||
|
||||
if check_health; then
|
||||
log "✅ Service nach Neustart wieder erreichbar"
|
||||
send_notification "⚠️ RECOVERED:" "TimeClock Backend wurde neu gestartet und ist wieder erreichbar."
|
||||
else
|
||||
log_error "❌ Service auch nach Neustart nicht erreichbar!"
|
||||
send_notification "🚨 CRITICAL:" "TimeClock Backend ist auch nach Neustart nicht erreichbar! Manuelle Intervention erforderlich."
|
||||
fi
|
||||
else
|
||||
log_error "❌ Service-Neustart fehlgeschlagen!"
|
||||
send_notification "🚨 CRITICAL:" "TimeClock Backend-Neustart fehlgeschlagen! Manuelle Intervention erforderlich."
|
||||
fi
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# Zusätzliche Checks (optional)
|
||||
# =============================================================================
|
||||
|
||||
# CPU & Memory Usage prüfen
|
||||
if [ "$USE_PM2" = true ] && command -v pm2 &> /dev/null; then
|
||||
PM2_STATUS=$(pm2 jlist | jq -r ".[] | select(.name==\"$SERVICE_NAME\") | \"CPU: \(.monit.cpu)%, Memory: \(.monit.memory / 1024 / 1024 | floor)MB\"" 2>/dev/null || echo "N/A")
|
||||
|
||||
# Nur bei hohem Ressourcenverbrauch loggen
|
||||
# (Optional: weitere Logik implementieren)
|
||||
fi
|
||||
|
||||
# Disk Space prüfen
|
||||
DISK_USAGE=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//')
|
||||
if [ "$DISK_USAGE" -gt 90 ]; then
|
||||
log_error "⚠️ Festplattenspeicher kritisch: ${DISK_USAGE}%"
|
||||
send_notification "⚠️ WARNING:" "Festplattenspeicher auf TimeClock-Server kritisch: ${DISK_USAGE}%"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
275
scripts/restore-backup.sh
Executable file
275
scripts/restore-backup.sh
Executable file
@@ -0,0 +1,275 @@
|
||||
#!/bin/bash
|
||||
|
||||
# =============================================================================
|
||||
# TimeClock v3 - Backup-Restore Script
|
||||
# =============================================================================
|
||||
# Stellt ein Datenbank-Backup wieder her
|
||||
#
|
||||
# Verwendung:
|
||||
# ./restore-backup.sh [BACKUP_FILE]
|
||||
# ./restore-backup.sh # Zeigt Liste der verfügbaren Backups
|
||||
# ./restore-backup.sh timeclock_db_20251018_020000.sql.gz
|
||||
#
|
||||
# WARNUNG: Dies überschreibt die aktuelle Datenbank!
|
||||
# =============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
# Farben
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
# Konfiguration
|
||||
BACKUP_DIR="/var/backups/timeclock"
|
||||
PROJECT_DIR="/var/www/timeclock"
|
||||
ENV_FILE="$PROJECT_DIR/backend/.env"
|
||||
|
||||
# Logging
|
||||
log() {
|
||||
echo -e "${BLUE}ℹ️ $1${NC}"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}✅ $1${NC}"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}⚠️ $1${NC}"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}❌ $1${NC}"
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Voraussetzungen prüfen
|
||||
# =============================================================================
|
||||
|
||||
if [ ! -f "$ENV_FILE" ]; then
|
||||
log_error ".env Datei nicht gefunden: $ENV_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d "$BACKUP_DIR" ]; then
|
||||
log_error "Backup-Verzeichnis nicht gefunden: $BACKUP_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# Datenbank-Credentials aus .env lesen
|
||||
# =============================================================================
|
||||
|
||||
get_env_value() {
|
||||
grep "^$1=" "$ENV_FILE" | cut -d '=' -f2- | tr -d '"' | tr -d "'"
|
||||
}
|
||||
|
||||
DB_HOST=$(get_env_value "DB_HOST")
|
||||
DB_PORT=$(get_env_value "DB_PORT")
|
||||
DB_NAME=$(get_env_value "DB_NAME")
|
||||
DB_USER=$(get_env_value "DB_USER")
|
||||
DB_PASSWORD=$(get_env_value "DB_PASSWORD")
|
||||
|
||||
# Defaults
|
||||
DB_HOST=${DB_HOST:-localhost}
|
||||
DB_PORT=${DB_PORT:-3306}
|
||||
|
||||
if [ -z "$DB_NAME" ] || [ -z "$DB_USER" ] || [ -z "$DB_PASSWORD" ]; then
|
||||
log_error "Datenbank-Credentials unvollständig in .env"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# Verfügbare Backups auflisten
|
||||
# =============================================================================
|
||||
|
||||
list_backups() {
|
||||
echo ""
|
||||
log "Verfügbare Backups in $BACKUP_DIR:"
|
||||
echo ""
|
||||
|
||||
BACKUPS=($(ls -t "$BACKUP_DIR"/timeclock_db_*.sql.gz 2>/dev/null))
|
||||
|
||||
if [ ${#BACKUPS[@]} -eq 0 ]; then
|
||||
log_warning "Keine Backups gefunden!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for i in "${!BACKUPS[@]}"; do
|
||||
BACKUP="${BACKUPS[$i]}"
|
||||
FILENAME=$(basename "$BACKUP")
|
||||
SIZE=$(du -h "$BACKUP" | cut -f1)
|
||||
DATE=$(stat -c %y "$BACKUP" | cut -d'.' -f1)
|
||||
|
||||
printf "%2d) %-50s %6s %s\n" $((i+1)) "$FILENAME" "$SIZE" "$DATE"
|
||||
done
|
||||
|
||||
echo ""
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Backup-Datei auswählen
|
||||
# =============================================================================
|
||||
|
||||
select_backup() {
|
||||
list_backups
|
||||
|
||||
read -p "Wähle ein Backup (Nummer) oder 'q' zum Beenden: " selection
|
||||
|
||||
if [ "$selection" = "q" ] || [ "$selection" = "Q" ]; then
|
||||
log "Abgebrochen."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! [[ "$selection" =~ ^[0-9]+$ ]]; then
|
||||
log_error "Ungültige Eingabe!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BACKUPS=($(ls -t "$BACKUP_DIR"/timeclock_db_*.sql.gz 2>/dev/null))
|
||||
INDEX=$((selection - 1))
|
||||
|
||||
if [ $INDEX -lt 0 ] || [ $INDEX -ge ${#BACKUPS[@]} ]; then
|
||||
log_error "Ungültige Auswahl!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BACKUP_FILE="${BACKUPS[$INDEX]}"
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Restore durchführen
|
||||
# =============================================================================
|
||||
|
||||
restore_backup() {
|
||||
local backup_file=$1
|
||||
|
||||
if [ ! -f "$backup_file" ]; then
|
||||
log_error "Backup-Datei nicht gefunden: $backup_file"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
log_warning "WARNUNG: Dies wird die aktuelle Datenbank '$DB_NAME' überschreiben!"
|
||||
log "Backup-Datei: $(basename $backup_file)"
|
||||
log "Größe: $(du -h $backup_file | cut -f1)"
|
||||
log "Datenbank: $DB_USER@$DB_HOST:$DB_PORT/$DB_NAME"
|
||||
echo ""
|
||||
|
||||
read -p "Fortfahren? (yes/no): " confirm
|
||||
|
||||
if [ "$confirm" != "yes" ]; then
|
||||
log "Abgebrochen."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Erstelle Backup der aktuellen Datenbank (Sicherheitskopie)
|
||||
log "Erstelle Sicherheitskopie der aktuellen Datenbank..."
|
||||
SAFETY_BACKUP="$BACKUP_DIR/timeclock_db_pre_restore_$(date +%Y%m%d_%H%M%S).sql.gz"
|
||||
|
||||
if mysqldump \
|
||||
--host="$DB_HOST" \
|
||||
--port="$DB_PORT" \
|
||||
--user="$DB_USER" \
|
||||
--password="$DB_PASSWORD" \
|
||||
--single-transaction \
|
||||
--databases "$DB_NAME" \
|
||||
| gzip > "$SAFETY_BACKUP"; then
|
||||
log_success "Sicherheitskopie erstellt: $(basename $SAFETY_BACKUP)"
|
||||
else
|
||||
log_error "Sicherheitskopie fehlgeschlagen!"
|
||||
read -p "Trotzdem fortfahren? (yes/no): " force
|
||||
if [ "$force" != "yes" ]; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Restore durchführen
|
||||
log "Stelle Backup wieder her..."
|
||||
|
||||
# Datenbank leeren (optional, aber empfohlen)
|
||||
log "Leere Datenbank..."
|
||||
mysql \
|
||||
--host="$DB_HOST" \
|
||||
--port="$DB_PORT" \
|
||||
--user="$DB_USER" \
|
||||
--password="$DB_PASSWORD" \
|
||||
-e "DROP DATABASE IF EXISTS $DB_NAME; CREATE DATABASE $DB_NAME;"
|
||||
|
||||
# Backup einspielen
|
||||
if gunzip < "$backup_file" | mysql \
|
||||
--host="$DB_HOST" \
|
||||
--port="$DB_PORT" \
|
||||
--user="$DB_USER" \
|
||||
--password="$DB_PASSWORD"; then
|
||||
|
||||
log_success "Backup erfolgreich wiederhergestellt!"
|
||||
|
||||
# Datenbank-Statistiken
|
||||
TABLE_COUNT=$(mysql \
|
||||
--host="$DB_HOST" \
|
||||
--port="$DB_PORT" \
|
||||
--user="$DB_USER" \
|
||||
--password="$DB_PASSWORD" \
|
||||
-e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '$DB_NAME';" -s -N)
|
||||
|
||||
log "Datenbank-Statistik:"
|
||||
log " 📊 Tabellen: $TABLE_COUNT"
|
||||
|
||||
# Optional: Service neu starten
|
||||
log_warning "Möchtest du den Backend-Service neu starten?"
|
||||
read -p "Service neu starten? (y/n): " restart
|
||||
|
||||
if [ "$restart" = "y" ] || [ "$restart" = "Y" ]; then
|
||||
if command -v pm2 &> /dev/null && pm2 list | grep -q "timeclock-backend"; then
|
||||
pm2 restart timeclock-backend
|
||||
log_success "PM2-Service neu gestartet"
|
||||
elif systemctl is-active --quiet timeclock; then
|
||||
sudo systemctl restart timeclock
|
||||
log_success "systemd-Service neu gestartet"
|
||||
else
|
||||
log_warning "Service-Verwaltung nicht gefunden - bitte manuell neu starten"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
log_success "Restore abgeschlossen!"
|
||||
log "Sicherheitskopie der alten Datenbank: $(basename $SAFETY_BACKUP)"
|
||||
|
||||
else
|
||||
log_error "Restore fehlgeschlagen!"
|
||||
log "Die Sicherheitskopie befindet sich unter: $(basename $SAFETY_BACKUP)"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Hauptprogramm
|
||||
# =============================================================================
|
||||
|
||||
echo ""
|
||||
echo -e "${BLUE}════════════════════════════════════════════════════════════${NC}"
|
||||
echo -e "${BLUE} TimeClock v3 - Backup Restore${NC}"
|
||||
echo -e "${BLUE}════════════════════════════════════════════════════════════${NC}"
|
||||
echo ""
|
||||
|
||||
# Wenn Backup-Datei als Argument übergeben wurde
|
||||
if [ $# -eq 1 ]; then
|
||||
BACKUP_FILE="$1"
|
||||
|
||||
# Wenn nur Dateiname (ohne Pfad) übergeben wurde
|
||||
if [ ! -f "$BACKUP_FILE" ]; then
|
||||
BACKUP_FILE="$BACKUP_DIR/$1"
|
||||
fi
|
||||
|
||||
restore_backup "$BACKUP_FILE"
|
||||
else
|
||||
# Interaktive Auswahl
|
||||
select_backup
|
||||
restore_backup "$BACKUP_FILE"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
Reference in New Issue
Block a user