check_inet_iface_curl.sh,check_inet_iface_ping.sh: Redesign: add support fpr restart service and reboot system.

This commit is contained in:
2026-01-14 09:43:46 +01:00
parent daeb0c9fc4
commit d74bff9960
2 changed files with 462 additions and 96 deletions

View File

@@ -1,66 +1,251 @@
#!/usr/bin/env bash
# Prüft ein Interface gegen drei Internet-Ziele.
# Es wird nur dann ein Fehler gemeldet, wenn alle drei Ziele nicht erreichbar sind.
# Zudem erfolgt die Meldung erst beim zweiten aufeinanderfolgenden Offline-Test.
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.
#
# Aufruf: check_inet_iface.sh <interface>
# Usage:
# check_inet_iface_curl.sh <interface> [--service NAME | --reboot] [--state-dir DIR]
# [--max-time SEC] [-h|--help]
IFACE="$1"
IFACE="${1:-}"
shift || true
# Drei Ziele, beliebig anpassbar (IPs oder Hostnames)
TARGETS=("1.1.1.1" "8.8.8.8" "www.debian.org" "oopen.de")
# Ziele - echte TCP/HTTPS-Tests
TARGETS=(
"oopen.de"
"1.1.1.1"
"8.8.8.8"
"www.debian.org"
)
PING_BIN="/bin/ping"
TIMEOUT_BIN="/usr/bin/timeout"
DATE_BIN="/bin/date"
PING_BIN="$(command -v ping)"
DATE_BIN="$(command -v date)"
TIMEOUT_BIN="$(command -v timeout)"
STATE_DIR="/var/run/check_inet"
STATE_FILE="$STATE_DIR/$IFACE.fail"
STATE_DIR="/run/check_inet"
MAX_TIME=8
SERVICE=""
DO_REBOOT=0
mkdir -p "$STATE_DIR"
# terminal detection
IS_TTY=0
if [[ -t 1 || -t 2 ]]; then IS_TTY=1; fi
if [ -z "$IFACE" ]; then
echo "Usage: $0 <interface>" >&2
exit 2
# 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
# ----------------------------------------------------------
# Funktion: Teste ein Ziel über das Interface
# ----------------------------------------------------------
test_target() {
local target="$1"
$TIMEOUT_BIN 10 $PING_BIN -I "$IFACE" -c 2 -W 2 "$target" >/dev/null 2>&1
return $?
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
}
# ----------------------------------------------------------
# Alle drei Ziele testen
# ----------------------------------------------------------
clean_up() {
FAILED=0
# Perform program exit housekeeping
blank_line
exit $1
}
for TG in "${TARGETS[@]}"; do
test_target "$TG"
if [ $? -ne 0 ]; then
FAILED=$((FAILED + 1))
fi
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
# Wenn mindestens ein Ziel erreichbar ist → online
if [ $FAILED -lt 3 ]; then
# Erfolg: State zurücksetzen
[ -f "$STATE_FILE" ] && rm -f "$STATE_FILE"
exit 0
if [[ -z "$IFACE" ]]; then
usage >&2
clean_up 2
fi
# Wenn alle Ziele fehlschlagen → offline
if [ -f "$STATE_FILE" ]; then
# Zweiter Fehlschlag → Meldung
TS="$($DATE_BIN '+%F %T')"
echo "$TS - Interface $IFACE: Internet nicht erreichbar (Targets: ${TARGETS[*]})!" >&2
exit 1
else
# Erster Fehlschlag - Still, aber State setzen
touch "$STATE_FILE"
exit 0
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"
$TIMEOUT_BIN $MAX_TIME $PING_BIN -I "$IFACE" -c 2 -W 2 "$target" >/dev/null 2>&1
}
# ------------------------------------------
# Tests
# ------------------------------------------
TOTAL="${#TARGETS[@]}"
FAILED=0
blank_line || true
log_info " Interface: \033[17G$IFACE"
log_info " Targets (${TOTAL}):\033[17G${TARGETS[*]}"
log_info " ping:\033[17G$PING_BIN timeout: ${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}: PING 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