Files
monitoring/check_inet_iface_curl.sh

253 lines
6.4 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
# Testet ein Interface mit curl gegen mehrere HTTP/HTTPS-Ziele.
# Online, sobald mindestens EIN Ziel funktioniert.
# Offline erst, wenn ALLE Ziele fehlschlagen.
# Erst der zweite Offline-Fall in Folge erzeugt Meldung + ggf. Aktion.
#
# Usage:
# check_inet_iface_curl.sh <interface> [--service NAME | --reboot] [--state-dir DIR]
# [--max-time SEC] [-h|--help]
IFACE="${1:-}"
shift || true
# Ziele - echte TCP/HTTPS-Tests
TARGETS=(
"https://oopen.de"
"https://1.1.1.1"
"https://8.8.8.8"
"https://www.debian.org"
)
CURL_BIN="$(command -v curl)"
DATE_BIN="$(command -v date)"
STATE_DIR="/run/check_inet"
MAX_TIME=8
SERVICE=""
DO_REBOOT=0
# terminal detection
IS_TTY=0
if [[ -t 1 || -t 2 ]]; then IS_TTY=1; fi
# colors (TTY only)
if [[ $IS_TTY -eq 1 ]]; then
RED=$'\e[31m'; GREEN=$'\e[32m'; YELLOW=$'\e[33m'; BOLD=$'\e[1m'; RESET=$'\e[0m'
else
RED=""; GREEN=""; YELLOW=""; BOLD=""; RESET=""
fi
usage() {
cat <<'USAGE'
check_inet_iface_curl.sh - prüft Konnektivität per curl über ein bestimmtes Interface.
Usage:
check_inet_iface_curl.sh <interface> [--restart-service NAME | --reboot] [--state-dir DIR]
[--max-time SEC] [-h|--help]
Optionen:
--restart-service NAME systemd-Service bei 2x OFFLINE in Folge neu starten
--reboot bei 2x OFFLINE in Folge System rebooten
--state-dir DIR State-Verzeichnis (Default: /run/check_inet)
--max-time SEC curl Timeout pro Ziel (Default: 8)
-h, --help Hilfe
Verhalten:
- Im Terminal: grün "OK" bei Erfolg, rot "FAILED" bei 2x OFFLINE + Details.
- Als Cron (kein TTY): bei Erfolg keine Ausgabe; bei 2x OFFLINE Meldung auf stderr
(damit Cron eine Mail erzeugen kann).
Exit-Codes:
0 = online / OK (oder 1. Offline nur gemerkt)
1 = 2x offline in Folge (Fehler + ggf. Aktion)
3 = Aktion fehlgeschlagen
USAGE
}
clean_up() {
# Perform program exit housekeeping
blank_line
exit $1
}
log_info() {
if [[ $IS_TTY -eq 1 ]] ; then
echo -e "$*";
fi
}
log_err() { echo -e "$*" >&2; }
die() { log_err "${RED}${BOLD}ERROR:${RESET} $*"; exit 64; }
blank_line() {
if [[ $IS_TTY -eq 1 ]] ; then
echo ""
fi
}
# -----------------------------
# args
# -----------------------------
while [[ $# -gt 0 ]]; do
case "$1" in
--restart-service)
[[ $# -ge 2 ]] || die "--restart-service braucht ein Argument"
SERVICE="$2"
shift 2
;;
--reboot)
DO_REBOOT=1
shift
;;
--state-dir)
[[ $# -ge 2 ]] || die "--state-dir braucht ein Argument"
STATE_DIR="$2"
shift 2
;;
--max-time)
[[ $# -ge 2 ]] || die "--max-time braucht ein Argument"
MAX_TIME="$2"
shift 2
;;
-h|--help)
usage
clean_up 0
;;
*)
die "Unbekannte Option: $1 (verwende -h)"
;;
esac
done
if [[ -z "$IFACE" ]]; then
usage >&2
clean_up 2
fi
if [[ -n "$SERVICE" && $DO_REBOOT -eq 1 ]]; then
die "--restart-service und --reboot schließen sich aus"
fi
STATE_FILE="$STATE_DIR/$IFACE.fail"
mkdir -p "$STATE_DIR"
# lock gegen parallele cron-runs
LOCK_FD=9
LOCK_FILE="$STATE_FILE.lock"
exec {LOCK_FD}>"$LOCK_FILE" || true
if command -v flock >/dev/null 2>&1; then
flock -n "$LOCK_FD" || clean_up 0
fi
# ------------------------------------------
# Funktion: Testet ein HTTP(S)-Ziel
# ------------------------------------------
test_target() {
local target="$1"
# -4 erzwingt IPv4, --interface bindet Source-Interface,
# --max-time begrenzt Timeout, -s silent, -o /dev/null keine Ausgabe
"$CURL_BIN" -4 --interface "$IFACE" --max-time "$MAX_TIME" -s -o /dev/null "$target"
}
# ------------------------------------------
# Tests
# ------------------------------------------
TOTAL="${#TARGETS[@]}"
FAILED=0
blank_line || true
log_info " Interface: \033[17G$IFACE"
log_info " Targets (${TOTAL}):\033[17G${TARGETS[*]}"
log_info " curl:\033[17G$CURL_BIN max-time: ${MAX_TIME}s"
blank_line || true
for TG in "${TARGETS[@]}"; do
if test_target "$TG"; then
log_info " ${GREEN}OK${RESET} $TG"
break;
else
FAILED=$((FAILED + 1))
log_info " ${YELLOW}FAIL${RESET} $TG"
fi
done
# Wenn mindestens EIN Ziel funktioniert -> online
if [[ $FAILED -lt $TOTAL ]]; then
[[ -f "$STATE_FILE" ]] && rm -f "$STATE_FILE"
if [[ $IS_TTY -eq 1 ]]; then
echo ""
echo -e " ${GREEN}${BOLD}OK${RESET} - Interface ${IFACE}: mindestens ein Ziel erreichbar."
fi
clean_up 0
fi
# Alle Ziele fail -> offline
# Erst beim zweiten Mal melden/handeln
TS="$("$DATE_BIN" '+%F %T')"
if [[ -f "$STATE_FILE" ]]; then
if [[ $IS_TTY -eq 1 ]]; then
log_err ""
log_err " ${RED}${BOLD}FAILED${RESET} - ${TS} - Interface ${IFACE}: TCP/HTTP(S) Verbindungen nicht erreichbar!
(curl; Targets: ${TARGETS[*]})"
log_err ""
else
log_err ""
log_err " ${TS} - Interface ${IFACE}: TCP/HTTP(S) Verbindungen nicht erreichbar!"
fi
# Aktion
if [[ -n "$SERVICE" ]]; then
log_info " ${YELLOW}Restart Service ${BOLD}$SERVICE${RESET}"
log_info ""
if systemctl restart "$SERVICE" >/dev/null 2>&1; then
if [[ $IS_TTY -eq 1 ]] ; then
log_err " ${GREEN}Service neugestartet:${RESET} $SERVICE"
else
log_err " ${TS} - Service neugestartet: $SERVICE"
log_err ""
fi
clean_up 1
else
if [[ $IS_TTY -eq 1 ]] ; then
log_err " ${RED}Service-Restart fehlgeschlagen:${RESET} $SERVICE"
else
log_err ""
log_err " ${TS} - Service-Restart fehlgeschlagen: $SERVICE"
log_err ""
fi
clean_up 3
fi
elif [[ $DO_REBOOT -eq 1 ]]; then
if [[ $IS_TTY -eq 1 ]]; then
log_err " ${YELLOW}${BOLD}Resboot machine NOW!${RESET}"
log_err ""
else
log_err " ${TS} - Resboot machine NOW!"
log_err ""
fi
/sbin/reboot >/dev/null 2>&1 || { log_err "${RED}Reboot fehlgeschlagen.${RESET}"; clean_up 3; }
clean_up 1
fi
#clean_up 1
else
# Erster Offline-Fall -> noch keine Meldung
touch "$STATE_FILE"
if [[ $IS_TTY -eq 1 ]]; then
log_info ""
log_info " ${YELLOW}${BOLD}WARN${RESET} - Interface ${IFACE} offline (das erste mal - noch keine Aktion/Meldung)."
else
log_err " ${TS} - Interface ${IFACE} offline (first time - no action started)"
fi
clean_up 0
fi