How can I display the IP address shown on eth0 using a script ?
19 Answers
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 eth0shows information abouteth0grep "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, example172.20.20.15/25cut -d/ -f1only takes the IP address portion.
In a script:
#!/bin/bash
theIPaddress=$(ip addr show eth0 | grep "inet\b" | awk '{print $2}' | cut -d/ -f1)
- 31,075
- 11
- 94
- 105
-
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
-
`ip addr show eth0 | grep -P "inet6?\b" | awk '{print $2}' | cut -d/ -f1` will print both IPv4 and IPv6. – Artem Russakovskii Jun 04 '20 at 08:14
Note: This answer is for older systems. If this does not work for you please consider other answers. This answer is not incorrect.
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
Update: For Ubuntu 18+, try: (don't forget to replace eth0 with interface you need the IP for. Thanks to @ignacio )
ifconfig eth0 | grep "inet " | awk '{print $2}'
- 7,830
- 9
- 54
- 93
-
4of course this doesn't work in the latest ubuntu. the latest ifconfig returns "inet
" instead of "inet addr – thang Nov 14 '18 at 23:10" -
2
-
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 '20 at 09:03
-
1
-
2quick update for `Ubuntu 18.04`: `ifconfig wlan0 | grep "inet " | awk '{print $2}'` – ignacio Oct 28 '20 at 16:55
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-addressDisplay 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-addressesDisplay 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.
- 3,129
- 3
- 20
- 31
-
1for 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
-
`ip route | grep default | grep -oP 'dev \S+' | cut -d' ' -f 2 | xargs ip addr show dev | grep -oP 'inet6? \S+'` – ThorSummoner Apr 11 '20 at 01:43
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:
#!/usr/bin/env bash
INTFC=eth0
MYIPV4=$(ip -4 -o addr show $INTFC | awk '{print $4}')
echo $MYIPV4
will yield: 192.168.1.166/24 as its output
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
Or, as a script:
#!/usr/bin/env bash
RHOST=8.8.8.8
MYIP=$(ip route get $RHOST | awk '{ print $NF; exit }')
echo $MYIP
will yield: 192.168.1.166 as its output
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:
#!/usr/bin/env bash
MYV4IP=$(hostname --all-ip-addresses | awk '{print $1}')
MYV6IP=$(hostname --all-ip-addresses | awk '{print $2}')
echo $MYV4IP
echo $MYV6IP
will yield: 192.168.1.166, and 2601:7c1:103:b27:352e:e151:c7d8:3379 as its answers (assuming you have an IPv6 address assigned).
- 554
- 1
- 7
- 18
@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.
- 253
- 4
- 10
-
1Love 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
-
1@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. – Capt. Crunch Dec 17 '16 at 06:55
-
1
-
1Very helpful. This should be the accepted answer, and this is not using the deprecated `ifconfig` which needs you to explicitly install `net-tools` in Ubuntu. – Haris Jun 11 '20 at 17:28
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.
- 77,204
- 56
- 214
- 254
-
@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 08:07
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 ).+(?=\/)"
- 121
- 2
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).
- 193,181
- 53
- 473
- 722
- 131
- 5
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}"
- 121
- 2
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
- 29
- 1
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
ipcommand which is notdeprecated - Uses only one command for filtering
- 1,398
- 10
- 16
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]
- 590
- 4
- 5
this can be used with a normal user too.
ip addr show eth0 | grep "inet " | cut -d '/' -f1 | cut -d ' ' -f6
- 11
- 3
-
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 https://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 07 '17 at 19:49
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 ;)
- 337
- 1
- 2
- 8
If eth0 has multiple IPs and you are looking for a public one here is an example of ignoring the 2 most common internal IP address ranges.
ip -4 addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep --invert-match -P '^(10\.|192\.168\.)'
This ignores 10.0.0.0/8 and 192.168.0.0/16 IPs.
- 151
- 3
Yes, you can do it like the other entries suggest, but you can also do it like a bauss:
#!/bin/bash
#
# IPs Table
type column &>/dev/null || apt-get install -yq bsdextrautils
links() { ip link | awk '/^[0-9]+:/ { sub(":", "", $2); sub("@.*", "", $2 ); print $2; }'; }
ipof() { ip addr show ${1:-enp6s0} | awk ' /link.ether/ { print "mac", $2 }
/inet6*/ { print $1, $2 }'; }
( echo dev inet inet6 mac
for i in `links`; do
unset ips a b c d
ips=$(ipof $i)
if [[ -z $ips ]]; then
mac=.
inet=.
inet6=.
else
read -s -r -d ';' _ mac _ inet _ inet6 <<< "$ips;"
if [[ -z $inet6 ]] && [[ $inet =~ :: ]]; then
inet6=$inet
inet=
fi
fi
echo $i ${inet:--} ${inet6:--} ${mac:--}
done; ) | column -t
The script is from my collection
Sample output A:
dev inet inet6 mac
lo 127.0.0.1/8 ::1/128 00:00:00:00:00:00
enp6s0 192.168.0.4/24 fe80::aaa1:59ff:fe50:85ea/64 a8:a1:59:50:85:ea
enp4s0d1 - - 24:8a:07:6b:5d:52
ibp4s0 - - 80:00:02:20:fe:80:00:00:00:00:00:00:24:8a:07:03:00:6b:5d:51
virbr0 192.168.122.1/24 - 52:54:00:f3:77:52
virbr1 192.168.39.1/24 - 52:54:00:cf:77:c6
vboxnet0 - - 0a:00:27:00:00:00
vboxnet1 - - 0a:00:27:00:00:01
vboxnet2 - - 0a:00:27:00:00:02
vboxnet3 - - 0a:00:27:00:00:03
vboxnet4 - - 0a:00:27:00:00:04
Sample output B:
dev inet inet6 mac
lo 127.0.0.1/8 ::1/128 00:00:00:00:00:00
ens3 10.40.237.34/18 fe80::8de:f6ff:fe19:f315/64 0a:de:f6:19:f3:15
lxcbr0 172.16.0.1/16 fe80::216:3eff:fe00:0/64 00:16:3e:00:00:00
vaf.sta.RsuBSCQ - fe80::fc91:4fff:fed1:6adc/64 fe:91:4f:d1:6a:dc
vaf.cra.G4EHHKb - fe80::fc47:69ff:fe86:abc6/64 fe:47:69:86:ab:c6
vaf.com.t2VC1vD - fe80::fc25:cff:fec5:515b/64 fe:25:0c:c5:51:5b
vaf.lor.cXYkGKF - fe80::fce8:6dff:fed1:8d08/64 fe:e8:6d:d1:8d:08
vaf.iff.2I4P4ay - fe80::fca0:6dff:fe33:e198/64 fe:a0:6d:33:e1:98
vaf.bag.etDqGZ3 - fe80::fca6:c9ff:fe17:8e4f/64 fe:a6:c9:17:8e:4f
vaf.bor.L9tqMch - fe80::fc90:92ff:fe48:bf48/64 fe:90:92:48:bf:48
vaf.dan.GhojJo8 - fe80::fc0c:71ff:feaa:8b81/64 fe:0c:71:aa:8b:81
vaf.tru.ZuH5xfb - fe80::fc2e:21ff:fe91:2ce5/64 fe:2e:21:91:2c:e5
vaf.huo.6ii1Tyy - fe80::fcbe:fbff:fe59:44f5/64 fe:be:fb:59:44:f5
vaf.nwt.CFoTS9J - fe80::fc5d:3fff:feac:917f/64 fe:5d:3f:ac:91:7f
vethe8qi4n - fe80::fca2:10ff:feec:5e2b/64 fe:a2:10:ec:5e:2b
vaf.cra.6gHyk8E - fe80::fc23:4bff:fe2c:e9b/64 fe:23:4b:2c:0e:9b
- 244
- 2
- 9
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.
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.
- 3,306
- 5
- 30
- 49
- 101
- 2