Bash – Create map network_iface_name <--> IPv4 address

bashipnetwork-interfacenetworking

I'd like to implement a bash script that creates a mapping between the network cards (or interfaces) names in my computer and their IP address (in CIDR format, if possible).

The goal is having something like an associative array, or a file looking like:

lo: "127.0.0.1/8"
eth0: "192.168.1.123/24"
br-priv: ""      # <-- No IP assigned
wlan0: "10.42.0.10/24"

I have the ifconfig and the ip commands available, but the parsing of their outputs is a bit tricky, because the IP address and the interface's name don't appear in the same line so I would have to find the interface IP address and then rollback to find the network's name, or viceversa.

Is there any other way to find my interfaces IP addresses?

I have all the interfaces names (as directory names) under /sys/class/net/

root@borrajax:~# ls /sys/class/net/
br-priv/   eth0/    lo/    mon0/   wlan0/

But I haven't been able to find their IP in those directories. Doing that would be great, because I could just walk the directory, retrieve the directory's name and then read the IP from some other file.

This is intended to run in an embedded system running OpenWRT, but a solution for a Debian based system might be suitable. My bash's version is 4.2.28, just in case.

Best Answer

Use the "-o" option of ip:

ip  -o addr  | sed -e 's/^[0-9]: \([^ ]*\).*inet \([^ \t]*\).*/\1: "\2"/;t;s/^[0-9]*: \([^ :]*\).*/\1: ""/g' | sort -r | sort -u -t: -k1,1

Output should be then in your case:

br-priv: "" 
eth0: "192.168.1.123/24"
lo: "127.0.0.1/8"
wlan0: "10.42.0.10/24"

The command prints only one IPv4 per network device (it is possible to configure multiple IP addresses at the same interface).


Explanations:

The sed expression

s/^[0-9]: \([^ ]*\).*inet \([^ \t]*\).*/\1: "\2"/;

replaces 1: lo inet 127.0.0.1/8 brd 255 [...] with lo: "127.0.0.1/8"

t;

jump to end if this could be done (=an IPv4 address was found), otherwise:

s/^[0-9]*: \([^ :]*\).*/\1: ""/

replace lines without IPv4-addresses e.g. 1: lo inet6 ::1/128 [...] with lo: "".

All lines are automatically printed out (no -n flag).

The command sort -r sorts now the line reverse. The lines with IPv4-addresses (e.g. lo: "127.0.0.1/8") are then in all cases before the lines without (lo: "").

The command sort -u -t: -k1,1 applies unique sorting to the first field (the interface names, separator is set to :). In our example only the "lo: "127.0.0.1/8" line survive as it comes first (due to the previous sorting).

Related Question