24

How can I display the IP address shown on eth0 using a script ?

17 Answers 17

29

save this in a file and then run bash <filename>

#!/bin/bash
ifconfig eth0 | grep "inet addr"

being more accurate to get only number showing IP address:

#!/bin/bash
ifconfig eth0 | grep "inet addr" | cut -d ':' -f 2 | cut -d ' ' -f 1

Update: If this doesn't works for you, try the other answer

  • 3
    of course this doesn't work in the latest ubuntu. the latest ifconfig returns "inet <ip>" instead of "inet addr <ip>" – thang Nov 14 '18 at 23:10
  • you can just use grep "inet" – Andrei Radulescu Nov 10 '19 at 15:11
  • here is an updated solution for ifconfig version "net-tools 2.10-alpha" : ifconfig eth0 | grep "inet" | grep -v "inet6" | sed -e 's/^[[:space:]]*//' | cut -d ' ' -f 2 – Maxime Ancelin Feb 13 at 9:03
  • 1
    @MaximeAncelin you should add new answer for this – Edward Torvalds Feb 13 at 9:57
27

For the sake of providing another option, you could use the ip addr command this way to get the IP address:

ip addr show eth0 | grep "inet\b" | awk '{print $2}' | cut -d/ -f1
  • ip addr show eth0 shows information about eth0
  • grep "inet\b" only shows the line that has the IPv4 address (if you wanted the IPv6 address, change it to "inet6\b")
  • awk '{print $2}' prints on the second field, which has the ipaddress/mask, example 172.20.20.15/25
  • cut -d/ -f1 only takes the IP address portion.

In a script:

#!/bin/bash
theIPaddress=$(ip addr show eth0 | grep "inet\b" | awk '{print $2}' | cut -d/ -f1)
  • this solution actually works! – thang Nov 14 '18 at 23:10
  • ip -4 ... and ip -6 ...! Thank you! – TamusJRoyce May 22 '19 at 18:12
17

Taken from https://stackoverflow.com/a/14910952/1695680

hostname -i

However that may return a local ip address (127.0.0.1), so you may have to use, and filter:

hostname -I

From hostname's manpages:

-i, --ip-address

Display the network address(es) of the host name. Note that this works only if the host name can be resolved. Avoid using this option; use hostname --all-ip-addresses instead.

-I, --all-ip-addresses

Display all network addresses of the host. This option enumerates all configured addresses on all network inter‐faces. The loopback interface and IPv6 link-local addresses are omitted. Contrary to option -i, this option does not depend on name resolution. Do not make any assumptions about the order of the output.

  • for the record, I like ip addr show label 'enp*' better, but I is annoying parse, something like ip addr show label 'enp*' | grep -oP inet\ \\S+ | cut -d' ' -f2 can work... how pretty – ThorSummoner Nov 20 '18 at 23:37
5

@markus-lindberg 's response is my favourite. If you add -o -4 to ip's flags then you get a much more easily parsable (and consistent) output:

ip -o -4 a | awk '$2 == "eth0" { gsub(/\/.*/, "", $4); print $4 }'

-o stands for --oneline, which is meant to help in exactly this kind of situations. The -4 is added to limit to the IPv4 address, which is what all the other responses imply.

  • Love the ip flags. Using cut rather than advanced awk wizardry: ip -o -4 addr show eth0 scope global | awk '{print $4;}' | cut -d/ -f 1 – Dawngerpony Dec 16 '16 at 14:03
  • @DuffJ it's probably down to a matter of personal taste. I "discovered" cut way after I learned about awk, and I like minimising the number of commands on my pipelines. Nice suggestion in any case. – Amos Shapira Dec 17 '16 at 6:55
  • I completely agree, Amos. Thanks for your solution! – Dawngerpony Dec 19 '16 at 12:34
4

Here are some oneliners.....

Awk

ifconfig eth0 | awk '/inet addr/{split($2,a,":"); print a[2]}'

split function in the above awk command splits the second column based on the delimiter : and stores the splitted value into an associative array a. So a[2] holds the value of the second part.

sed

ifconfig eth0 | sed -n '/inet addr/s/.*inet addr: *\([^[:space:]]\+\).*/\1/p'

In basic sed , \(...\) called capturing group which is used to capture the characters. We could refer those captured characters through back-referencing. \([^[:space:]]\+\) captures any character but not space one or more times.

grep

ifconfig eth0 | grep -oP 'inet addr:\K\S+'

\K discards the previously matched characters from printing at the final and \S+ matches one or more non-space characters.

Perl

ifconfig eth0 | perl -lane 'print $1 if /inet addr:(\S+)/'

One or more non-space characters which are next to the inet addr: string are captured and finally we print those captured characters only.

  • @edwardtorvalds added some explanation. I think this would be helpful for future readers. Feel free to ask any questions from the above commands... :) – Avinash Raj Dec 12 '14 at 8:07
3

Here's a good one, only uses grep as secondary command:

ip addr show eth0 | grep -oP 'inet \K\S[0-9.]+'

I don't see why you should use more commands than needed

3

You should use ip (instead of ifconfig) as it's current, maintained, and perhaps most importantly for scripting purposes, it produces a consistent & parsable output. Following are a few similar approaches:

If you want the IPv4 address for your Ethernet interface eth0:

$ ip -4 -o addr show eth0 | awk '{print $4}'
192.168.1.166/24  

As a script:

$ INTFC=eth0  
$ MYIPV4=$(ip -4 -o addr show $INTFC | awk '{print $4}') 
$ echo $MYIPV4
192.168.1.166/24

The output produced above is in CIDR notation. If CIDR notation isn't wanted, it can be stripped:

$ ip -4 -o addr show eth0 | awk '{print $4}' | cut -d "/" -f 1 
192.168.1.166  

Another option that IMHO is "most elegant" gets the IPv4 address for whatever interface is used to connect to the specified remote host (8.8.8.8 in this case). Courtesy of @gatoatigrado in this answer:

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

As a script:

$ RHOST=8.8.8.8  
$ MYIP=$(ip route get $RHOST | awk '{ print $NF; exit }')
$ echo $MYIP
192.168.1.166

This works perfectly well on a host with a single interface, but more advantageously will also work on hosts with multiple interfaces and/or route specifications.

While ip would be my preferred approach, it's certainly not the only way to skin this cat. Here's another approach that uses hostname if you prefer something easier/more concise:

$ hostname --all-ip-addresses | awk '{print $1}'  

Or, if you want the IPv6 address:

$ hostname --all-ip-addresses | awk '{print $2}'  

As a script:

$ MYV4IP=$(hostname --all-ip-addresses | awk '{print $1}') 
$ MYV6IP=$(hostname --all-ip-addresses | awk '{print $2}')
$ echo $MYV4IP
192.168.1.166 
$ echo $MYV6IP 
2601:7c1:103:b27:352e:e151:c7d8:3379
2

Just one more option that can be useful if you don't have awk (as it is the case in some embedded devices):

ip addr show dev eth0 scope global | grep "inet\b" | cut -d/ -f 1 | egrep -o "([[:digit:]]{1,3}[.]{1}){3}[[:digit:]]{1,3}"
1

I suggest using a python library like netifaces that is specifically designed for this purpose.

sudo pip install netifaces
python -c "import netifaces; print netifaces.ifaddresses('eth0')[netifaces.AF_INET][0]['addr']"

To obtain the default network interface that is in use.

default_inf = netifaces.gateways()['default'][netifaces.AF_INET][1]
1
ip addr|awk '/eth0/ && /inet/ {gsub(/\/[0-9][0-9]/,""); print $2}'

This only use ip addr which is a replacement for ifconfig and awk combined with substitution (gsub).

Stop using too many processes for simple tasks

1

ifconfig eth0|grep 'inet '|awk '{print $2}'

1

here's for IPv4:

ip -f inet a|grep -oP "(?<=inet ).+(?=\/)"

here's for IPv4 & particular dev (eth0):

ip -f inet a show eth0|grep -oP "(?<=inet ).+(?=\/)"

for IPv6:

ip -6 -o a|grep -oP "(?<=inet6 ).+(?=\/)"

0

this can be used with a normal user too.

ip addr show eth0 | grep "inet " | cut -d '/' -f1 | cut -d ' ' -f6
  • he ask for eth0, this version of your script could help (also show loopback tho) ip addr show | grep "inet " | cut -d '/' -f1 | cut -d ' ' -f6 – TiloBunt Mar 25 '17 at 17:01
  • This is pretty much the same answer as askubuntu.com/a/560466/367990, just using cut twice instead of a combination of awk and cut to parse the output. Next time you should better check out all other answers first and ensure you don't post a duplicate solution. In this case here, I think it's arguable whether it's a duplicate or just similar, so please take it as a general hint. Thanks. – Byte Commander Jul 7 '17 at 19:49
0

This is the shortest way I could find:

ip -f inet addr show $1 | grep -Po 'inet \K[\d.]+'

Replace $1 with your network interface.

ip -f inet tells ip to only return values for the inet (ipv4) family.

grep -Po tells grep to interperate the next value as a perl-regex, and only print the matching values.

The regex \K[\d.]+ says "throw away everything up to this point (\K), and match as many numeric values followed by a dot in a row as possible". This will therefore only match the IP address and ignore everything after it, including the shortform \XX subnet mask.

0

in these days with multiples interfaces (eg if you use a docker) and naming interface by ETH is not anymore the norms

I use this command to extract the IP/Mask :

IPMASK=$(ip a s|grep -A8 -m1 MULTICAST|grep -m1 inet|cut -d' ' -f6)

So whatever how many interfaces I'll have and whatever their name, GREP will only grab the first having the MULTICAST option.

I use this command to extract only the IP without the mask :

IP=$(ip a s|grep -A8 -m1 MULTICAST|grep -m1 inet|cut -d' ' -f6|cut -d'/' -f1)

I use these command on different BDS & NIX it never fail ;)

  • If you're going to parse the output of ip, use the -o option. – muru Oct 26 '17 at 8:31
0

In my script I'm using something like that:

re="inet[[:space:]]+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)"
if [[ $(ip addr show eth0) =~ $re ]]; then
    echo ${BASH_REMATCH[1]}
else
    echo "Cannot determin IP" 1>&2
fi

It doesn't spawn any process.

0

Yet another way (assuming you don't want a CIDR address and want IPv4):

$ ip -br -4 addr show dev eth0 | awk '{split($3,a,"/"); print a[1]}'
  • Uses the ip command which is not deprecated
  • Uses only one command for filtering

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