IP of localhost

76,655

Solution 1

The information can change at any time, so it needs to be retrieved from the kernel, it can't be stored in a file.

There is no really nice way to obtain this information. Your parsing is as good as any, except that hard-coding the second line is wrong: there is no guarantee that the interfaces will be listed in any particular order. It is fairly common for a machine to have more than one interface: you may have multiple network cards, or virtual interfaces.

Often, the IP address you're interested in is the one associated with the default route. With most configurations, you can obtain the right interface with the route command, then extract the IP address of that interface with ifconfig.

/sbin/ifconfig $(/sbin/route -n |
                 awk '$1 == "0.0.0.0" {print $8}') |
awk 'match($0, /inet addr:[.0-9]+/) {print substr($0, RSTART+10, RLENGTH-10)}'

Note that there is no need to call sudo. ifconfig and route are often not in the default PATH for non-root users, but you can use them with no special privilege as long as you're only reading information and not changing the settings.

On unix variants other than Linux, you may have to tweak the commands above. Most have commands called ifconfig and route, but the output format may be different.

Under Linux, instead of ifconfig and route, you can use the ip command from the iproute2 tool suite. While the authors of iproute2 consider ifconfig and route to be deprecated, there is in fact little advantage to using ip, since the output of ip is not markedly easier to parse, and ifconfig and route are always available whereas some stripped-down Linux installations omit ip.

Solution 2

There are a fundamental flaws with your question. Firstly, hosts may (and likely will) have more than one address (e.g., multiple interfaces) and even more than one address per interface. This is even more of an issue with IPv6 where every globally connected host as at least two addresses.

Secondly, the "best" way to do this from a shell will vary from system to system.

Linux:

/sbin/ip addr show eth0 | awk -F"[ /]+" '/inet / {print $3}'

>= Solaris 11:

ipadm show-addr net0/v4 | awk -F"[ /]+" '/ok/ {print $5}'

Mac OS X/Darwin:

ipconfig getifaddr en0

Even going lowest common denominator and using ifconfig won't be consistent because the output format may change. However, to clean up your example, use this:

ifconfig eth0 | awk -F"[ :]+" '/inet / {print $4}'

If you're using a fancier language like perl, ruby, java, etc., instead of the shell, each language will have its own way of obtaining this data from the kernel. I'll leave finding this up to you.

Solution 3

All the answers here are technically correct, but they're not what I would consider the "right" answer. Unfortunately, your question is extremely vague (which I can understand if you're not really good with how networking in Linux works), so I'll give some answers to possible interpretations of the question.


The machine's primary IP

The machine has one IP above all others which is considered the machines primary IP. Note though that this is pretty meaningless, as a box can have multiple IPs and which one gets used varies (I'll get into this in a bit).

The primary IP is simply the IP associated with the machine's hostname. You can find this IP by running the following

getent hosts "$(hostname)" | awk '{ print $1 }'

Now, what this does is looks up the IP for the machine's hostname according to /etc/nsswitch.conf. In most cases, the /etc/nsswitch.conf file contains hosts: files dns. This means that when trying to do any sort of hostname or address lookups, it will look in /etc/hosts first, and then consult DNS (as configured by /etc/resolv.conf).
So the command getent hosts "$(hostname)" will likely grab the matching entry from /etc/hosts. The awk simply just grabs just the IP out of that line.

(getent is just a simple utility for querying 'databases' listed in /etc/nsswitch.conf)


The IP used to communicate with the outside world

As I mentioned earlier, the machine's primary IP is fairly meaningless. The machine can use any of multiple IPs for communication. In your case, you likely just have one interface and one (non-localhost) IP. However a server can have multiple interfaces or IPs (sometimes multiple IPs on a single interface).
Which IP gets used is determined by the kernel's routing table. I'm not going to get into the specifics of how the routing table works as its not simple (there's multiple routing tables, and which one gets used is dependent upon table selection rules). I'll just tell you how to find which IP would get used.

To find out which IP will be used to communicate with a specific destination, use the following command:

ip route get 1.2.3.4

(with 1.2.3.4 being the IP of the destination)

On my machine, if I do this with one of google.com's IPs (74.125.139.102), I get the following:

74.125.139.102 via 192.168.0.1 dev wlan0  src 192.168.0.24 
    cache 

What this tells me is that the IP 192.168.0.24 will be used whenever my machine goes to talk to 74.125.139.102.

If you want just the IP, you can just throw an extra grep on the end.

ip route get 1.2.3.4 | grep -oP '(?<=src )\S+'

grep is used instead of an awk because it's less prone to error. It's possible the line may change in which the IP won't be in the same place, but it will always follow "src", so we just grab the value immediately after "src"


Default gateway IP

Lastly, there's the default gateway. If you don't have a specific destination to query to see which IP will be used, you can pick the one from the default gateway. If you only have one interface, this is all that'll matter anyway.
This is basically the exact same thing as above, just using the default gateway as our destination to look up

ip route get "$(ip route show to 0/0 | grep -oP '(?<=via )\S+')"

This will give you a line like the one in the above section. The src value is the IP that will be used for traffic flowing through the default gateway.

As in the previous section, to get just the IP, add a grep.

ip route get "$(ip route show to 0/0 | grep -oP '(?<=via )\S+')" | grep -oP '(?<=src )\S+'

Solution 4

Your request is ambiguos, usually with the word "localhost" people mean the loopback interface and 127.0.0.1 is the most common and right answer.

What you are missing is:

  • the fact that every interface can have a different IP, the loopback interface is a network interface just like your ethernet card or your wireless usb receiver.
  • as consequence a single PC does not have a single IP, it all depends on what interface are you considering and how many interfaces you are using under your OS.

You are probably interested in the topic "Kernel routing tables" which is a good way to start understanding how the kernel handles your networking activity.

Share:
76,655

Related videos on Youtube

Emanuel Berg
Author by

Emanuel Berg

Emanuel Berg Hire me! Programmer, Swedish university degree in Computer Science. computer projects (includes CV, letters, code, screenshots) internet activity (where to find me) Check out some of my Unix &amp; Linux tech writing.

Updated on September 18, 2022

Comments

  • Emanuel Berg
    Emanuel Berg over 1 year

    How does a Linux instance determine its IP address?

    That is, not the 127.0.0.1.

    Is this stored in file or does ifconfig somehow calculate it at every invocation?

    I managed to solve it just to show I made an effort, but it is not anything I'd put in a serious application:

    sudo ifconfig | head -n 2 | tail -n 1 | tr -s " " | tr " " ":" | cut -d":" -f 4
    
    • Admin
      Admin almost 12 years
      Nitpicking: 127.0.0.1 is an IP address like all others. It's only special by convention and because it's assigned to the loopback interface. Other than that, it's configured the same way as addresses on hardware.
    • Admin
      Admin almost 12 years
      @Alexios: What you say is, the title reads out "What is the IP of 127.0.0.1?"
    • Admin
      Admin almost 12 years
      It is 127.0.0.2 or 127.0.0.3 or 127.0.1.17 or ... Any address starting with 127.x.y.z will connect to the localhost.
    • Admin
      Admin almost 12 years
      jippie: Right. Though only because we assign subnet 127.0.0.0/8 to lo. Again, convention. Emanuel: yes, though it seems people got the spirit of the question. Perhaps asking about the IP address of the local host (not localhost) would explain better. Though hosts don't have addresses. Interfaces have addresses, and possibly more than one (possibly more than two in IPv6).
  • Emanuel Berg
    Emanuel Berg almost 12 years
    OK, there was an edit to my post. Maybe it is better now. See my comment to Ignacio Vazquez-Abram's answer below. I have a software server and I reach it with localhost. Obviously it only works when I'm online so then I'd like to mail my friends and urge them to test it, so I thought a command to just echo that number. But I appreciate emphasis on correct terminology.
  • bahamat
    bahamat almost 12 years
    You misunderstood. Your fundamental flaw is that you assume that each host has one address. This is not the case. But I do hope that this is useful for you.
  • Emanuel Berg
    Emanuel Berg almost 12 years
    Well, that assumption was implicit to say the least. But, let's not waste time on that. What do you call the digits you put in a browser URL field to reach, in my case, /var/www/index.html? Yes, your answer is useful.
  • bahamat
    bahamat almost 12 years
    Generally speaking, you can use any global IP address on your host to connect to the web server. If you have 5 interfaces and apache is bound on all 5 then you can use any of the 5 addresses you prefer. I'm just saying to watch out because there may be more than one.
  • Simon Gates
    Simon Gates almost 12 years
    +1. In the Linux invocation, I'd use /inet6? / to catch IPv6 (inet6) as well as IPv4 addresses (inet). Matter of taste, of course. Also, I wouldn't really call Perl, Ruby and Java shells.
  • bahamat
    bahamat almost 12 years
    @Alexios: no, those were examples of non-shells.
  • phemmer
    phemmer over 11 years
    I consider the output of ip to be immensely easier to parse than ifconfig (but this is just opinion). Also the output values of ip are always the same format as is used for input (making scripting very easy). However ip does have one major bit of functionality that ifconfig does not. Run ip addr add 1.2.3.4/32 dev eth0 (or an interface which already has an IP), and then try and see that IP with ifconfig. ifconfig won't show it, while ip addr will.
  • Emanuel Berg
    Emanuel Berg over 11 years
    Great post! I had to make a small modification to make it print only the IP: ip route get "$(ip route show to 0/0 | grep -oP '(?<=via )\S+')" | head -n 1 | awk '{ print $5 }' I don't know how this differs from Gilles' solution, so I'll just keep both.
  • phemmer
    phemmer over 11 years
    @EmanuelBerg Gilles' solution is basically the same thing as the Default gateway IP solution in my answer. Just a different way of getting the info. Also while an awk does work to get just the IP, I would use a grep instead. It's less prone to breakage (edited my answer to provide an example)
  • derobert
    derobert over 11 years
    ip does so many things that ifconfig/route can't do, that its not funny. Advanced routing (rules, multiple routing tables, etc.), network namespaces, multiple IPs per interface, neighbor tables, tunnels, IPSec policies,… Not important on your average desktop, matters quite a bit with interesting router & firewall setups.
  • derobert
    derobert over 11 years
    As long as we're eliminating assumptions, there are two more than need to go. (1) that there is one default gateway (there can be zero or more, I personally have managed a machine with Internet connectivity and zero default gateways as it ran BGP, and currently manage one with two default gateways); (2) the default gateway doesn't depend on the source address. That machine selects its default gateway based in part on source IP address.
  • phemmer
    phemmer over 11 years
    @derobert (1) can be solved by putting a -m 1 on the grep for ip route show to 0/0. (2) You contradicted yourself. First you say it doesn't depend on source address, then you say its based on source address :-). Unless you bind to a specific source IP, the source IP is chosen based on the next-hop (this is why you look up the gateway first and the source IP second). The ip route command uses the routing tables to determine both next-hop and source IP.
  • phemmer
    phemmer over 11 years
    or I should say that (1) can be solved in the case of multiple default routes. In the case of no default routes, well ya, not going to work at all there :-P
  • derobert
    derobert over 11 years
    @Patrick Packets forwarding through the box already have a source address. Even for locally originated packets, the default route can be picked in interesting ways, for example by the iptables mangle OUTPUT chain setting a fwmark.
  • phemmer
    phemmer over 11 years
    @derobert yes that is true (the forwarding caveat), however I would expect that to behave exactly the same as if an application sending traffic from the local box had bound to a specific IP. Though my answer wasn't considering forwarded traffic at all, just local traffic. Also good point on the iptables rule. I don't know if this impacts the results of ip route get or not, but I would expect not (doubt it's that smart).
  • IgorGanapolsky
    IgorGanapolsky almost 8 years
    Why is it that when I run route PRINT, it prints Gateway Interface 172.31.98.1 172.31.98.19? But when I go to whatismyip.com it prints 198.179.93.195.
  • IgorGanapolsky
    IgorGanapolsky almost 8 years
    But localhost cannot have more than one ip address, right? It is always 127.0.0.1
  • IgorGanapolsky
    IgorGanapolsky almost 8 years
    So how is localhost's ip address determined? I mean, what sets it to 127.0.0.1.
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' almost 8 years
    @IgorGanapolsky NAT. The 172.31.* addresses are for use in an internal network.
  • IgorGanapolsky
    IgorGanapolsky almost 8 years
    @Gilles Makes sense, as I was sitting in Starbucks on their WiFi...
  • bahamat
    bahamat almost 8 years
    No. It will likely also have ::1, the IPv6 localhost address. But even with IPv4, 127.0.0.0/8 is defined as localhost. It is not unusual for any address within that range to be on the loopback interface.