#!/bin/bash # mc-log-watcher.sh - Parse les logs MC en temps réel + historique récent OUTPUT="/var/cache/mc-logs.json" MAX_EVENTS=200 LOG_MC1="/srv/Minecraft/logs/latest.log" LOG_MC2="/srv/Fabric/logs/latest.log" TMP="$OUTPUT.tmp" HISTORY_LINES=500 # Lignes historiques à lire au démarrage declare -a EVENTS=() touch "$OUTPUT" chmod 644 "$OUTPUT" write_json() { local json='{"events":[' local first=true for event in "${EVENTS[@]}"; do $first || json+=',' json+="$event" first=false done json+=']}' echo "$json" > "$TMP" mv "$TMP" "$OUTPUT" } add_event() { local server="$1" local type="$2" local message="$3" local ts="$4" # optionnel: timestamp extrait du log # Si pas de timestamp fourni, utiliser l'heure actuelle if [ -z "$ts" ]; then ts=$(date -u +"%Y-%m-%dT%H:%M:%SZ") fi message="${message//\\/\\\\}" message="${message//\"/\\\"}" local entry="{\"ts\":\"$ts\",\"server\":\"$server\",\"type\":\"$type\",\"msg\":\"$message\"}" EVENTS+=("$entry") if [ "${#EVENTS[@]}" -gt "$MAX_EVENTS" ]; then EVENTS=("${EVENTS[@]:1}") fi } # Extraire le timestamp ISO depuis une ligne de log MC # Format: [HH:MM:SS] ... → on utilise la date du jour + l'heure du log extract_ts() { local line="$1" local hour if [[ "$line" =~ ^\[([0-9]{2}):([0-9]{2}):([0-9]{2})\] ]]; then hour="${BASH_REMATCH[1]}:${BASH_REMATCH[2]}:${BASH_REMATCH[3]}" echo "$(date -u +%Y-%m-%d)T${hour}Z" else date -u +"%Y-%m-%dT%H:%M:%SZ" fi } parse_line() { local server="$1" local line="$2" local write="$3" # "write" pour écrire le JSON après [[ -z "$line" ]] && return local ts ts=$(extract_ts "$line") if [[ "$line" =~ ([A-Za-z0-9_]+)\ joined\ the\ game ]]; then add_event "$server" "join" "${BASH_REMATCH[1]} a rejoint le serveur" "$ts" elif [[ "$line" =~ ([A-Za-z0-9_]+)\ left\ the\ game ]]; then add_event "$server" "leave" "${BASH_REMATCH[1]} a quitté le serveur" "$ts" elif [[ "$line" =~ ([A-Za-z0-9_]+)\ (was\ slain|was\ shot|drowned|fell|burned|tried\ to\ swim|walked\ into|was\ killed|was\ blown|suffocated|hit\ the\ ground|starved|was\ poked|was\ impaled|was\ fireballed|was\ stung) ]]; then local msg="${line#*]: }" add_event "$server" "death" "$msg" "$ts" elif [[ "$line" =~ ([A-Za-z0-9_]+)\ has\ (made\ the\ advancement|completed\ the\ challenge|reached\ the\ goal)\ \[(.+)\] ]]; then add_event "$server" "advancement" "${BASH_REMATCH[1]} : ${BASH_REMATCH[3]}" "$ts" elif [[ "$line" =~ \[Server\ thread/INFO\]:\ \<([A-Za-z0-9_]+)\>\ (.+) ]]; then add_event "$server" "chat" "<${BASH_REMATCH[1]}> ${BASH_REMATCH[2]}" "$ts" elif [[ "$line" =~ Done\ \([0-9.]+s\)\!\ For\ help ]]; then add_event "$server" "start" "Serveur démarré" "$ts" elif [[ "$line" =~ Stopping\ the\ server ]]; then add_event "$server" "stop" "Serveur arrêté" "$ts" fi [ "$write" = "write" ] && write_json } # ===== Lire l'historique récent des deux logs ===== echo "[mc-log-watcher] Lecture historique ($HISTORY_LINES lignes)..." if [ -f "$LOG_MC1" ]; then while IFS= read -r line; do parse_line "MC1" "$line" done < <(tail -n "$HISTORY_LINES" "$LOG_MC1") fi if [ -f "$LOG_MC2" ]; then while IFS= read -r line; do parse_line "MC2" "$line" done < <(tail -n "$HISTORY_LINES" "$LOG_MC2") fi write_json echo "[mc-log-watcher] Historique chargé (${#EVENTS[@]} events). Surveillance en cours..." # ===== Surveiller en temps réel ===== FIFO=$(mktemp -u /tmp/mc-watcher-XXXXXX) mkfifo "$FIFO" trap "rm -f $FIFO; kill 0" EXIT INT TERM tail -F "$LOG_MC1" 2>/dev/null | sed 's/^/MC1|/' > "$FIFO" & tail -F "$LOG_MC2" 2>/dev/null | sed 's/^/MC2|/' > "$FIFO" & while IFS= read -r rawline; do server="${rawline%%|*}" line="${rawline#*|}" parse_line "$server" "$line" "write" done < "$FIFO"