artfulrobot
artfulrobot

Reputation: 21397

How to find network interface name

I have a bash script that runs on a variety of different Ubuntu Linux machines. Its job is to find out the LAN IPv4 address of the localhost.

The script is using

ip addr show eth0 | sed -n '/inet /{s/^.*inet \([0-9.]\+\).*$/\1/;p}'

which is fine, but some machines for some reason use eth1 instead of eth0. I would like to be able to discover the LAN iface name, so I can substitute it in here instead of eth0.

Of course, if you can come up with a different oneliner that does the same thing, all good.

Upvotes: 18

Views: 62353

Answers (7)

David W.
David W.

Reputation: 107040

Believe it or not, there is no standard, easy way to get this information. There is no standard give me the current IP and Interface Name command. There isn't even a standard format for the information returned by ifconfig.

I was going to recommend forgoing pure shell and go with a scripting language like Python where you can do this:

import socket
socket.gethostbyname(socket.gethostname())

Except it doesn't work on most Linux systems because there's usually an entry in the /etc/host file pointing to 127.0.0.1, the loopback address. Perl has the same issues.

You have a firm grasp on the scripting involved, and you've seen the issues. The only thing I can recommend is to test this on each machine you're going to run it on, and see what pops out. There isn't going to be a general purpose one liner that works with all operating systems, or even with different systems on the same operating system because of the way the network is setup and the way interfaces may be named by each location.

Upvotes: 3

user150471
user150471

Reputation: 391

The main NIC will usually have a default route. So:

ip -o -4 route show to default

The NIC:

ip -o -4 route show to default | awk '{print $5}'

The gateway:

ip -o -4 route show to default | awk '{print $3}'

Unlike ifconfig, ip has a consistent & parsable output. It only works on Linux; it won't work on other Unixen.

Upvotes: 29

r00txs
r00txs

Reputation: 61

Most recenttly systemd/udev has automatically started to assign interface names for all local Ethernet, WLAN and WWAN interfaces to something that we're all accustomed to . This is a departure from the traditional interface naming scheme ("eth0", "eth1", "wlan0", ...) .. now we have to check first what the local interface name is before we can use it while previously we it was a pretty accurate guess that "eth0" was the right name. What you're asking for is the network NAME .. Here's a small script to solve the problem

  1. Use "ip route get 8.8.8.8 " to figure out which ACTIVE interface has the route to internet ( or currently being used ) Output should look like :

    8.8.4.4 via 10.10.1.1 dev enp0s3 src 10.10.1.118 cache

  2. Use awk to print the 5th text block for Interface NAME

    ]# ip route get 8.8.8.8 | awk -- '{print $5}' Output : enp0s3

  3. Use awk to print the 7th text block for Interface Address

    ]# ip route get 8.8.8.8 | awk -- '{print $7}' Output : 10.10.1.118

Upvotes: 6

gatoatigrado
gatoatigrado

Reputation: 16850

Not sure if this helps, but it seems that ip route get will show which interface it uses to connect to a remote host.

ubuntu@ip-10-40-24-21:/nail/srv/elasticsearch$ ip route get 8.8.8.8
8.8.8.8 via <gateway address> dev eth0  src <eth0 IP Address>

of course you could automate that in shell script with something like,

ip route get 8.8.8.8 | awk '{ print $NF; exit }'

Upvotes: 15

Neolo
Neolo

Reputation: 61

1) This one print only interface names (I needed that for handing upcoming and downcoming PPP links):

for i in $( ifconfig | grep 'ppp' | awk '{print $1}' );
do

printf "$i "; ## Or echo

done

Result:

ppp0 ppp1 ppp2

2) This one prints interface names and IP

declare -a IPADDR

index=0

for i in $( ifconfig | grep 'inet addr' | awk '{print $2}'| sed 's#addr:##g' );
do
        IPADDR[$index]=$i
        let "index += 1"
done

index=0

for i in $( ifconfig | grep 'ppp' | awk '{print $1}' );
do
        echo $i 
        let "index += 1"
done

Result:

ppp0 addr:IP

ppp1 addr:IP

ppp2 addr:IP

Upvotes: 1

Aaron Digulla
Aaron Digulla

Reputation: 328556

How about searching for the string inet and brd (for broadcast)? That would give you:

ip addr show|egrep '^ *inet'|grep brd|awk -- '{ print $2; }'|sed -e 's:/[0-9]*$::'

Note that I'm using more commands than necessary; you can probably achieve the same thing with sed and a more complex regexp but I prefer a command that makes it obvious by which steps I arrive at the result.

If you want to run it in a single command, I suggest to try awk:

ip addr show|awk -- '$1 == "inet" && $3 == "brd"  { split($2,a,"/"); print a[1]; }'

which isn't much longer than the sed version but more readable.

+1 Slightly more readable:

ip addr show | awk '$1 == "inet" && $3 == "brd" { sub (/\/.*/,""); print $2 }'

Upvotes: 3

artfulrobot
artfulrobot

Reputation: 21397

I'd still like to know if there was an easier way to do this, but this is my workaround: I know the LAN subnet, so...

ip addr show | grep "inet 10.67.5." \
    | sed -n '/inet /{s/^.*inet \([0-9.]\+\).*$/\1/;p}'

Upvotes: 1

Related Questions