I Need Help Getting Interface Names and IP

I have fun into a small issue. I need to get the Network Interface name and IP associated with it.

So far I have to lines of code that almost work:

ip a | awk 'BEGIN{ "hostname -I|cut -d\" \" -f 1" | getline ip} $2 ~ ip {print "Device: "$NF "  IP: "$2}'

and

ifconfig | awk '{ print $2}' | grep -v 127.0.0.1 | grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}"

What I want is something such as:

eth0 192.168.2.41
wlan0 192.168.2.118
wlan1 192.168.2.119

So, can any of you linux gurus help me?

sure, that exact format or would you like something you can parse easier with JS or the like ?

1 Like

The output will be used in a Bash script to set up the RPi as an acess point.

Maybe something like (according to stackoverflow)

ip r show|grep " src "|cut -d " " -f 3,12

1 Like

ipv4 only, or ipv6 too, or either, or both ?

2 Likes

Close but the wrong IP on the wlan interfaces

ipv4 only at this time.

ok let me poke around some old code. The main problem is you can’t predict what crazy stuff people have done with multiple interfaces up, or bonding multiple nics, or whether wifi is up if wired is also up, so there are lots of edge cases.

It’s a pi so we can assume python is there as well if awk gets too painful. Gimme an hour.

1 Like

This is what I want:

ip r show|grep " scope "|cut -d " " -f 3,9

eth0 192.168.2.41
wlan1 192.168.2.118
wlan0 192.168.2.120
wlan2 192.168.2.119

Thank you!

I wouldn’t assume you always have a route for each interface.

Try the following just for grins to see if you get the same answers from ‘ip addr’…


# example derived from 'Jotne' answer in https://stackoverflow.com/questions/21336126/linux-bash-script-to-extract-ip-address

my_ip=$(ip addr | grep -v "::" | grep -v "127.0.0.1" | sed -e s:/:\ : | grep scope | awk '{print $2}')
my_if=$(ip addr | grep -v "::" | grep -v "127.0.0.1" | sed -e s:/:\ : | grep scope | awk '{print $8}')

echo "# ---- from 'ip addr' ---"
echo $my_if $my_ip

Works for a one-nic up system, either wifi or ethernet. Guessing it needs some tweaks to handle multiple live interfaces at a time.

1 Like

That will work also. I’ll work on the script and test both methods.

Thank you.

Incidentally, I stumbled across a cool one in researching this. Try “hostname -I” on your system. It reports all the ip addresses you have currently.

That might be the starters for a loop where you’d first get the ip addresses active and then map them to their interfaces. But for what you’re trying to do, maybe you’d need the opposite. I dunno.

But just in case, here’s an example from a 2-nic debian system so a Raspbian pi should look the same if it had multiple NICs up…

vagrant@stretch64pkg:~$ hostname -I
10.0.2.15 192.168.33.24

vagrant@stretch64pkg:~$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:8d:c0:4d brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:fe8d:c04d/64 scope link
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:f0:1d:0d brd ff:ff:ff:ff:ff:ff
    inet 192.168.33.24/24 brd 192.168.33.255 scope global eth1
       valid_lft forever preferred_lft forever

vagrant@stretch64pkg:~$ ip r
default via 10.0.2.2 dev eth0
10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15
192.168.33.0/24 dev eth1 proto kernel scope link src 192.168.33.24

1 Like

Just as a caution, Linux has been moving away from eth# as the name for network interfaces, using some long name instead. The first release of Raspbian Stretch made the switch, and they subsequently backed it out in a later update because it broke too many scripts. Just saying don’t hard-code the interface based on eth#, so you’re not a victim when the interface name format changes…

1 Like

Yes, they have started going to what they call “Predictable Interface Names.”

Chatter on the Internet is that many don’t understand the and many more don’t like it. Fortunately there is a method to force the simple names.

This is what I ended up with and I think will work out well.

bash -e <(wget -qO - http://fsoft.com/archivesw/script/test.sh)

my_ifip=$(ip addr | grep -v "::" | grep -v "127.0.0.1" | sed -e s:/:\ : | grep scope | awk '{print $8 ":" $2}')
varIF=${my_ifip}
echo ""
for i in "${varIF[@]}"
do
   echo "$i"
done
echo ""

And this is even cleaner:

varA=$(ip route|grep " scope "|cut -d " " -f 3,9)
echo "$varA"

Discussion and transition has been going on for a decade+ now. Drives old school people like me crazy. Just ignore the device names and go with whatever the local system has, predictable or not.

(there was one kernel change years ago when my eth0 and eth1 allocations flipped on embedded systems that were already wired into large flying things that we couldn’t simply rewire to match the hardware when the software flipped its brain 180 degrees. Fortunately we had the ‘nameif’ command back then and could reverse the software naming to the old behavior.)

2 Likes

The first one with the loop blows up if you call it with ‘sh’ so be sure to call it with bash specifically (which works).

The second one seems to work ok when called as a script, but sometimes doesn’t give you the line feed between lines when called interactively from a bash session. You also need to properly quote your variables.

Try it like this one one line:

varA=$(ip route|grep " scope "|cut -d " " -f 3,9) ; echo "${varA}"

Both variants fail differently if you have multiple ip addresses on one interface. That’s used pretty rarely, but it happens. Your first example gets pretty confused, it finds the second address but loses track of the NIC name. The second example just reports the first address for that device and ignores the second one. Just thought I’d mention it.

To add ip addresses to an interface just do:

ip addr add 1.2.3.4 dev eth1
ip addr add 2.3.4.5 dev eth1
1 Like

This is the end result:

IFS=$’\n’

echo “”
my_ifip=$(ip addr | grep -v “::” | grep -v “127.0.0.1” | sed -e s:/:\ : | grep scope | awk ‘{ print $8 " " $2 }’)
varIF=(my_ifip) echo "{#varIF[@]} network interfaces"
for i in "{varIF[@]}" do echo {i// / = }
done

A big Thank You! to @vinceskahan and @hankster for their assistance.

1 Like

Another caution is the use of grep -v “::” to filter IPv6 addresses as written by two different people above. The :: notation is optional in an IPv6 address, and from someone living in the 21st century actually using IPv6 from their ISP I can say with authority that they are not handing out shortened addresses with :: in them to end-user devices.

Result from your first example above on Raspbian Stretch:

wlan0:192.168.1.110
dynamic:2604:2000:2642:2d00:1609:427:efb9:64d5

For those who haven’t looked into IPv6 yet, the IP address space is a /128. To shock everyone out of IPv4-think, the minimum block that ISP’s will hand out is a /64…even to a home customer! (The minimum allocation for businesses requesting their own address pool is a /48.) My cable modem on Time Warner/Spectrum will let me request a /56, which is a whole lotta /64 subnets for ethernet segmenting. The biggest mindset change from IPv4-think is that ISP’s will hand out live IPv6 addresses to every client on your internal network, so you get more than one IPv4 address and being forced to use NAT for sharing it between devices…

1 Like

I’m not worried about IPv6 since this is strictly a private network internal to the RPi. If it ever becomes an issue I will address it then.