How to get the primary IP address of the local machine on Linux and OS X? [closed]
Asked Answered
D

31

449

I am looking for a command line solution that would return me the primary (first) IP address of the localhost, other than 127.0.0.1

The solution should work at least for Linux (Debian and RedHat) and OS X 10.7+

I am aware that ifconfig is available on both but its output is not so consistent between these platforms.

Dictation answered 10/11, 2012 at 13:32 Comment(7)
Do you just want your machine local network IP? i.e 192.168.0.12Presbyterian
Yes, the local IP, first of them as it can have more than one, but I could live even with a list. For the moment I am happy to support only IPv4 addresses and ignore the IPv6, as want it only to generate a hash.Dictation
How do you define "primary"? If you're thinking "the IP address that's on the same subnet as my default route", you'll need to program a bit for that. But what if the machine has no default route, but still has >1 IP addresses?Ehrenburg
Try curl -4 ifconfig.co . It will answer with your external IP4 address.Caddy
I've just used curl ifconfig.me and it worked fine.Intramundane
bash: ifconfig: command not found --> the command is deprecated, see ifconfig and locate command not found, bash: ifconfig: command not found on Unix & Linux Stack Exchange where the question belongs.Potbellied
2>/dev/null ifconfig | grep inet | tail -1 | awk '{print $2}' I think this is the answer you are looking for.Rebba
P
592

Use grep to filter IP address from ifconfig:

ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'

Or with sed:

ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'

If you are only interested in certain interfaces, wlan0, eth0, etc. then:

ifconfig wlan0 | ...

You can alias the command in your .bashrc to create your own command called myip for instance.

alias myip="ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p'"

A much simpler way is hostname -I (hostname -i for older versions of hostname but see comments). However, this is on Linux only.

Presbyterian answered 10/11, 2012 at 13:39 Comment(19)
Note also that in OSX, sed uses the -E option for Extended RE, not the GNU-style -r option.Ehrenburg
@Ehrenburg Linux supports both but only documents -r is the converse true for OSX?Presbyterian
Interesting; I didn't realize that GNU sed supported -E. Recent versions of FreeBSD have added the -r option as an alias for -E to ease script portability, but the update hasn't yet been brought over to OSX, which last I checked still uses a version of sed from a FreeBSD release of a few years ago. Not sure precisely which one, as OSX has adoped FreeBSD source code a few times over the years. I believe the use of -E was intended to be comparable to grep's -E option. No idea why GNU folks opted for -r instead.Ehrenburg
@Ehrenburg I changed answer to use -E to be sure of portability, you'd think that --help and the man pages would be updated.. it did cause slight confusion for me earlier in another question using -EPresbyterian
I found a problem, while this works on OS X it does return more than one IP, a list of IPs. It seems that the first one is the right one but still this would break my logic. See gist.github.com/ssbarnea/31b9dcb0f8fd528b958c -- it also returns the vnic ones that are active but used by paralles.Dictation
@Dictation like I said in my answer 10 months ago if you want to filter by interface then do ifconfig en1 | sed ...Presbyterian
Can this support ipv6 addresses?Wendolynwendt
Note about hostname: -I is a shortcut for --all-ip-addresses which displays all configured network addresses on all network interfaces, each separated by a space. It excludes the loopback interface (127.0.0.0/8) and IPv6 link-local addresses. It does not depend on name resolution. The output order is arbitrary. Older versions of the command (at least 1.1) do not have this option, but do have one for -i, a shortcut for --ip-address which displays all network addresses for the resolved host name, and as such should be avoided per the manual (for newer versions with -I).Salliesallow
Slight modification for when you know some of the address. This one only returns addresses in the range 10.0.0.0/16. ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(10\.0\.[0-9]*\.[0-9]*).*/\2/p'.Matrimony
OSX: ipconfig getifaddr en0Rabelaisian
This doesn't work in Linux distribution with LANG different to "en" or "en_*", because ifconfig returns the inet label translated to the user language. The best way to do this regardless of the the *nix system (Linux, OSX, ...) and regardless of the user language is here: #23934925Conte
you should probably exclude other private ips, as 172.17. this are widely used for docker container traffic redirection.Fiber
This doesn't answer the question, it just provides a list of all IPs, not the primary (default route) one.Mureil
So what about an ipv6-only host?Pavlodar
THIS IS DANGEROUS. It fails to avoid the internal IP addresses and in this day of Dockers and VPNs and stuff there is often many of them. If you know the interface, then fine, but this does not show how to find it.Choate
Replace ifconfig with ip for Arch LinuxBaboon
You can also use hostname -I in Linux serverHulburt
This returns multiple ip address if its run inside a google inside like 172.18.0.1 172.17.0.1 Truism
This answer is deprecated!!Nickelous
I
303

The following will work on Linux but not OSX.

This doesn't rely on DNS at all, and it works even if /etc/hosts is not set correctly (1 is shorthand for 1.0.0.0):

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

or avoiding awk and using Google's public DNS at 8.8.8.8 for obviousness:

ip route get 8.8.8.8 | head -1 | cut -d' ' -f8

A less reliable way: (see comment below)

hostname -I | cut -d' ' -f1
Induration answered 15/9, 2014 at 15:8 Comment(21)
The method that gets the first address produced by the hostname -I is unreliable, because (according to the documentation) one cannot make any assumptions about the order of the addresses. So it may well be some internal network (like the network on which virtual machines are living). The other method seems good.Laurencelaurene
ip -4 route get 1 | head -1 | cut -d' ' -f8 | tr -d '\n' (if you want IPv4 address and truncate to avoid empty spaces)Dariodariole
Note that none of these work on OS X.Reasonable
Note that ip route get 8.8.8.8 | head -1 | cut -d' ' -f8 doesn't work for local network IPs, only for remote ones as the output of ip route get is different then (the via 192.168.1.1 part is missing). You'd need to change -f8 to -f6 then. Or simply use the awk solution which works reliable in all of those cases for me.Gagarin
More detailed response that uses the same ip route get 8.8.8.8 technique, from the related post: https://mcmap.net/q/41428/-linux-bash-script-to-extract-ip-addressBuchheim
The advantage of this method is, at least on my Linux box, that it can be run by a normal user, while ifconfig requires root.Roose
For me ip route get 1 | awk '{print $(NF-2);exit}' works as I get uid appended to the outptutKerrill
THIS (the first one) IS THE ONLY CORRECT SOLUTION. It is important to read the IP specifically from the interface associated with the default route. Otherwise you are quite likely to get some worthless internal address.Choate
it didn't work for me but it was closed enough: ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'Foucault
The solution of @Foucault works for the new ip output (which appends "uid xxxx") and for the old ip output.Tourniquet
@Tourniquet thanks for testing, I extract it to an answer, cause here won't be found.Foucault
Seems like the output format of ip isn't quite stable. For me, cut -d' ' -f8 doesn't work, but cut -d' ' -f7 does.Hypso
hostname -I | cut -d' ' -f1 works on 16.04 and 18.04Extrajudicial
I tried on OS X 10.13.6 (macOS High Sierra) and these two work fine: ip route get 1 | awk '{print $NF;exit}' and ip route get 8.8.8.8 | head -1 | cut -d' ' -f8 The first one needs the $ back-slash escaped as bash alias; the second does not need that.Neubauer
I think ip route get 1 | awk '{gsub("^.*src ",""); print $1; exit}' is better - there are too many different variants of ip route that have different things on that line. This looks for the IP that goes with "src" and prints it.Feminacy
ip route get 1 | sed -e 's/ /\n/g' | grep -A1 src | tail -n 1Tackling
ip route get 1 | awk '{print $NF;exit}' returns 1000 for me is that correct ? I actually expected 192.168.178.23Overload
As with similar answers, if you have multiple interfaces (e.g. a VPN) and need the local IP address as seen by any other arbitrary IP, simply substitute that other IP address for 1/8.8.8.8.Tasty
@Overload As @Foucault also noted, the first version doesn't work for me because of the uid added to the output. It just returns your uid (1000 in your case). See estani's answer here: https://mcmap.net/q/41138/-how-to-get-the-primary-ip-address-of-the-local-machine-on-linux-and-os-x-closedTasty
ip route get 1 | sed -nr 's/^.* src ([0-9.]+)( .*|)$/\1/p' - this will work with and without uid suffixDemineralize
Only the ``` less reliable way``` worked for meCentigrade
P
263

For linux machines (not OS X) :

hostname --ip-address
Patent answered 19/9, 2013 at 21:58 Comment(10)
That only works if the name is in DNS. If not, you get the message "hostname: Name or service not known."Lacey
hostname -i is the equivalent short formHedelman
This will sometimes simply return 127.0.0.1. If available, better use hostname -I as recommended by the manual (Ubuntu): "--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."Sloppy
It doesn't work on Linux either, at least not with hostname in GNU Coreutils version 8.26.Wagtail
On my machine, hostname -i gives only the local IP, while hostname -I gives all the other IPsPram
This returned 127.0.0.1 on my machineDisvalue
THIS IS DANGEROUS. It fails to avoid the internal IP addresses and in this day of Dockers and VPNs and stuff there is often many of them. If you know the interface, then fine, but this does not show how to find it.Choate
this just shows 127.0.0.1 for me on Redhat server, maybe depends on your /etc/ssh/sshd_config settings?Bork
if you have ipv6 enabled, it will return on the same line both ipv4 and ipv6 address.Cuman
The hostname manpage (on Debian) for -i, --ip-address says "Avoid using this option; use hostname --all-ip-addresses instead"Drab
M
104

Solution

$ ip -o route get to 8.8.8.8 | sed -n 's/.*src \([0-9.]\+\).*/\1/p'
192.168.8.16

Explanation

The correct way to query network information is using ip:

  • -o one-line output
  • route get to get the actual kernel route to a destination
  • 8.8.8.8 Google IP, but can use the real IP you want to reach

e.g. ip output:

8.8.8.8 via 192.168.8.254 dev enp0s25 src 192.168.8.16 uid 1000 \   cache

To extract the src ip, sed is the ligthest and most compatible with regex support:

  • -n no output by default
  • 's/pattern/replacement/p' match pattern and print replacement only
  • .*src \([0-9.]\+\).* match the src IP used by the kernel, to reach 8.8.8.8

e.g. final output:

192.168.8.16

Other answers

I think none of the preceding answer are good enough for me, as they don't work in a recent machine (Gentoo 2018).

Issues I found with preceding answers:

  • use of positional column in command output;
  • use of ifconfig which is deprecated and -- for example -- don't list multple IPs;
  • use of awk for a simple task which sed can handle better;
  • ip route get 1 is unclear, and is actually an alias for ip route get to 1.0.0.0
  • use of hostname command, which don't have -I option in all appliance and which return 127.0.0.1 in my case.
Mcavoy answered 29/3, 2018 at 9:43 Comment(4)
You could avoid fork to sed and become more detailed infos by using bash read! See my answerNickelous
This is the only solution that worked flawlessly for me in 2022Offcenter
not working. Option "-o" is unknown, try "ip -help".Erato
In my ip implementation, -o is present and is a shortcut for -onelineMcavoy
D
100

on Linux

hostname -I

on macOS

ipconfig getifaddr en0

hostname -I can return multiple addresses in an unreliable order (see the hostname manpage), but for me it just returns 192.168.1.X, which is what you wanted.

Drab answered 4/10, 2017 at 12:40 Comment(6)
for me it was hostname -i with a lower I.Inescutcheon
@PaulWoitaschek the manpage for the lowercase -i flag says this: Avoid using this option; use hostname -I instead.Drab
@Boris if you're running in something like a docker container running Alpine (and thus BusyBox) it will only accept lowercase -i flagPortion
hostname -I | grep -o "^[0-9.]*" If you just want the first one.Hat
This may be a naive question, but in ipconfig getifaddr en0, what exactly is special about "en0"? Is every macOS system guaranteed to have an "en0" network device?Nynorsk
@Nynorsk en0 is Wi-Fi according to this answer.Drab
N
49

Edited (2014-06-01 2018-01-09 2021-07-25 2024-02-19)

From some time ago, I use now newer ip tool. But under , I will do simply:

read -r _{,} gateway _ iface _ ip _ < <(ip r g 1.0.0.0)

Then

printf '%-12s %s\n'  gateway $gateway iface $iface ip $ip
gateway      192.168.1.1
iface        eth0
ip           192.168.1.37

From there, the mask is:

while IFS=$' /\t\r\n' read lne lip lmask _; do
    case $lne:$lip in "inet:$ip") masklen=$lmask; break ;; esac
done < <(ip a s dev $iface)

echo Mask is $masklen bits length.
Mask is 24 bits length.

( Note: I've replaced double test: [[ $ip = ... ]] && [[... by case condition, because of efficience and speedness more infos at stringContain!! )

Then if you want to see your mask as an IP:

printf -v mask '%*s' $masklen ''
printf -v mask %-32s ${mask// /1}
printf -v mask %d.%d.%d.%d $((mask=2#${mask// /0},mask>>24)) \
    $((mask>>16&255)) $((mask>>8&255)) $((mask&255))

Then showing all variables:

for var in ip mask gateway masklen iface; do
    printf '%-12s %s\n' $var ${!var}
done
ip           192.168.1.37
mask         255.255.255.0
gateway      192.168.1.1
masklen      24
iface        eth0

Edited (2014-06-01 2018-01-09)

For stronger config, with many interfaces and many IP configured on each interfaces, I wrote a pure bash script (not based on 127.0.0.1) for finding correct interface and ip, based on default route. I post this script at very bottom of this answer.

Intro

As both Os have installed by default, there is a bash tip for both Mac and Linux:

The locale issue is prevented by the use of LANG=C:

myip=
while IFS=$': \t' read -a line ;do
    [ -z "${line%inet}" ] && ip=${line[${#line[1]}>4?1:2]} &&
        [ "${ip#127.0.0.1}" ] && myip=$ip
  done< <(LANG=C /sbin/ifconfig)
echo $myip

Putting this into a function:

Minimal:

getMyIP() {
    local _ip _line
    while IFS=$': \t' read -a _line ;do
        [ -z "${_line%inet}" ] &&
           _ip=${_line[${#_line[1]}>4?1:2]} &&
           [ "${_ip#127.0.0.1}" ] && echo $_ip && return 0
      done< <(LANG=C /sbin/ifconfig)
}

Simple use:

getMyIP
192.168.1.37

Fancy tidy:

getMyIP() {
    local _ip _myip _line _nl=$'\n'
    while IFS=$': \t' read -a _line ;do
        [ -z "${_line%inet}" ] &&
           _ip=${_line[${#_line[1]}>4?1:2]} &&
           [ "${_ip#127.0.0.1}" ] && _myip=$_ip
      done< <(LANG=C /sbin/ifconfig)
    printf ${1+-v} $1 "%s${_nl:0:$[${#1}>0?0:1]}" $_myip
}

Usage:

getMyIP
192.168.1.37

or, running same function, but with an argument:

getMyIP varHostIP
echo $varHostIP
192.168.1.37
set | grep ^varHostIP
varHostIP=192.168.1.37

Nota: Without argument, this function output on STDOUT, the IP and a newline, with an argument, nothing is printed, but a variable named as argument is created and contain IP without newline.

Nota2: This was tested on Debian, LaCie hacked nas and MaxOs. If this won't work under your environ, I will be very interested by feed-backs!

Older version of this answer

( Not deleted because based on sed, not bash. )

Warn: There is an issue about locales!

Quick and small:

myIP=$(ip a s|sed -ne '/127.0.0.1/!{s/^[ \t]*inet[ \t]*\([0-9.]\+\)\/.*$/\1/p}')

Exploded (work too;)

myIP=$(
    ip a s |
    sed -ne '
        /127.0.0.1/!{
            s/^[ \t]*inet[ \t]*\([0-9.]\+\)\/.*$/\1/p
        }
    '
)

Edit:

How! This seem not work on Mac OS...

Ok, this seem work quite same on Mac OS as on my Linux:

myIP=$(LANG=C /sbin/ifconfig  | sed -ne $'/127.0.0.1/ ! { s/^[ \t]*inet[ \t]\\{1,99\\}\\(addr:\\)\\{0,1\\}\\([0-9.]*\\)[ \t\/].*$/\\2/p; }')

splitted:

myIP=$(
    LANG=C /sbin/ifconfig  |
        sed -ne $'/127.0.0.1/ ! {
            s/^[ \t]*inet[ \t]\\{1,99\\}\\(addr:\\)\\{0,1\\}\\([0-9.]*\\)[ \t\/].*$/\\2/p;
        }')

My script (jan 2018):

This script will first find your default route and interface used for, then search for local ip matching network of gateway and populate variables. The last two lines just print, something like:

Interface   : en0
Local Ip    : 10.2.5.3
Gateway     : 10.2.4.204
Net mask    : 255.255.252.0
Run on mac  : true

or

Interface   : eth2
Local Ip    : 192.168.1.31
Gateway     : 192.168.1.1
Net mask    : 255.255.255.0
Run on mac  : false

Well, there it is:

#!/bin/bash
runOnMac=false
int2ip() { printf ${2+-v} $2 "%d.%d.%d.%d" \
        $(($1>>24)) $(($1>>16&255)) $(($1>>8&255)) $(($1&255)) ;}
ip2int() { local _a=(${1//./ }) ; printf ${2+-v} $2 "%u" $(( _a<<24 |
                  ${_a[1]} << 16 | ${_a[2]} << 8 | ${_a[3]} )) ;}
while IFS=$' :\t\r\n' read a b c d; do
    [ "$a" = "usage" ] && [ "$b" = "route" ] && runOnMac=true
    if $runOnMac ;then
        case $a in 
            gateway )    gWay=$b  ;;
            interface )  iFace=$b ;;
        esac
    else
        [ "$a" = "0.0.0.0" ] && [ "$c" = "$a" ] && iFace=${d##* } gWay=$b
    fi
done < <(/sbin/route -n 2>&1 || /sbin/route -n get 0.0.0.0/0)
ip2int $gWay gw
while read lhs rhs; do
    [ "$lhs" ] && { 
        [ -z "${lhs#*:}" ] && iface=${lhs%:}
        [ "$lhs" = "inet" ] && [ "$iface" = "$iFace" ] && {
            mask=${rhs#*netmask }
            mask=${mask%% *}
            [ "$mask" ] && [ -z "${mask%0x*}" ] &&
                printf -v mask %u $mask ||
                ip2int $mask mask
            ip2int ${rhs%% *} ip
            (( ( ip & mask ) == ( gw & mask ) )) &&
                int2ip $ip myIp && int2ip $mask netMask
        }
    }
done < <(/sbin/ifconfig)
printf "%-12s: %s\n" Interface $iFace Local\ Ip $myIp \
       Gateway $gWay Net\ mask $netMask Run\ on\ mac $runOnMac
Nickelous answered 10/11, 2012 at 13:57 Comment(10)
@sorin: yes, this work now with ifconfig. (as sbin is not on my $PATH fullpath have to be specified, but same path exist on MacOS too. :-)Nickelous
@Dictation try this with time to select which you would use so long...Nickelous
the quick and small solution was the best approach. Newer solutions give me syntax errors. Compatibility is always a plus. Thank you.Zaxis
This does not show the public ip address , like curl ifconfig.me doesTruism
@Truism this is not the scope of request... And ifconfig.me is just another what-is-my-ip provider.Nickelous
Your solution does not return the IP address that users can connect into the machine using ssh. Most of the other answers does since its the scope of the request.Truism
@Truism My solution return my ip used to adress router. Public IP and routing from public network to my private ip is a router concern. All hosts on my private network could reach my host by IP returned by my solution. And If I want to connect from public network, THIS is THE IP I have to configure into the router for this.Nickelous
Thanks for the update its more clear now. I am just confused to visualize how the routing process is done, is it done from the modem's interface? I have tried your solution inside a google instance, since I don't have access to their routers I need the machine's public IP inorder for me to ssh into it. For my VMs using VMware Workstation Bridged: Connected directly to the pyhsical network check, I am required to its public IP as well. I did not understand how did you configured the router, have you done port forwarding for this?Truism
@Truism Yes, I was speaking about private network. About google cloud, I don't know, but if you can reach your instance, you should be able to access it from a web browser and from a ssh client!?Nickelous
@F.Hauri Yes sir related to google instance, I can access them from a browser and from a ssh client using the IP address returned by curl ifconfig.me.Truism
A
29

Specific to only certain builds of Ubuntu. Though it may just tell you 127.0.0.1:

hostname  -i

or

hostname -I
Ardeha answered 8/1, 2014 at 13:45 Comment(6)
does this work in every case?Utrecht
no. - it may just tell you 127.0.0.1.Crucify
hostname -I works on ubuntu.Bigelow
$ hostname --ip-address just gives me 127.0.0.1 on Arch LinuxHimes
use hostname -I or hostname --all-ip-addressesCornwall
Simplest answer. hostname -I give the local IP hostname -i gives the loopback ipRolfe
A
25

You can also get IP version 4 address of eth0 by using this command in linux

/sbin/ip -4 -o addr show dev eth0| awk '{split($4,a,"/");print a[1]}'

Output will be like this

[root@localhost Sathish]# /sbin/ip -4 -o addr show dev eth0| awk '{split($4,a,"/");print a[1]}'
192.168.1.22
Anjelicaanjou answered 25/3, 2014 at 11:12 Comment(2)
This assumes eth0, which is not current naming strategy and never was guaranteed to be the primary interface.Feminacy
This is the most elegant method if you know the interface. Ideal if your system has multiple interfaces but you are just interested in a particular one.Empedocles
M
16

Using some of the other methods You may enter a conflict where multiple IP adresses is defined on the system. This line always gets the IP address by default used.

ip route get 8.8.8.8 | head -1 | awk '{print $7}'
Marius answered 3/3, 2017 at 12:58 Comment(2)
It will fail if there is no default route (but good idea)Legalize
Nice... Suppose to work even if you don't have internet?Pasteurizer
C
14

This works on Linux and OSX

This will get the interface associated to the default route

NET_IF=`netstat -rn | awk '/^0.0.0.0/ {thif=substr($0,74,10); print thif;} /^default.*UG/ {thif=substr($0,65,10); print thif;}'`

Using the interface discovered above, get the ip address.

NET_IP=`ifconfig ${NET_IF} | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'`

OSX

uname -a

Darwin laptop 14.4.0 Darwin Kernel Version 14.4.0: Thu May 28 11:35:04 PDT 2015; root:xnu-2782.30.5~1/RELEASE_X86_64 x86_64

echo $NET_IF

en5

echo $NET_IP

192.168.0.130

CentOS Linux

uname -a

Linux dev-cil.medfx.local 2.6.18-164.el5xen 1 SMP Thu Sep 3 04:03:03 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux

echo $NET_IF

eth0

echo $NET_IP

192.168.46.10

Colewort answered 5/11, 2015 at 16:54 Comment(1)
Despite all the answers to this question, this one appears to be the only one that comes close to actually being correct. Just needs a | head -1 at the end of the first line to get the default interface, and the rest is good.Mureil
C
13
ifconfig | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}'
Christine answered 5/7, 2018 at 2:43 Comment(5)
If you're looking to make this into a bash alias: alias myip="ifconfig | grep 'inet ' | grep -v '127.0.0.1' | awk '{print \$2}'"Compte
Right. But the question initially was about the command. So I just posted relevantly. Cheers!Christine
Don't understand why this answer has less likes. Simple & working!!!Shelashelagh
Purely with awk, this would be: ifconfig | awk '/inet / {if($2=="127.0.0.1") {next}; print $2}'Acervate
I am using termux (arch linux) and here is my answer : 2>/dev/null ifconfig | grep inet | tail -1 | awk '{print $2}' it will give you exact local ipRebba
F
10

Im extracting my comment to this answer:

ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'

It bases on @CollinAnderson answer which didn't work in my case.

Foucault answered 9/8, 2018 at 12:59 Comment(4)
This will get you your IP on the default network. But if you have multiple interfaces (e.g. a VPN, maybe a WAN...), and need the local IP address as seen by some other IP on one of those connected networks, simply substitute that other IP address for the 1 in the ip route command... et voilà!Tasty
I think this is the most usable answer, only note that this might not work on some systems/versions because of last space char in sed command (src might be last portion in the line). I think it is ok without it: ip route get 1 | sed -nr 's/^.* src ([0-9.]*).*/\1/p'Demineralize
can do without a capture group: ip --oneline route get 1 | sed 's/.* src //g;s/ .*//g'Conners
@Conners if it works for you is ok, but it won't work in all distros. Check unix.stackexchange.com/questions/420965/…Foucault
E
8

Assuming you need your primary public IP as it seen from the rest of the world, try any of those:

wget http://ipecho.net/plain -O - -q
curl http://icanhazip.com
curl http://ifconfig.me/ip
Eudosia answered 11/7, 2017 at 6:20 Comment(0)
L
8

Finds an IP address of this computer in a network which is a default gateway (for example excludes all virtual networks, docker bridges) eg. internet gateway, wifi gateway, ethernet

ip route| grep $(ip route |grep default | awk '{ print $5 }') | grep -v "default" | awk '/scope/ { print $9 }'

Works on Linux.

Test:

➜  ~ ip route| grep $(ip route |grep default | awk '{ print $5 }') | grep -v "default" | awk '/scope/ { print $9 }'
192.168.0.114

➜  reverse-networking git:(feature/type-local) ✗ ifconfig wlp2s0
wlp2s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.114  netmask 255.255.255.0  broadcast 192.168.0.255
        inet6 fe80::d3b9:8e6e:caee:444  prefixlen 64  scopeid 0x20<link>
        ether ac:x:y:z  txqueuelen 1000  (Ethernet)
        RX packets 25883684  bytes 27620415278 (25.7 GiB)
        RX errors 0  dropped 27  overruns 0  frame 0
        TX packets 7511319  bytes 1077539831 (1.0 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
Larrikin answered 24/2, 2019 at 10:11 Comment(1)
Nice! Taco Bell programming at it's best -- thanks for this.Kamerad
O
6

I have to add to Collin Andersons answer that this method also takes into account if you have two interfaces and they're both showing as up.

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

I have been working on an application with Raspberry Pi's and needed the IP address that was actually being used not just whether it was up or not. Most of the other answers will return both IP address which isn't necessarily helpful - for my scenario anyway.

Odelet answered 18/1, 2018 at 10:53 Comment(1)
Better use JSON instead: ip -j r g 1 | python3 -c 'import sys,json; print(json.load(sys.stdin)[0]["prefsrc"])' (works for Ansible, too)Fong
E
5
ip addr show | grep -E '^\s*inet' | grep -m1 global | awk '{ print $2 }' | sed 's|/.*||'
Examinant answered 13/2, 2014 at 4:8 Comment(1)
I don't know why this one seems to be glossed over.Persons
N
5

The shortest way to get your local ipv4-address on your linux system:

hostname -I | awk '{print $1}'
Nesta answered 5/10, 2014 at 6:37 Comment(2)
Bad. The man page tells you specifically not to make any assumptions about the order of the output.Lathrope
Works great for my trivial use cases – I don't care if it is quick and dirty! Great!Krystlekrystyna
F
4

Primary network interface IP

ifconfig `ip route | grep default | head -1 | sed 's/\(.*dev \)\([a-z0-9]*\)\(.*\)/\2/g'` | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | head -1
Funest answered 13/3, 2015 at 19:24 Comment(0)
U
3

Not sure if this works in all os, try it out.

ifconfig | awk -F"[ :]+" '/inet addr/ && !/127.0/ {print $4}'
Ununa answered 27/8, 2013 at 20:59 Comment(3)
Doesn't work on CentOS 7.0Costanzo
@BenoitBlanchon Then use this ip route get 1 | awk '{print $NF;exit}'. Should work on most system.Ununa
Indeed ip route get 1 | awk '{print $NF;exit}' worksCostanzo
D
3

Another ifconfig variantion that works both on Linux and OSX:

ifconfig | grep "inet " | cut -f2 -d' '
Dramaturge answered 19/7, 2016 at 14:0 Comment(2)
one small variation: ifconfig | grep '\<inet\>' | cut -d ' ' -f2 | grep -v '127.0.0.1'Dubbin
Why do half of these answers not work at all for me?Footlocker
D
3

I just utilize Network Interface Names, my custom command is

[[ $(ip addr | grep enp0s25) != '' ]] && ip addr show dev enp0s25 | sed -n -r 's@.*inet (.*)/.*brd.*@\1@p' || ip addr show dev eth0 | sed -n -r 's@.*inet (.*)/.*brd.*@\1@p' 

in my own notebook

[flying@lempstacker ~]$ cat /etc/redhat-release 
CentOS Linux release 7.2.1511 (Core) 
[flying@lempstacker ~]$ [[ $(ip addr | grep enp0s25) != '' ]] && ip addr show dev enp0s25 | sed -n -r 's@.*inet (.*)/.*brd.*@\1@p' || ip addr show dev eth0 | sed -n -r 's@.*inet (.*)/.*brd.*@\1@p'
192.168.2.221
[flying@lempstacker ~]$

but if the network interface owns at least one ip, then it will show all ip belong to it

for example

Ubuntu 16.10

root@yakkety:~# sed -r -n 's@"@@g;s@^VERSION=(.*)@\1@p' /etc/os-release
16.04.1 LTS (Xenial Xerus)
root@yakkety:~# [[ $(ip addr | grep enp0s25) != '' ]] && ip addr show dev enp0s25 | sed -n -r 's@.*inet (.*)/.*brd.*@\1@p' || ip addr show dev eth0 | sed -n -r 's@.*inet (.*)/.*brd.*@\1@p'
178.62.236.250
root@yakkety:~#

Debian Jessie

root@jessie:~# sed -r -n 's@"@@g;s@^PRETTY_NAME=(.*)@\1@p' /etc/os-release
Debian GNU/Linux 8 (jessie)
root@jessie:~# [[ $(ip addr | grep enp0s25) != '' ]] && ip addr show dev enp0s25 | sed -n -r 's@.*inet (.*)/.*brd.*@\1@p' || ip addr show dev eth0 | sed -n -r 's@.*inet (.*)/.*brd.*@\1@p'
192.81.222.54
root@jessie:~# 

CentOS 6.8

[root@centos68 ~]# cat /etc/redhat-release 
CentOS release 6.8 (Final)
[root@centos68 ~]# [[ $(ip addr | grep enp0s25) != '' ]] && ip addr show dev enp0s25 | sed -n -r 's@.*inet (.*)/.*brd.*@\1@p' || ip addr show dev eth0 | sed -n -r 's@.*inet (.*)/.*brd.*@\1@p'
162.243.17.224
10.13.0.5
[root@centos68 ~]# ip route get 1 | awk '{print $NF;exit}'
162.243.17.224
[root@centos68 ~]#

Fedora 24

[root@fedora24 ~]# cat /etc/redhat-release 
Fedora release 24 (Twenty Four)
[root@fedora24 ~]# [[ $(ip addr | grep enp0s25) != '' ]] && ip addr show dev enp0s25 | sed -n -r 's@.*inet (.*)/.*brd.*@\1@p' || ip addr show dev eth0 | sed -n -r 's@.*inet (.*)/.*brd.*@\1@p'
104.131.54.185
10.17.0.5
[root@fedora24 ~]# ip route get 1 | awk '{print $NF;exit}'
104.131.54.185
[root@fedora24 ~]#

It seems like that command ip route get 1 | awk '{print $NF;exit}' provided by link is more accurate, what's more, it more shorter.

Dossier answered 11/11, 2016 at 3:24 Comment(0)
T
2

I went through a lot of links (StackExchange, AskUbuntu, StackOverflow etc) and came to the decision to combine all the best solutions into one shell script.

In my opinion these two QAs are the best of seen:

How can I get my external IP address in a shell script? https://unix.stackexchange.com/q/22615

How do I find my internal ip address? https://askubuntu.com/a/604691

Here is my solution based on some ideas by rsp shared in his repository (https://github.com/rsp/scripts/).

Some of you could say that this script is extremely huge for so simple task but I'd like to make it easy and flexible in usage as much as possible. It supports simple configuration file allowing redefine the default values.

It was successfully tested under Cygwin, MINGW and Linux (Red Hat).

Show internal IP address

myip -i

Show external IP address

myip -e

Source code, also available by the link: https://github.com/ildar-shaimordanov/tea-set/blob/master/home/bin/myip. Example of configuration file is there, next to the main script.

#!/bin/bash

# =========================================================================
#
# Getting both internal and external IP addresses used for outgoing 
# Internet connections.
#
# Internal IP address is the IP address of your computer network interface 
# that would be used to connect to Internet.
#
# External IP address is the IP address that is visible by external 
# servers that you connect to over Internet.
#
# Copyright (C) 2016 Ildar Shaimordanov
#
# =========================================================================

# Details of the actual implementation are based on the following QA:
#
# How can I get my external IP address in a shell script?
# https://unix.stackexchange.com/q/22615
#
# How do I find my internal ip address?
# https://askubuntu.com/a/604691

# =========================================================================

for f in \
    "$( dirname "$0" )/myip.conf" \
    ~/.myip.conf \
    /etc/myip.conf
do
    [ -f "$f" ] && {
        . "$f"
        break
    }
done

# =========================================================================

show_usage() {
    cat - <<HELP
USAGE
  $( basename "$0" ) [OPTIONS]

DESCRIPTION
  Display the internal and external IP addresses

OPTIONS
  -i  Display the internal IP address
  -e  Display the external IP address
  -v  Turn on verbosity
  -h  Print this help and exit
HELP
    exit
}

die() {
    echo "$( basename "$0" ): $@" >&2
    exit 2
}

# =========================================================================

show_internal=""
show_external=""
show_verbose=""

while getopts ":ievh" opt
do
    case "$opt" in
    i )
        show_internal=1
        ;;
    e )
        show_external=1
        ;;
    v )
        show_verbose=1
        ;;
    h )
        show_usage
        ;;
    \? )
        die "Illegal option: $OPTARG"
        ;;
    esac
done

if [ -z "$show_internal" -a -z "$show_external" ]
then
    show_internal=1
    show_external=1
fi

# =========================================================================

# Use Google's public DNS to resolve the internal IP address
[ -n "$TARGETADDR" ] || TARGETADDR="8.8.8.8"

# Query the specific URL to resolve the external IP address
[ -n "$IPURL" ] || IPURL="ipecho.net/plain"

# Define explicitly $IPCMD to gather $IPURL using another tool
[ -n "$IPCMD" ] || {
    if   which curl >/dev/null 2>&1
    then
        IPCMD="curl -s"
    elif which wget >/dev/null 2>&1
    then
        IPCMD="wget -qO -"
    else
        die "Neither curl nor wget installed"
    fi
}

# =========================================================================

resolveip() {
    {
        gethostip -d "$1" && return
        getent ahostsv4 "$1" \
        | grep RAW \
        | awk '{ print $1; exit }' 
    } 2>/dev/null
}

internalip() {
    [ -n "$show_verbose" ] && printf "Internal: "

    case "$( uname | tr '[:upper:]' '[:lower:]' )" in
    cygwin* | mingw* | msys* )
        netstat -rn \
        | grep -w '0.0.0.0' \
        | awk '{ print $4 }'
        return
        ;;
    esac

    local t="$( resolveip "$TARGETADDR" )"
    [ -n "$t" ] || die "Cannot resolve $TARGETADDR"
    ip route get "$t" \
    | awk '{ print $NF; exit }'
}

externalip() {
    [ -n "$show_verbose" ] && printf "External: "

    eval $IPCMD "$IPURL" $IPOPEN
}

# =========================================================================

[ -n "$show_internal" ] && internalip
[ -n "$show_external" ] && externalip

# =========================================================================

# EOF
Tila answered 21/10, 2016 at 18:52 Comment(0)
K
2

Works on Mac, Linux and inside Docker Containers:

$ hostname --ip-address 2> /dev/null || (ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p' | awk '{print$1; exit}')

Also works on Makefile as:

LOCAL_HOST := ${shell hostname --ip-address 2> /dev/null || (ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p' | awk '{print $1; exit}')}

Katakana answered 2/5, 2017 at 14:54 Comment(1)
Mac don't work: hostname --ip-address => hostname: illegal option -- - on macOS SierraTaiwan
V
2

There's a node package for everything. It's cross-platform and easy to use.

$ npm install --global internal-ip-cli

$ internal-ip
fe80::1

$ internal-ip --ipv4
192.168.0.3

This is a controversial approach, but using npm for tooling is becoming more popular, like it or not.

Vientiane answered 3/6, 2018 at 22:10 Comment(0)
H
1
ifconfig | grep "inet addr:" | grep -v "127.0.0.1" | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'  | head -1
Hauger answered 21/9, 2013 at 12:32 Comment(1)
not working on macOS 10.12.6Ruffi
D
1

If you know the network interface (eth0, wlan, tun0 etc):

ifconfig eth0 | grep addr: | awk '{ print $2 }' | cut -d: -f2
Dim answered 19/2, 2015 at 20:26 Comment(0)
I
1
ifconfig $(netstat -rn | grep -E "^default|^0.0.0.0" | head -1 | awk '{print $NF}') | grep 'inet ' | awk '{print $2}' | grep -Eo '([0-9]*\.){3}[0-9]*' 
Island answered 23/9, 2016 at 15:44 Comment(0)
E
1

For linux, what you need is this command:

ifconfig $1|sed -n 2p|awk '{ print $2 }'|awk -F : '{ print $2 }'

type this in your shell and you will simply know your ip.

Ermin answered 24/7, 2017 at 7:29 Comment(1)
No. It does not work.Legalize
F
1

This is easier to read: ifconfig | grep 'inet addr:' |/usr/bin/awk '{print $2}' | tr -d addr:

Faggot answered 11/9, 2017 at 17:20 Comment(1)
not working on macOS 10.12.6Ruffi
R
1

If you have npm and node installed : npm install -g ip && node -e "const ip = require('ip'); console.log(ip.address())"

Ruffi answered 26/10, 2017 at 10:29 Comment(0)
E
0

On a Mac, consider the following:

scutil --nwi | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
Eggcup answered 8/12, 2014 at 19:17 Comment(1)
The output of scutil --nwi does not include the IP address on my Macbook running Sierra.Motorcycle

© 2022 - 2024 — McMap. All rights reserved.