Erstellen Sie ein Array mit allen Netzwerkschnittstellen in Bash

8

Ich möchte in Bash ein Array erstellen, das alle aktiven Netzwerkschnittstellen enthält.

Ich habe es geschafft, eine for-Schleife zu erstellen, aber wenn ich versuche, das Array zu erstellen, enthält es nur die letzte loSchnittstelle, aber nicht die andere. Das ist mein Code:

#!/bin/bash

for iface in $(ifconfig | cut -d ' ' -f1| tr ':' '\n' | awk NF)
do
           printf "$iface%s\n"
           declare -a array_test=["$iface"]
done
for i in "${array_test[@]}"; do echo "$i"; done

Und das ist meine Ausgabe:

eno1
eno2
eno3
lo
[lo]

Wie kann ich auch die lo localhost-Schnittstelle vom Array ausschließen?

Georgé Stoyanov
quelle
1
@peterh bashkann für recht komplexe Skripte verwendet werden (wie z. B. kshoder zsh) .... aber je komplexer es ist, desto schwieriger ist es zu lesen, zu verstehen und zu ändern - und desto langsamer wird es (z. B. eine Schleife umher) Das Gabeln mehrerer Programme ist unglaublich langsam. Zu diesem Zeitpunkt übersteigen die Zeit- / Aufwandskosten für das Schreiben und Verwalten eines Shell-Skripts die Kosten für das Erlernen der Grundlagen awk(oder perloder oder python) und das Umschreiben in etwa 1/10 der Codezeilen erheblich . Wenn Sie bereits eine dieser Sprachen kennen, ist dieser Punkt viel früher erreicht.
Cas
Ich schreibe ein Skript, um Netzwerkstörungen mit den Befehlen iproute und tc zu emulieren. Ich habe diesen Array-Ansatz verwendet, um zu überprüfen, ob die benutzerdefinierte Variable gültig ist. Ich glaube, dieses Skript in Python zu schreiben wäre ein bisschen schmerzhaft und ich nutze auch die Gelegenheit, um ein bisschen Bash zu lernen.
Georgé Stoyanov

Antworten:

9

Hier ist eine Lösung, weisen Sie die Liste zu und fügen Sie ihr dann ein Element hinzu:

#!/bin/bash

array_test=()
for iface in $(ifconfig | cut -d ' ' -f1| tr ':' '\n' | awk NF)
do
        printf "$iface\n"
        array_test+=("$iface")
done
echo ${array_test[@]}

Wenn die Ausgabe ein Element pro Zeile anzeigen soll:

for i in "${array_test[@]}"; do echo "$i"; done

So entfernen Sie localhost aus der Ausgabe:

if [ "$iface" != "lo" ] 
then
    array_test+=("$iface")
fi
Kevin Lemaire
quelle
Wie kann ich die lolocalhost-Schnittstelle vom Array ausschließen?
Georgé Stoyanov
in Antwort und Frage hinzugefügt
Kevin Lemaire
Eigentlich können Sie das gleiche tun, indem Sie das letzte Element im Array entfernen. Ich habe in der Zwischenzeit die Antwort gefunden:unset "net_array[${#net_array[@]}-1]"
Georgé Stoyanov
1
Ich werde das nicht tun, weil ich nicht sicher bin, ob localhost immer auf der letzten Position sein wird
Kevin Lemaire
5

Mein Versuch:

readarray -t interfaces < <(ip l | awk -F ":" '/^[0-9]+:/{dev=$2 ; if ( dev !~ /^ lo$/) {print $2}}')
for i in "${interfaces[@]// /}" ; do echo "$i" ; done
Baselab
quelle
3

basherstellt ein Array aus einer durch Leerzeichen getrennten Liste (Leerzeichen, Tabulatoren, Zeilenumbrüche), die Sie ihm geben. zB array=(a b c). Wir können den Befehl substitution ( $()) verwenden, um eine solche durch Leerzeichen getrennte Liste zu generieren. Zum Beispiel:

$ ifaces=( $(ip addr list | awk -F': ' '/^[0-9]/ {print $2}') )

und drucken Sie nun das soeben erstellte Array aus:

$ declare -p ifaces
declare -a ifaces=([0]="lo" [1]="eth0" [2]="eth1" [3]="br1" [4]="br0" [5]="ppp0")

Ausschließen lo:

$ ifaces=( $(ip addr list | awk -F': ' '/^[0-9]/ && $2 != "lo" {print $2}') )
$ declare -p ifaces
declare -a ifaces=([0]="eth0" [1]="eth1" [2]="br1" [3]="br0" [4]="ppp0")

Wenn Sie wirklich ifconfigeher als verwenden möchten ip, versuchen Sie Folgendes:

ifaces=( $(ifconfig | awk -F':'  '/^[^ ]*: / && $1 != "lo" {print $1}') )
cas
quelle
2

ifconfig gibt nur die Schnittstellen aus, die aktiv sind.

Unter Linux können Sie eine Liste der Schnittstellen im /sys/class/netVerzeichnis abrufen. Mit zshkönnen Sie also Folgendes tun:

interfaces=(/sys/class/net/*(DN:t))

Ausschließen lo:

set -o extendedglob
interfaces=(/sys/class/net/^lo(DN:t))

Für nur updiejenigen, die Sie tun könnten:

interfaces=(/sys/class/net/*(DNe{'[[ $(<$REPLY/operstate) = up ]]'}:t)

oder unter der Annahme des Standardwerts von $IFS.

interfaces=($(ip -br link | LC_ALL=C awk '$2 == "UP" {print $1}'))

Auf meinem System ist zumindest der Status für loUNBEKANNT, würde also ausgeschlossen.

Dies würde auch mit bashbereitgestellten Schnittstellennamen funktionieren, die keine Platzhalterzeichen enthalten. In neueren Versionen von Linux, IIRC enthalten Schnittstellennamen garantiert keine Leerzeichen und Zeilenumbrüche (Standardeinstellung $IFS), sodass diese keine Probleme verursachen. Andere Unicode-Leerzeichen sind jedoch zulässig, daher LC_ALL = C, was garantieren sollte, dass awkdiese nicht geteilt werden.

Stéphane Chazelas
quelle
1

Wenn Sie '-j' für ip(json-Ausgabe) unterstützen, verwenden Sie das hervorragende jq Dienstprogramm.

# ip -j addr show | jq -r .[].ifname
lo
eth0
eth1
tunl0
gre0
gretap0
erspan0
ip_vti0
ip6_vti0
sit0
ip6tnl0
ip6gre0
dummy0
kube-ipvs0
cbr0
vethfbcab624

(Beispiel von einem Kubernetes-Knoten)

lgekman
quelle
Tippfehler; soll "ip -j link show" sein
lgekman