How to Dynamically Identify Ethernet Interface Name in Bash Scripts on Ubuntu


3 views

Modern Linux distributions like Ubuntu 16.04+ use predictable network interface names that follow the enpXsY pattern rather than the traditional eth0 naming scheme. This creates challenges for scripts that need to automatically configure network interfaces.

Here are several robust approaches to identify your wired Ethernet interface:

Method 1: Using ip Command with Filtering

#!/bin/bash
ETH_INTERFACE=$(ip -o link show | awk -F': ' '/^[0-9]+: en/ {print $2}' | grep -v lo)
echo "Ethernet interface: $ETH_INTERFACE"

Method 2: Checking sysfs for Physical Connections

#!/bin/bash
for interface in /sys/class/net/en*; do
    if [[ -d "$interface/device" ]]; then
        ETH_INTERFACE=$(basename "$interface")
        break
    fi
done
echo "Ethernet interface: $ETH_INTERFACE"

Method 3: Using udevadm for Detailed Information

#!/bin/bash
ETH_INTERFACE=$(udevadm info -e | grep -A 20 'ID_NET_DRIVER=.*' | grep -B 10 'DEVTYPE=ethernet' | head -n 1 | cut -d'/' -f5)
echo "Ethernet interface: $ETH_INTERFACE"

If your system has multiple Ethernet ports, you might want to select based on specific criteria:

#!/bin/bash
# Get first active Ethernet interface with IP address
ETH_INTERFACE=$(ip -o -4 addr show | awk -F'[ :/]+' '/en/ && !/127.0.0.1/ {print $2; exit}')
echo "Primary Ethernet interface: $ETH_INTERFACE"

Here's a complete script that configures IP address dynamically:

#!/bin/bash

# Get Ethernet interface
get_eth_interface() {
    local interface
    for interface in /sys/class/net/en*; do
        if [[ -d "$interface/device" ]]; then
            echo $(basename "$interface")
            return 0
        fi
    done
    return 1
}

ETH_INTERFACE=$(get_eth_interface) || { echo "No Ethernet interface found"; exit 1; }

# Your configuration logic here
echo "Configuring $ETH_INTERFACE..."
# ip addr add 192.168.1.100/24 dev $ETH_INTERFACE
# ip link set $ETH_INTERFACE up

For systems still using ethX naming:

#!/bin/bash
ETH_INTERFACE=$(ls /sys/class/net | grep -E '^eth[0-9]+$' | head -n 1)
[ -z "$ETH_INTERFACE" ] && ETH_INTERFACE=$(ls /sys/class/net | grep -E '^enp[0-9]+s[0-9]+$' | head -n 1)
echo "Using interface: $ETH_INTERFACE"

Always include proper error handling in production scripts:

#!/bin/bash
set -e

# Function to validate interface
validate_interface() {
    local iface=$1
    if [ ! -d "/sys/class/net/$iface" ]; then
        echo "Error: Interface $iface does not exist" >&2
        return 1
    fi
    
    if ! ip -o link show dev "$iface" | grep -q "LOWER_UP"; then
        echo "Warning: Interface $iface is not connected" >&2
    fi
    
    return 0
}

ETH_INTERFACE=$(ip -o link show | awk -F': ' '/^[0-9]+: en/ {print $2}' | head -n 1)
validate_interface "$ETH_INTERFACE" || exit 1

These methods provide reliable ways to identify Ethernet interfaces in scripts without hardcoding interface names. The best approach depends on your specific requirements and system configuration.


Traditional network interface naming (eth0, eth1) has been replaced in modern Linux distributions by predictable network interface names (like enp7s0). This change means scripts relying on hardcoded "eth0" will break on newer systems.

Here are several robust approaches to identify your wired Ethernet interface:

Method 1: Using ip and grep

# Get wired interface name
WIRED_IFACE=$(ip link show | grep -Po '^[0-9]+: \K(enp[^:]+|eth[0-9]+)' | head -1)
echo "Wired interface: $WIRED_IFACE"

Method 2: Using ls and sysfs

# Alternative method examining /sys/class/net
for iface in /sys/class/net/*; do
  if [[ $(readlink -f "$iface") == */devices/pci* ]] && \
     [[ $(<"$iface/type") -eq 1 ]]; then
    echo "Found wired interface: $(basename "$iface")"
    break
  fi
done

Method 3: Comprehensive nmcli Approach

# Using NetworkManager's CLI tool
WIRED_IFACE=$(nmcli -t -f DEVICE,TYPE dev | grep -E 'ethernet$' | cut -d: -f1)
echo "Wired interface via nmcli: $WIRED_IFACE"

For systems with multiple Ethernet ports, you might want to select the active one:

# Get first active wired interface with an IP address
ACTIVE_IFACE=$(ip -o -4 addr show | \
  awk '{print $2}' | \
  grep -E '^enp|^eth' | \
  head -1)
echo "Active wired interface: $ACTIVE_IFACE"

Here's how to modify your existing script to use dynamic detection:

#!/bin/bash

# Detect wired interface
WIRED_IFACE=$(ip link show | grep -Po '^[0-9]+: \K(enp[^:]+|eth[0-9]+)' | head -1)

if [ -z "$WIRED_IFACE" ]; then
  echo "ERROR: No wired interface found" >&2
  exit 1
fi

# Your existing configuration logic here
echo "Configuring $WIRED_IFACE..."
# ifconfig $WIRED_IFACE 192.168.1.100 netmask 255.255.255.0 up
  • They filter by interface type (Ethernet)
  • They work with both traditional (ethX) and predictable (enpXsY) naming
  • They handle cases where the interface might not be currently plugged in
  • They exclude wireless (wlan/wlp) and virtual interfaces

Verify your script works correctly by testing on different systems:

# Dry-run test
./your_script.sh
ip addr show $WIRED_IFACE