382 lines
12 KiB
Bash
382 lines
12 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
# Script Name: dockernet-inspector.v1.sh
|
|
# Beschreibung: Dockernet Inspector - Verwaltet und inspiziert Docker-Netzwerke
|
|
# - Alle Netzwerke auflisten
|
|
# - Details zu einem spezifischen Docker-Netzwerk anzeigen
|
|
# - Belegte IPs je Netzwerk und netzwerkuebergreifend ausgeben
|
|
# Verwendung: bash ./dockernet-inspector.v1.sh [BEFEHL] [OPTIONS]
|
|
# Befehle:
|
|
# networks - Alle Docker Netzwerke auflisten
|
|
# inspect - Details zu einem Netzwerk anzeigen (Standard)
|
|
# ips - Belegte IPs in einem Netzwerk
|
|
# ips-all - Belegte IPs in allen Netzwerken
|
|
# help, -h, --help - Diese Hilfe anzeigen
|
|
# Autor: Patrick Asmus
|
|
# Web: https://www.cleveradmin.de
|
|
# Git-Reposit.: https://git.techniverse.net/scriptos/dockernet-inspector.git
|
|
# Version: 1.4.0
|
|
# Datum: 22.03.2026
|
|
# Modifikation: Netzwerk loeschen Funktion hinzugefügt (nur unbenutzte Netzwerke)
|
|
#####################################################
|
|
|
|
set -uo pipefail
|
|
|
|
TABLE_LINE_WIDTH=80
|
|
INTERACTIVE_MODE=false
|
|
|
|
print_rule() {
|
|
local char="$1"
|
|
printf '%*s\n' "$TABLE_LINE_WIDTH" '' | tr ' ' "$char"
|
|
}
|
|
|
|
print_table_title() {
|
|
local title="$1"
|
|
echo "$title"
|
|
print_rule "="
|
|
}
|
|
|
|
# Hilfe-Funktion
|
|
show_help() {
|
|
cat <<HELP
|
|
Dockernet Inspector v1.2.0 - Docker Netzwerk Verwaltungstool
|
|
|
|
VERWENDUNG:
|
|
$0 - Interaktiver Modus (Menü)
|
|
$0 networks - Alle Docker Netzwerke auflisten
|
|
$0 inspect <netzwerk> - Details zu einem Netzwerk anzeigen
|
|
$0 ips <netzwerk> - Belegte IPs in einem Netzwerk anzeigen
|
|
$0 ips-all - Belegte IPs in allen Netzwerken anzeigen
|
|
$0 <netzwerk> - Alias fuer 'inspect <netzwerk>'
|
|
$0 help - Diese Hilfe anzeigen
|
|
|
|
BEFEHLE:
|
|
networks Listet alle verfuegbaren Docker Netzwerke auf
|
|
ips <netzwerk> Zeigt Containername und IPv4-Adresse im angegebenen Netzwerk
|
|
ips-all Zeigt alle belegten IPv4-Adressen in allen Netzwerken (aufsteigend)
|
|
inspect <netzwerk> Zeigt detaillierte Informationen zu einem Netzwerk:
|
|
- Netzwerktyp (Driver)
|
|
- Bridge-Interface
|
|
- Subnetz und Gateway
|
|
- Interface-Status
|
|
- Netzwerk-Statistiken (RX/TX bytes und packets)
|
|
help Zeigt diese Hilfe an
|
|
|
|
BEISPIELE:
|
|
$0 networks
|
|
$0 ips mynetwork
|
|
$0 ips-all
|
|
$0 inspect mynetwork
|
|
$0 mynetwork
|
|
$0 -h
|
|
|
|
HELP
|
|
}
|
|
|
|
# Funktion zum Auflisten aller Docker Netzwerke
|
|
list_networks() {
|
|
local table_output header
|
|
|
|
print_table_title "Verfuegbare Docker Netzwerke:"
|
|
table_output="$(docker network ls --format "table {{.ID}}\t{{.Name}}\t{{.Driver}}\t{{.Scope}}")" || {
|
|
echo "Fehler: Docker Netzwerke konnten nicht abgerufen werden."
|
|
exit 2
|
|
}
|
|
|
|
header="$(printf "%s\n" "$table_output" | head -n 1)"
|
|
printf "%s\n" "$header"
|
|
print_rule "-"
|
|
printf "%s\n" "$table_output" | tail -n +2
|
|
}
|
|
|
|
print_dynamic_table() {
|
|
local data="$1"
|
|
local formatted
|
|
local header
|
|
|
|
if command -v column >/dev/null 2>&1; then
|
|
formatted="$(printf "%b" "$data" | column -t -s $'\t')"
|
|
else
|
|
formatted="$(printf "%b" "$data")"
|
|
fi
|
|
|
|
header="$(printf "%s\n" "$formatted" | head -n 1)"
|
|
printf "%s\n" "$header"
|
|
print_rule "-"
|
|
printf "%s\n" "$formatted" | tail -n +2
|
|
}
|
|
|
|
list_ips_in_network() {
|
|
local net="$1"
|
|
local rows table_data
|
|
|
|
rows="$(docker network inspect "$net" --format '{{range $id, $c := .Containers}}{{println $c.Name $c.IPv4Address}}{{end}}' 2>/dev/null || true)"
|
|
[[ -z "$rows" ]] && {
|
|
echo "Keine Container mit IPv4-Adresse im Netzwerk '$net' gefunden."
|
|
exit 0
|
|
}
|
|
|
|
print_table_title "Belegte IP-Adressen im Netzwerk '$net':"
|
|
table_data=$'CONTAINER\tIP\n'
|
|
while read -r cname ipcidr; do
|
|
[[ -z "${cname:-}" || -z "${ipcidr:-}" ]] && continue
|
|
table_data+="${cname}"$'\t'"${ipcidr%%/*}"$'\n'
|
|
done < <(printf "%s\n" "$rows" | sort -k2,2V)
|
|
print_dynamic_table "$table_data"
|
|
}
|
|
|
|
list_ips_all_networks() {
|
|
local nets rows table_data
|
|
rows=""
|
|
|
|
nets="$(docker network ls --format '{{.Name}}' 2>/dev/null || true)"
|
|
[[ -z "$nets" ]] && {
|
|
echo "Fehler: Docker Netzwerke konnten nicht abgerufen werden."
|
|
exit 2
|
|
}
|
|
|
|
while read -r net; do
|
|
[[ -z "${net:-}" ]] && continue
|
|
while read -r cname ipcidr; do
|
|
[[ -z "${cname:-}" || -z "${ipcidr:-}" ]] && continue
|
|
rows+="${net}"$'\t'"${cname}"$'\t'"${ipcidr%%/*}"$'\n'
|
|
done < <(docker network inspect "$net" --format '{{range $id, $c := .Containers}}{{println $c.Name $c.IPv4Address}}{{end}}' 2>/dev/null || true)
|
|
done < <(printf "%s\n" "$nets")
|
|
|
|
[[ -z "$rows" ]] && {
|
|
echo "Keine belegten IPv4-Adressen in Docker Netzwerken gefunden."
|
|
exit 0
|
|
}
|
|
|
|
print_table_title "Belegte IP-Adressen in allen Netzwerken (aufsteigend):"
|
|
table_data=$'NETZWERK\tCONTAINER\tIP\n'
|
|
while IFS=$'\t' read -r net cname ip; do
|
|
[[ -z "${net:-}" || -z "${cname:-}" || -z "${ip:-}" ]] && continue
|
|
table_data+="${net}"$'\t'"${cname}"$'\t'"${ip}"$'\n'
|
|
done < <(printf "%s" "$rows" | sort -t $'\t' -k3,3V -k1,1 -k2,2)
|
|
print_dynamic_table "$table_data"
|
|
}
|
|
|
|
# Funktion zum Loeschen eines unbenutzten Netzwerks
|
|
delete_network() {
|
|
local nets net container_count
|
|
|
|
nets="$(docker network ls --format '{{.Name}}' 2>/dev/null || true)"
|
|
if [[ -z "$nets" ]]; then
|
|
echo "Fehler: Keine Docker Netzwerke gefunden."
|
|
return 1
|
|
fi
|
|
|
|
echo "Verfuegbare Netzwerke:"
|
|
select net in $nets; do
|
|
if [[ -n "$net" ]]; then
|
|
# Standardnetzwerke schuetzen
|
|
if [[ "$net" == "bridge" || "$net" == "host" || "$net" == "none" ]]; then
|
|
echo "FEHLER: Das Standard-Netzwerk '$net' kann nicht geloescht werden."
|
|
return 1
|
|
fi
|
|
|
|
# Pruefen ob Container das Netzwerk verwenden
|
|
container_count="$(docker network inspect "$net" --format '{{len .Containers}}' 2>/dev/null || echo 0)"
|
|
if [[ "$container_count" -gt 0 ]]; then
|
|
echo "FEHLER: Das Netzwerk '$net' wird aktuell von $container_count Container(n) verwendet und kann nicht geloescht werden."
|
|
echo ""
|
|
echo "Verbundene Container:"
|
|
docker network inspect "$net" --format '{{range $id, $c := .Containers}} - {{$c.Name}} ({{$c.IPv4Address}}){{println}}{{end}}' 2>/dev/null
|
|
return 1
|
|
fi
|
|
|
|
# Sicherheitsabfrage
|
|
read -p "Soll das Netzwerk '$net' wirklich geloescht werden? (j/N): " confirm
|
|
if [[ "$confirm" == "j" || "$confirm" == "J" ]]; then
|
|
if docker network rm "$net" >/dev/null 2>&1; then
|
|
echo "Netzwerk '$net' wurde erfolgreich geloescht."
|
|
else
|
|
echo "FEHLER: Netzwerk '$net' konnte nicht geloescht werden."
|
|
return 1
|
|
fi
|
|
else
|
|
echo "Loeschvorgang abgebrochen."
|
|
fi
|
|
return 0
|
|
else
|
|
echo "Ungueltige Auswahl. Bitte versuchen Sie es erneut."
|
|
fi
|
|
done
|
|
}
|
|
|
|
# Interaktive Menü-Funktion
|
|
interactive_menu() {
|
|
while true; do
|
|
echo ""
|
|
print_rule "="
|
|
echo "Dockernet Inspector - Interaktives Menü"
|
|
print_rule "="
|
|
echo ""
|
|
echo "1. Alle Netzwerke auflisten"
|
|
echo "2. Detaillierte Infos zu einem Netzwerk"
|
|
echo "3. IPs eines Netzwerks anzeigen"
|
|
echo "4. Alle belegten IPs anzeigen"
|
|
echo "5. Netzwerk loeschen"
|
|
echo "0. Beenden"
|
|
echo ""
|
|
read -p "Bitte waehlen Sie eine Option (0-5): " choice
|
|
echo ""
|
|
|
|
case "$choice" in
|
|
1)
|
|
list_networks
|
|
;;
|
|
2)
|
|
if select_and_inspect_network; then
|
|
:
|
|
fi
|
|
;;
|
|
3)
|
|
nets="$(docker network ls --format '{{.Name}}' 2>/dev/null || true)"
|
|
if [[ -z "$nets" ]]; then
|
|
echo "Fehler: Keine Docker Netzwerke gefunden."
|
|
continue
|
|
fi
|
|
|
|
echo "Verfuegbare Netzwerke:"
|
|
select net in $nets; do
|
|
if [[ -n "$net" ]]; then
|
|
list_ips_in_network "$net"
|
|
break
|
|
else
|
|
echo "Ungueltige Auswahl. Bitte versuchen Sie es erneut."
|
|
fi
|
|
done
|
|
;;
|
|
4)
|
|
list_ips_all_networks
|
|
;;
|
|
5)
|
|
delete_network
|
|
;;
|
|
0)
|
|
echo "Auf Wiedersehen!"
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "FEHLER: Ungueltige Eingabe '$choice'. Bitte geben Sie eine Nummer zwischen 0 und 5 ein."
|
|
sleep 1
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
# Funktion zur Auswahl und Inspektion eines Netzwerks
|
|
select_and_inspect_network() {
|
|
local nets net
|
|
|
|
nets="$(docker network ls --format '{{.Name}}' 2>/dev/null || true)"
|
|
if [[ -z "$nets" ]]; then
|
|
echo "Fehler: Keine Docker Netzwerke gefunden."
|
|
return 1
|
|
fi
|
|
|
|
echo "Verfuegbare Netzwerke:"
|
|
select net in $nets; do
|
|
if [[ -n "$net" ]]; then
|
|
NET="$net"
|
|
inspect_network "$NET"
|
|
return 0
|
|
else
|
|
echo "Ungueltige Auswahl. Bitte versuchen Sie es erneut."
|
|
fi
|
|
done
|
|
}
|
|
|
|
# Separate Funktion fuer Netzwerk-Inspektion
|
|
inspect_network() {
|
|
local NET="$1"
|
|
|
|
# 1) Netzwerk-ID und Bridge-Name separat holen
|
|
local ID BR_RAW IF SUBNET GATEWAY state rxb txb rxp txp
|
|
ID="$(docker network inspect "$NET" --format '{{.Id}}' 2>/dev/null || true)"
|
|
[[ -z "$ID" ]] && { echo "Fehler: Netzwerk '$NET' nicht gefunden."; return 2; }
|
|
|
|
BR_RAW="$(docker network inspect "$NET" --format '{{index .Options "com.docker.network.bridge.name"}}' 2>/dev/null || true)"
|
|
|
|
# 2) Falls kein eigener Bridge-Name: Standardname br-<ID[:12]>
|
|
if [[ -z "$BR_RAW" || "$BR_RAW" == "<no value>" ]]; then
|
|
IF="br-${ID:0:12}"
|
|
else
|
|
IF="$BR_RAW"
|
|
fi
|
|
|
|
# 3) Subnet/Gateway
|
|
SUBNET="$(docker network inspect "$NET" --format '{{(index .IPAM.Config 0).Subnet}}' 2>/dev/null || true)"
|
|
GATEWAY="$(docker network inspect "$NET" --format '{{(index .IPAM.Config 0).Gateway}}' 2>/dev/null || true)"
|
|
|
|
# 4) Interface-Status & Stats
|
|
state="unknown"; rxb=0; txb=0; rxp=0; txp=0
|
|
if ip link show "$IF" &>/dev/null; then
|
|
state="$(cat /sys/class/net/"$IF"/operstate 2>/dev/null || echo unknown)"
|
|
rxb="$(cat /sys/class/net/"$IF"/statistics/rx_bytes 2>/dev/null || echo 0)"
|
|
txb="$(cat /sys/class/net/"$IF"/statistics/tx_bytes 2>/dev/null || echo 0)"
|
|
rxp="$(cat /sys/class/net/"$IF"/statistics/rx_packets 2>/dev/null || echo 0)"
|
|
txp="$(cat /sys/class/net/"$IF"/statistics/tx_packets 2>/dev/null || echo 0)"
|
|
else
|
|
echo "WARN: Interface $IF existiert (noch) nicht auf dem Host."
|
|
fi
|
|
|
|
echo ""
|
|
print_rule "="
|
|
echo "Detaillerte Informationen fuer Netzwerk: $NET"
|
|
print_rule "="
|
|
echo ""
|
|
cat <<OUT
|
|
Docker-Netzwerk : $NET
|
|
Driver : $(docker network inspect "$NET" --format '{{.Driver}}')
|
|
Bridge-Interface : $IF
|
|
Subnet/Gateway : ${SUBNET:--} / ${GATEWAY:--}
|
|
OperState : $state
|
|
RX bytes/packets : $rxb / $rxp
|
|
TX bytes/packets : $txb / $txp
|
|
OUT
|
|
echo ""
|
|
}
|
|
|
|
# Argument-Verarbeitung
|
|
COMMAND="${1:-}"
|
|
case "$COMMAND" in
|
|
networks)
|
|
list_networks
|
|
exit 0
|
|
;;
|
|
ips)
|
|
NET="${2:-}"
|
|
[[ -z "$NET" ]] && { echo "Fehler: Netzwerkname erforderlich. Verwendung: $0 ips <docker-network-name>"; exit 1; }
|
|
list_ips_in_network "$NET"
|
|
exit 0
|
|
;;
|
|
ips-all)
|
|
list_ips_all_networks
|
|
exit 0
|
|
;;
|
|
help | -h | --help)
|
|
show_help
|
|
exit 0
|
|
;;
|
|
inspect)
|
|
NET="${2:-}"
|
|
[[ -z "$NET" ]] && { echo "Fehler: Netzwerkname erforderlich. Verwendung: $0 inspect <docker-network-name>"; exit 1; }
|
|
inspect_network "$NET"
|
|
exit 0
|
|
;;
|
|
"")
|
|
# Starte interaktiven Modus, wenn keine Argumente uebergeben wurden
|
|
interactive_menu
|
|
exit 0
|
|
;;
|
|
*)
|
|
# Kompatibilitaet: Wenn erstes Argument kein bekannter Befehl ist, behandle es als Netzwerkname
|
|
NET="$COMMAND"
|
|
inspect_network "$NET"
|
|
exit 0
|
|
;;
|
|
esac
|