211 lines
6.3 KiB
Bash
Executable File
211 lines
6.3 KiB
Bash
Executable File
#!/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
|
|
|