June 13Jun 13 Hallokurz eine kleine Geschichte: ich hatte netzwerkprobleme (abbrüche)... am ende war es ein defektes Netzwerkkabel .... (nun wäre die geschichte fertig) bei dem langen suchen ist mir (mit hilfe der KI) aufgefallen das es sein kann das die (onboard)netzwerkkarte wohl auch noch ein problem (ringbuffer) hat. habe immer tx_errors gehabt. mir hat das script geholfen um zu sehen wann die 'probleme' auftreten (vorsicht 100% vibe code)ich habe dann festgestellt das es immer beim UrBackup die probleme gibt (also bei last)nach dem deaktivieren der onboard karte und einbau einer Intel Gigabit CThabe ich nun keine fehler.ich hoffe das der code nicht ganz so schlecht ist (100% KI) und vielleicht hilft es ja dem einen oder anderen#!/bin/bash #name=Linkwatch #description=Netzwerk-Ereignisse loggen und alarmieren #backgroundOnly=true #arrayStarted=true LOGFILE="/mnt/user/Log/NetzwerkCRASH.log" PIDFILE="/var/run/linkwatch.pid" CLEANUP_FLAG="/tmp/linkwatch_cleanup_done" IFACE="eth0" SLEEP_BEFORE_START=30 MAX_LOG_BYTES=$((50 * 1024 * 1024)) HOSTNAME=$(hostname) MAIN_PID=$$ log() { if [ -f "$LOGFILE" ] && [ "$(stat -c%s "$LOGFILE")" -ge "$MAX_LOG_BYTES" ]; then tail -c $((MAX_LOG_BYTES / 2)) "$LOGFILE" > "${LOGFILE}.tmp" \ && mv "${LOGFILE}.tmp" "$LOGFILE" echo "===== Log rotiert $(date '+%F %T') =====" >> "$LOGFILE" fi echo "$*" >> "$LOGFILE" } # Kompakte NIC-Zusammenfassung (nur relevante Felder) nic_summary() { local iface="$1" local speed duplex autoneg link mac speed=$(ethtool "$iface" 2>/dev/null | awk '/Speed:/{print $2}') duplex=$(ethtool "$iface" 2>/dev/null | awk '/Duplex:/{print $2}') autoneg=$(ethtool "$iface" 2>/dev/null | awk '/Auto-negotiation:/{print $2}') link=$(ethtool "$iface" 2>/dev/null | awk '/Link detected:/{print $3}') mac=$(ip link show "$iface" 2>/dev/null | awk '/link\/ether/{print $2}') local tx_err rx_miss tx_pkt rx_pkt tx_err=$(ethtool -S "$iface" 2>/dev/null | awk '/tx_errors/{print $2}') rx_miss=$(ethtool -S "$iface" 2>/dev/null | awk '/rx_missed/{print $2}') tx_pkt=$(ethtool -S "$iface" 2>/dev/null | awk '/tx_packets/{print $2}') rx_pkt=$(ethtool -S "$iface" 2>/dev/null | awk '/rx_packets/{print $2}') echo " MAC=$mac Speed=${speed:-?} Duplex=${duplex:-?} AutoNeg=${autoneg:-?} Link=${link:-?}" echo " TX=$tx_pkt RX=$rx_pkt TX-Err=${tx_err:-0} RX-Missed=${rx_miss:-0}" } # ── Restart-Logik ────────────────────────────────────────────────── if [ -f "$PIDFILE" ]; then OLD_PID=$(cat "$PIDFILE") if kill -0 "$OLD_PID" 2>/dev/null; then log "===== Linkwatch Restart – stoppe PID $OLD_PID $(date '+%F %T') =====" pkill -P "$OLD_PID" 2>/dev/null kill "$OLD_PID" 2>/dev/null sleep 2 else log "===== Linkwatch – veraltete PID bereinigt $(date '+%F %T') =====" fi rm -f "$PIDFILE" fi rm -f "$CLEANUP_FLAG" # ── Lock ─────────────────────────────────────────────────────────── exec 9>"$PIDFILE" if ! flock -n 9; then log "Linkwatch Lock aktiv – Abbruch." exit 1 fi echo $$ >&9 # ── Cleanup ──────────────────────────────────────────────────────── cleanup() { if [ ! -f "$CLEANUP_FLAG" ]; then touch "$CLEANUP_FLAG" log "===== Linkwatch beendet $(date '+%F %T') =====" rm -f "$PIDFILE" pkill -P "$MAIN_PID" 2>/dev/null fi } trap cleanup EXIT INT TERM # ── Alert via Unraid Notify ──────────────────────────────────────── send_alert() { local subject="$1" local message="$2" log ">>> ALERT: $subject – $message" /usr/local/emhttp/plugins/dynamix/scripts/notify \ -s "[$HOSTNAME] $subject" \ -d "$message" \ -i "alert" } # ── Cooldown ────────────────────────────────────────────────────── LAST_ALERT_FILE="/tmp/linkwatch_last_alert.txt" cooldown_ok() { local last now last=$(cat "$LAST_ALERT_FILE" 2>/dev/null || echo 0) now=$(date +%s) if [ $((now - last)) -gt 300 ]; then echo "$now" > "$LAST_ALERT_FILE" return 0 fi return 1 } sleep "$SLEEP_BEFORE_START" log "===== Linkwatch gestartet $(date '+%F %T') =====" # ── Baseline ─────────────────────────────────────────────────────── TX_NOW=$(ethtool -S "$IFACE" 2>/dev/null | awk '/tx_errors/{print $2}') echo "${TX_NOW:-0}" > /tmp/lw_tx_last.txt log "Baseline TX Errors: ${TX_NOW:-0}" RX_MISSED_NOW=$(ethtool -S "$IFACE" 2>/dev/null | awk '/rx_missed/{print $2}') echo "${RX_MISSED_NOW:-0}" > /tmp/lw_rxmissed_last.txt log "Baseline RX Missed: ${RX_MISSED_NOW:-0}" dmesg -c > /dev/null 2>&1 log "dmesg Buffer geleert – überwache ab $(date '+%F %T')" # ── 1. ip monitor – Link Events (kein veth-Spam) ─────────────────── ip monitor link | grep -v "veth" | while read -r line; do log "===== $(date '+%F %T') =====" log "$line" nic_summary "$IFACE" | while read -r summary; do log "$summary"; done log "" done & # ── 2. dmesg -w – Kernel Events ──────────────────────────────────── dmesg -w \ | grep --line-buffered -E "${IFACE}|r8169|NETDEV|link" \ | grep -v --line-buffered "veth" \ | while read -r line; do log "$(date '+%F %T') $line" if echo "$line" | grep -qi "downshift"; then SPEED=$(echo "$line" | grep -oP 'actual speed \K\S+') cooldown_ok && send_alert "NIC Downshift!" \ "eth0 auf ${SPEED:-?} degradiert" fi if echo "$line" | grep -qi "Link is Down"; then cooldown_ok && send_alert "Link Down!" "eth0 Verbindung verloren" fi if echo "$line" | grep -qi "Link is Up"; then log "Link wieder up ($(date '+%F %T'))" fi done & # ── 3. Periodische Checks alle 5 min ────────────────────────────── HOUR_COUNTER=0 while true; do sleep 300 HOUR_COUNTER=$((HOUR_COUNTER + 1)) # Stündliches Stats-Log if [ $((HOUR_COUNTER % 12)) -eq 0 ]; then TX_STAT=$(ethtool -S "$IFACE" 2>/dev/null | awk '/tx_errors/{print $2}') RX_STAT=$(ethtool -S "$IFACE" 2>/dev/null | awk '/rx_missed/{print $2}') SPEED_STAT=$(ethtool "$IFACE" 2>/dev/null | awk '/Speed:/{print $2}') log "── Stunden-Stats $(date '+%F %T') – Speed: $SPEED_STAT | TX Errors: $TX_STAT | RX Missed: $RX_STAT" fi # Speed-Check SPEED=$(ethtool "$IFACE" 2>/dev/null | awk '/Speed:/{print $2}') if [[ "$SPEED" != "1000Mb/s" && "$SPEED" != "" ]]; then cooldown_ok && send_alert "Speed degradiert!" "eth0 läuft mit $SPEED" fi # TX Errors Delta TX_NOW=$(ethtool -S "$IFACE" 2>/dev/null | awk '/tx_errors/{print $2}') TX_LAST=$(cat /tmp/lw_tx_last.txt 2>/dev/null || echo 0) echo "$TX_NOW" > /tmp/lw_tx_last.txt TX_DIFF=$((TX_NOW - TX_LAST)) if [ "$TX_DIFF" -gt 10 ]; then send_alert "TX Errors!" \ "eth0 +$TX_DIFF tx_errors in letzten 5 min (gesamt: $TX_NOW)" fi # RX Missed Delta (mit Counter-Reset-Schutz) RX_NOW=$(ethtool -S "$IFACE" 2>/dev/null | awk '/rx_missed/{print $2}') RX_LAST=$(cat /tmp/lw_rxmissed_last.txt 2>/dev/null || echo 0) RX_DIFF=$((RX_NOW - RX_LAST)) if [ "$RX_DIFF" -lt 0 ]; then # Counter wurde zurückgesetzt (Reboot/Reload) log "── RX Missed Counter Reset erkannt – neue Baseline: $RX_NOW" echo "$RX_NOW" > /tmp/lw_rxmissed_last.txt else echo "$RX_NOW" > /tmp/lw_rxmissed_last.txt if [ "$RX_DIFF" -gt 1000 ]; then send_alert "RX Buffer Overflow!" \ "eth0 +$RX_DIFF rx_missed in letzten 5 min" fi fi # Gateway-Check GW=$(ip route | awk '/default/{print $3}' | head -1) if [ -n "$GW" ] && ! ping -c 2 -W 2 "$GW" &>/dev/null; then cooldown_ok && send_alert "Gateway down!" "Ping auf $GW fehlgeschlagen" fi done & wait
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.