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
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.