#!/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