A colleague just asked me how do I get the IP address of the server this script is running on?, which a great question. You can do it in Python but it's a bit of a hassle and as is often the case, it's really easy to do this in bash. I came up with this off the top of my head. It's not the best way to do it but it works nicely and it's very clear so I figured it would be a nice example to show. (I have a few alternative implementation as well but if you have a neat one I'd love to see it in the comments)
ifconfig |grep "inet addr" |grep -v "127.0.0.1" |awk '{ print $2 }' |cut -d ":" -f 2
What I especially like about it is that it really shows off the approach of combining simple and powerful programs that is at the heart of the UNIX philosophy. So much software today tries to solve every conceivable problem and address every possible use case. In contrast, each of the programs above does a specific job very well and it was up to the user (me, in this case) to put them together to achieve the desired result. If we accept that there should be a learning curve to use software then we can make it much simpler (and thus secure, reliable and enjoyable) by letting the user shoulder some of the burden of the interaction. I'll talk about this in more detail at some point here because it's something that's been on my mind for a while.
So let's run through this step by step.
ifconfig
This command is used to configure your network interfaces. With no arguments it will list information about the interfaces you have connected and part of that information is the IP address! It will typically output something like this:
eth0 Link encap:Ethernet HWaddr 00:1a:a0:96:5b:cb
inet addr:192.168.2.162 Bcast:192.168.2.255 Mask:255.255.255.0
inet6 addr: fe80::21a:a0ff:fe96:5bcb/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:139351 errors:0 dropped:0 overruns:0 frame:0
TX packets:92329 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
RX bytes:91510049 (91.5 MB) TX bytes:17897244 (17.8 MB)
Memory:fdfc0000-fdfe0000
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:10766 errors:0 dropped:0 overruns:0 frame:0
TX packets:10766 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:7603756 (7.6 MB) TX bytes:7603756 (7.6 MB)
Your machine have more than one eth
adapter and you may have
wireless adapters as well. In amongst this information, you can see
the IP addresses are listed on lines that start with inet addr:<IP address>
. Now we know the format, we can use some UNIX tools to pull
it out.
|
The |
symbol is read as "pipe" and means "use the ouput of the last
command as the input of the next". We use this between each command to
refine our result.
grep "inet addr"
This command filters the output from ifconfig. In this case we're saying we only want lines that include inet addr. So this grep command takes the output I have shown above and filters it into something that looks like the following:
inet addr:192.168.2.162 Bcast:192.168.2.255 Mask:255.255.255.0
inet addr:127.0.0.1 Mask:255.0.0.0
The next step is to filter this still further.
grep -v "127.0.0.1"
Here I use grep's -v
option, which inverts the filtering. In this
case, I am saying only consider lines that do not contain
127.0.0.1
. I am doing this because 127.0.0.1
is localhost. All
computers have this IP address automatically so it isn't that useful
to know about this one. I want to exclude this from the output so we
only show interesting IP addresses.
We have now filtered the output to the following:
inet addr:192.168.2.162 Bcast:192.168.2.255 Mask:255.255.255.0
Now for the trickiest bit!
awk '{ print $2 }'
awk is a tool for matching and processing patterns in text. Here I'm
using it in its simplest form to simply say "print the second
field". Fields are automatically created by looking at the spacing and
you can see that in this case we have some space then inet then a
little space and then adr:192.168.2.162
and so on. We ask awk to
give us just that second field, which contains the IP address we are
after. An awk command will be applied separately to every line it is
given so if we had two IP addresses here, awk would give us the
correct field for both.
addr:192.168.2.162
Now we're getting close!
cut -d ":" -f 2
In this last step, we use the cut command to split the input on the
:
character (the delimiter is specified using -d
) and give us the
resulting 2nd field (the field is specified with the -f
argument. (We could have used awk again but it's nice to see a few
different commands at work :) )
192.168.2.162
Make a bash alias
I have set this up as an alias so I can type myip
from the shell to
see my IP address(es). You can do the same by putting this line in
your ~/.bash_aliases
file or in some other location where it will be
run automatically.
alias myip='ifconfig |grep "inet addr" | grep -v "127.0.0.1"| awk '{ print $2 }' | cut -d ":" -f 2'
Enjoy!