Is there a way to get only the name of physical ethernet interface(i.e not virtual ethernet interface)?
To give a bit of background, I'm trying to get a few SBCs(RPi 3) to write their IP addresses to a DataBase. But since the names of the physical ethernet interface on different SBCs is not usually same, I'm finding it hard to get their IP addresses.
One way I could think of solving this is to give all the SBCs ethernet interface a common name like eth0. But this method feels a bit clunky. So, is there any other alternative to get only the name of physical ethernet interface?
- 115
- 1
- 1
- 8
7 Answers
You can tell which interfaces are virtual via
ls -l /sys/class/net/
which gives you this output:
[root@centos7 ~]# ls -l /sys/class/net/
total 0
lrwxrwxrwx. 1 root root 0 Mar 20 08:58 ens33 -> ../../devices/pci0000:00/0000:00:11.0/0000:02:01.0/net/ens33
lrwxrwxrwx. 1 root root 0 Mar 20 08:58 lo -> ../../devices/virtual/net/lo
lrwxrwxrwx. 1 root root 0 Mar 20 08:58 virbr0 -> ../../devices/virtual/net/virbr0
lrwxrwxrwx. 1 root root 0 Mar 20 08:58 virbr0-nic -> ../../devices/virtual/net/virbr0-nic
From there, you could grep to filter only non-virtual interfaces:
ls -l /sys/class/net/ | grep -v virtual
Another option is to use this small script, adapted from this answer, which prints the name of all interfaces which do not have a MAC address of 00:00:00:00:00:00 i.e. physical:
#!/bin/bash
for i in $(ip -o link show | awk -F': ' '{print $2}')
do
mac=$(ethtool -P $i)
[[ $mac != *"00:00:00:00:00:00"* ]] && echo "$i"
done
- 28,763
- 21
- 89
- 133
-
@dr01.Thanks! I think there is a problem with the script though.Its including the virtual interfaces but excludes the loopback. But the command "ls -l /sys/class/net/ | grep -v virtual" works . And how can wlan interface be excluded as well? – yash Mar 20 '18 at 09:07
-
@yash another `grep -v` should do: `ls -l /sys/class/net/ | grep -v virtual | grep -v wlan` – Matheus Santana Mar 20 '18 at 09:46
-
@Matheus Santana. Your command only works if the wlan interface has "wlan" in its name. – yash Mar 20 '18 at 10:05
Inspired by an existing answer, which names the useful /sys/class/net directory and the admonition to not use ls and my need to only see the name and not surrounding material, I came up with the following single command:
find /sys/class/net -mindepth 1 -maxdepth 1 -lname '*virtual*' -prune -o -printf '%f\n'
This gives you a listing of all non-loopback and non-virtual interfaces:
$ find /sys/class/net -mindepth 1 -maxdepth 1 -lname '*virtual*' -prune -o -printf '%f\n'
eth1
eth0
- 71
- 1
- 1
-
1
-
I went with `find /sys/class/net -type l -not -lname '*virtual*' -printf '%f\n'` which is a bit shorter and seems to work the same. Are you aware of situations where there would be more contents under `/sys/class/net` that would make that slower and/or wrong? – dimo414 Feb 20 '22 at 19:18
-
`-type l` is necessary, because when there are some bonding devices, there will be a file (not symlink) under the `/sys/class/net`, such as `/sys/class/net/bonding_masters`. Hope this can make this script more reliable. – osexp2000 Feb 28 '22 at 14:26
This will give you the name of one physical device. I think the awk wouldn't work right for multiple devices. However, take off the awk and you'd get a list of all the physical names.
lshw -class network | grep -A 1 "bus info" | grep name | awk -F': ' '{print $2}'
- 31
- 3
-
The command works fine on my system, but interestingly it doesn't work on an SBC. The output is blank whether I use "sudo" or not. – yash Mar 14 '19 at 06:24
-
The output of lshw may be different on an SBC, so the grep would need to be adjusted. – Spellinator Apr 17 '19 at 04:31
I have used the following to get it in python.
#!/usr/bin/env python3
from os import listdir
from os.path import islink, realpath, join
interfaces = [i for i in listdir("/sys/class/net") if islink(join("/sys/class/net", i))]
interfaces = [i for i in interfaces if not realpath(join("/sys/class/net", i)).startswith(("/sys/devices/virtual", "/sys/devices/vif"))]
print("Physical interfaces:", interfaces)
Prints the following in my case:
Physical interfaces: ['enp3s0']
Take a note that virtual network devices are not always are found by path "/sys/devices/virtual". For example, on Xen nodes, there are also devices such as "devices/vif-1-0/net/vif1.0", so I also excluded them.
- 767
- 7
- 24
We need a "clean list of interfaces" that doesn't have the loopback.
I came up with two ways I thought were "okay".
find /sys/class/net -type l -execdir basename '{}' ';' | grep -v "^lo$"
(explanation: find all the actual devices udev made a symlink for and get the "basename" which is the filename and interface name | get rid of any line that is exactly "lo")
!!! don't use "ls" in bash scripts
And
arp | awk '{ if ( NR > 1 ) { print } }' | awk '{print $5}' | sed '/^$/d'| sort -u
(explanation: gimme the arp table info | don't print if line 1, which are arp table headers | only print the fifth column | delete empty lines | aphabetize and remove duplicates)
With the arp command, you can specify "ethernet" devices.
arp -t ether
I am not sure if that gets rid of the "virtual devices". It for sure includes my wifi network interface. With a "clean list" of names, you can plug them into most other commands and test for the MAC address of all zeroes or a virtual attribute...
I saw a lot of answers parsing "ls". Really shouldn't do that. Good chance network interfaces are not named in ways that break stuff the usual way (i.e. spaces, newlines, other weird characters...). Also, find, arp, awk, sed, and sort are generally on every linux device already.
I only tested my commands on my Kubuntu laptop. Nobody is paying me so, that is all I have time for today. I also needed to get the name of my network interfaces and I'll be using the arp one on my instances that don't know their single network device as well as their whole existance is entirely abstracted.
- 196
- 1
- 4
You can also use below to get the physical interface.
ip r | grep default | awk '/default/ {print $5}'
It basically fetch the interface name from route show output.
- 1,009
- 2
- 13
- 20
ls -l /sys/class/net/ | awk '$NF~/\/devices\/(platform|pci)/{print $9}'
support for busybox
- 121
- 3