7

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?

6 Answers 6

10

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
3
  • @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, 2018 at 9:07
  • @yash another grep -v should do: ls -l /sys/class/net/ | grep -v virtual | grep -v wlan Mar 20, 2018 at 9:46
  • @Matheus Santana. Your command only works if the wlan interface has "wlan" in its name.
    – yash
    Mar 20, 2018 at 10:05
5

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
3
  • 1
    find -lname is perfect here, thanks.
    – dimo414
    Feb 20 at 18:51
  • 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 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.
    – osexp2003
    Feb 28 at 14:26
2

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}'

2
  • 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, 2019 at 6:24
  • The output of lshw may be different on an SBC, so the grep would need to be adjusted. Apr 17, 2019 at 4:31
1

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.

0

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.

0

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.