Moinsen an alle BasherInnen oder ShellscripterInnen.
Ich habe mir die letzten Tage die Finger kaputt getippt, um mir ein Bashscript zusammenzubasteln,
das mir für meine eingerichteten MACVLAN(s) Informationen bereitstellt.
Wer mag mir dabei helfen das zu optimieren und mir evtl. auch etwas über den besseren Umgang mit den einzelnen Befehlen erklären,
falls ich die nicht richtig bzw. ungünstig eingesetzt habe?
Ich danke allen vorab und total viel, dass ihr euch Zeit dafür genommen habt.
Vorab einige Informationen.
Im Einsatz ist bei mir eine Fritz!Box, die WireGuard bereitstellt, und der DHCP ist vorgesehen meine Geräte mit IP-Adressen zu versehen.
Jetzt hat WireGuard die Eigenschaft, IP-Adressen nach/hinter dem DHCP-Bereich automatisch zu vergeben.
Was zu einem Problem geführt hätte, wenn ich vorhatte eine MACVLAN hinter dem DHCP-Bereich einzurichten.
Damit hätte ich keine Kontrolle mehr über die IP-Vergabe und es wäre bestimmt zu Doppelvergaben gekommen.
Meine Lösung war dann ein neues Netzwerk in der Fritz!Box/Router einzurichten, das richtig groß ist.
Das wollte ich zwar verhindern, aber dann war alles nur noch lästig, und ein neues Netzwerk hatte dann doch gewonnen.
Das Script habe ich erst mit dem TextEdit von UGreen programmiert, und bin dann auf VSCode umgestiegen, mit SSH-Remote und jetzt geht es etwas einfacher.
Script liegt im Freigabe-Ordner docker auf dem Volume1 /volume1/docker und hat den Dateinamen: mcvlan_infos.sh
Dem musste ich dann noch die Linux-Berechtigung zur Ausführbarkeit geben: sudo chmod +x /volume1/docker/mcvlan_infos.sh
Das Script führe ich mit diesem Befehl aus: sudo /volume1/docker/mcvlan_infos.sh
Da sudo eingesetzt wird, wie immer mit Passworteingabe die Ausführung bestätigen.
Das Script
Das Script setzt diese Befehle ein:
- docker network ls --format json
Gib mir alle Docker-Netzwerke im JSON-Format. - docker network ls --filter driver=macvlan --format "{{.Name}}"
Gib mir eine gefilterte Liste der Netzwerke mit dem Driver=macvlan und nur die Docker-Netzwerk-Namen.
Diese Namensliste brauche ich, um eine Schleife über die Netzwerke einzusetzen. - jq
Verarbeitung der JSON ausgaben.
Beispiel aus dem Script: network_names_parts=$(jq -C -r '. | .Name | split(".")' <<< $(docker network ls --format json)) - echo
Ich habe viel mit Einfärbungen gearbeitet.
Beispiel aus dem Script: echo -e "° ${Blue}Networks found: ${NC} ${Yellow}$(grep -o '\]' <<< ${network_names_parts} | wc -l)${NC}" - wc
Konnte mir nicht anders helfen, um an eine Zahl zu kommen. - Für den Kontrollfluss if else for
- ipcalc
Ich dachte mir, dass Netzwertberechnungen nützlich wären,
aber der Aufwand, die selber zu programmieren, war mir zu hoch.
Beispiel aus dem Script: echo -e " > ${Blue}IPCALC for Subnet of Network${NC} ${Green}${mcvlanitem}${NC}: ${subnet}\n$(ipcalc -c ${subnet})\n"
Nicht vergessen ipcalc -c , wegen der bunten Farben.
Das Script ist auf Englisch, wieso nicht.
Hier der Quellcode im aktuellen Zustand:
#!/bin/bash
#clear
#SCRIPT_DIR=$(pwd)
unset saved_IFS
[ -n "${IFS+set}" ] && saved_IFS=$IFS
# Default POSIX $IFS should be: $' \t\n'
# $1=Space $2=Tab $3=NewLine
# if script breaks, do reset IFS.
trap "cleanup" 0 2 3 15
cleanup() {
unset IFS
[ -n "${saved_IFS+set}" ] && { IFS=$saved_IFS; unset saved_IFS; }
}
# some Colors for the WOW-Effect
Black='\e[0;30m'
Red='\e[0;31m'
Green='\e[0;32m'
Yellow='\e[0;33m'
Blue='\e[0;34m'
Purple='\e[0;35m'
Cyan='\e[0;36m'
White='\e[0;37m'
NC='\033[0m' # No Color
# for the splitting of Strings
IFS=$'\n' # split on newline
set -o noglob
# the working Magic
echo -e "° ${Blue}Scanning for Networks ...${NC}"
network_names_parts=$(jq -C -r '. | .Name | split(".")' <<< $(docker network ls --format json))
echo -e "° ${Blue}Networks found: ${NC} ${Yellow}$(grep -o '\]' <<< ${network_names_parts} | wc -l)${NC}"
echo -e "° ${network_names_parts//$'\n'/' '}"
echo -e "° ${Blue}Searching for Networks with${NC} ${GREEN}Driver=macvlan${NC} ${Blue}...${NC}"
# iterate thru the filtered Networks
macvlan_names_list=$(docker network ls --filter driver=macvlan --format "{{.Name}}")
echo -e " Found MACVLAN Networks: "$Green${#macvlan_names_list[@]}${NC}" in total"
if [[ -n ${macvlan_names_list[0]} ]]; then
echo -e " Found MACVLAN: $(printf "[ \e[0;32m\"%s\" \033[0m] " "${macvlan_names_list[@]}")"
macvlan_count=0
for mcvlanitem in ${macvlan_names_list[@]}; do
macvlan_count=$((macvlan_count+1))
# inspect the actual Item/Network
echo -e "° ${Blue}MACVLAN : ${NC}${Green}$macvlan_count.${NC} - Networkname for inspection: ${Green}${mcvlanitem}${NC}"
inspect=$(docker network inspect $mcvlanitem --format json 2>/dev/null)
# get the Pre-Configured/Templated Network-Name
configured_from=$(jq -C -r '.[].ConfigFrom.Network' <<< "${inspect}")
if [[ -n ${configured_from} ]]; then
echo -e " > The MACVLAN-Network ${Green}$mcvlanitem${NC} is configured from: ${Yellow}$configured_from${NC}"
subnet=$(jq -r '.[].IPAM.Config[0].Subnet' <<< "$inspect")
iprange=$(jq -r '.[].IPAM.Config[0].IPRange' <<< "$inspect")
enableipv6=$(jq -r '.[].EnableIPv6' <<< "$inspect")
gateway=$(jq -r '.[].IPAM.Config[0].Gateway' <<< "$inspect")
auxiliary_addresses=$(jq -r '.[].IPAM.Config[0].AuxiliaryAddresses["device0"]' <<< "$inspect") # What if: more than one Config?
options_parent=$(jq -r '.[].Options.parent' <<< "$inspect")
echo -e " \tParent NIC : ${Green}${options_parent}${NC}"
echo -e " \tEnableIPv6 : ${enableipv6}"
echo -e " \tSubnet : ${Green}${subnet}${NC}"
echo -e " \tIPRange : ${Yellow}${iprange}${NC}"
echo -e " \tGateway : ${gateway}"
echo -e " \tAuxiliary"
echo -e " \tAddresses : ${Red}${auxiliary_addresses}${NC}"
echo ""
# iterate thru the Containers in Inspect
container_count_in_macvlan=0
IFS=$'*'
containerslist=($(jq -r '.[].Containers' <<< "${inspect}" | jq -r '.[] | .[], "*"'))
for container in "${!containerslist[@]}"; do
containeritem=(${containerslist[$container]})
if [[ -n ${containeritem[0]} ]]; then
container_count_in_macvlan=$((container_count_in_macvlan+1))
container_header_string=" Container in MACVLAN: "$mcvlanitem' #'$(printf ' %-4s ' ${container_count_in_macvlan})
width=80
width_text=${#container_header_string}
container_header_first_dashes=$(printf -- '_%.0s' {1..15})
remainder_header=$((width-17-width_text))
for ((i=q;i<remainder_header;i++)) do
container_header_trailing_dashes+='_'
done
container_header_string=" Container in MACVLAN: "${Yellow}$mcvlanitem${NC}' #'${Yellow}$(printf ' %-4s ' ${container_count_in_macvlan})${NC}
echo -e "${container_header_first_dashes} ${container_header_string} ${container_header_trailing_dashes}"
#echo -e "Name : ${Green}${containeritem[0]}${NC}"
# Optimize: this is somewhat slow, maybe storing into a variable and use that over again?
container_id=$(jq -r '.[].Containers | to_entries | .['$container'] | .key' <<< "${inspect}")
container_name=$(jq -r '.[].Containers | to_entries | .['$container'] | .value | .Name' <<< "${inspect}")
container_endpointID=$(jq -r '.[].Containers | to_entries | .['$container'] | .value | .EndpointID' <<< "${inspect}")
container_macaddress=$(jq -r '.[].Containers | to_entries | .['$container'] | .value | .MacAddress' <<< "${inspect}")
container_ipv4address=$(jq -r '.[].Containers | to_entries | .['$container'] | .value | .IPv4Address' <<< "${inspect}")
container_ipv6address=$(jq -r '.[].Containers | to_entries | .['$container'] | .value | .IPv6Address' <<< "${inspect}")
# split up the Mac-Address for colorizing and such
IFS=$':'
macsplit=(${container_macaddress})
mac_A=$(printf '%5s' "${macsplit[0]}")
mac_B=$(printf '%5s' "${macsplit[1]}")
mac_C=$(printf '%5s' "${macsplit[2]}")
mac_D=$(printf '%5s' "${macsplit[3]}")
mac_E=$(printf '%5s' "${macsplit[4]}")
mac_F=$(printf '%5s' "${macsplit[5]}")
secondary_macadress_string=$Red$mac_A$mac_B$NC$Yellow$mac_C$mac_D$mac_E$mac_F$NC
# split up the IP-Address for colorizing and such
IFS=$'.'
ipv4split=(${container_ipv4address})
# split the las Octet with the CIDR to seperate the CIDR
IFS=$'/'
ipv4lastsplit=(${ipv4split[3]})
ipv4cidr=${ipv4lastsplit[1]}
IFS=$'\n'
ipv4_first_octet=$(printf '%5s' "${ipv4split[0]}")
ipv4_second_octet=$(printf '%5s' "${ipv4split[1]}")
ipv4_third_octet=$(printf '%5s' "${ipv4split[2]}")
ipv4_fourth_octet=$(printf '%5s' "${ipv4lastsplit[0]}")
secondary_ipv4_string=" "$Yellow$ipv4_first_octet$ipv4_second_octet$ipv4_third_octet$ipv4_fourth_octet$NC
primary_macaddress_string=$(printf '%-33s' "${container_macaddress}")
primary_ipv4_string=$(printf '%-33s' "${container_ipv4address}")
echo -e "Name : ${Green}${container_name}${NC}"
echo -e "ContainerID : ${Yellow}${container_id}${NC}"
echo -e "EndpointID : ${Purple}${container_endpointID}${NC}"
echo -e "MacAddress : ${primary_macaddress_string}${NC}|${secondary_macadress_string}"
echo -e "IPv4Address : ${primary_ipv4_string}${NC}|${secondary_ipv4_string}"
echo -e "IPv6Address : ${container_ipv6address}"
echo -e $(printf -- '_%.0s' {1..80})
container_header_trailing_dashes=''
fi
done
else
echo -e " > Input is wrong: The Network Name is not found by Docker."
fi
# some summary output and IPCALCing = WIP
echo -e " > ${Blue}Found Containers in${NC} ${Yellow}${mcvlanitem}${NC}: ${Green}${#containerslist[@]}${NC}"
echo -e $(printf -- '_%.0s' {1..80})
echo ""
echo -e " > ${Blue}IPCALC for Subnet of Network${NC} ${Green}${mcvlanitem}${NC}: ${subnet}\n$(ipcalc -c ${subnet})\n"
echo -e $(printf -- '_%.0s' {1..80})
echo -e " > ${Blue}IPCALC for IPRange of Network${NC} ${Green}${mcvlanitem}${NC}: ${iprange}\n$(ipcalc -c ${iprange})"
echo -e $(printf -- '_%.0s' {1..80})
done
else
echo -e " ${Cyan}No MACVLANs found.${NC}"
fi
echo ""
unset IFS
[ -n "${saved_IFS+set}" ] && { IFS=$saved_IFS; unset saved_IFS; }
Display More
Warnungen
Ich habe nach bestem gewissen gearbeitet, was das auch zu bedeuten hat.
Das Script bitte nicht einfach so einsetzen, weil könnte auch was kaputtgehen.
Bitte lest euch das Script durch, falls ihr es einsetzen wollt.
Es soll nichts ins Internet hochgeladen werden, und auch soll nichts im System aus dem Script heraus geändert werden.
Es soll nur Informationen sammeln und ausgeben.
Bitte die Informationen nicht weitergeben, die geben den Hackern aus Wanne-Eickel und Hamburg genug, um zu schaden. (Wieso Wanne-Eickel überhaupt ...)
Wo es hapert ...
Das Script und ich sind jetzt wieder Freunde, aber das war nicht immer so ...
Ich habe mich noch nicht gut genug in jq eingearbeitet, sowie sind mir die Bash-Script Eigenheiten noch nicht geläufig.
Ich habe mir überlegt, die einzelnen Umformatierungen und Einfärbungen in Funktionen/Methoden auszulagern.
Mir ist es einfach nicht gelungen, die Container in ein Array zu überführen, um damit einfacher zu arbeiten.
Dieser Bereich ist sehr langsam in der Ausführung, weil Wiederholungen?
#!/bin/bash
container_id=$(jq -r '.[].Containers | to_entries | .['$container'] | .key' <<< "${inspect}")
container_name=$(jq -r '.[].Containers | to_entries | .['$container'] | .value | .Name' <<< "${inspect}")
container_endpointID=$(jq -r '.[].Containers | to_entries | .['$container'] | .value | .EndpointID' <<< "${inspect}")
container_macaddress=$(jq -r '.[].Containers | to_entries | .['$container'] | .value | .MacAddress' <<< "${inspect}")
container_ipv4address=$(jq -r '.[].Containers | to_entries | .['$container'] | .value | .IPv4Address' <<< "${inspect}")
container_ipv6address=$(jq -r '.[].Containers | to_entries | .['$container'] | .value | .IPv6Address' <<< "${inspect}")
Etwaige Fehlerbehandlung ist mir nur so nebenbei eingefallen. Sollte wohl eingeplant und verbessert werden ...
Das mit dem wc ist mir nicht geheuer, aber es geht auch.
Wie mit dem Script im Forum umgehen?
Ich habe keine Ahnung, wie mir die HelferInnen Verbesserungen und Vorschläge mitteilen können.
Einfach hier Antworten oder per Private-Message?
Nur mal so am Rande, wenn mein PM-Postfach überquillt, dann gebe ich mir nicht die Schuld. Wie immer ...
Ich schlage vor, es mit direkten Antworten hier im Post.
Abschlussbemerkungen
So, bis hier ist erstmal alles gut gegangen, und ihr habt euch wirklich ein Fleißsternchen verdient. ![]()
Ich danke für eure Zeit und Geduld und wünsche viel Spaß mit dem Script und bitte fühlt euch nicht gedrängt hier mitzuarbeiten.
Wenn das Script soweit allgemeingültig ist, möchte ich es im Upload veröffentlichen.
Dann soll die Datei macvlan_infos.sh heißen. Also die Beta-Version ist mcvlan_infos.sh.
Die Kommentare sollen nachher alle bereinigt werden. Wer will schon meine Schimpfworte mitlesen?
Liebe Grüße aus Hamburg und Tüdülüüü ![]()