Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!

Geolocate a number of IP addresses via shell script UNIX
From time to time I like to know (when reviewing log files) where an IP address is geographically located. The following shell script will take a list of IP address in a file named list, and look up their geographic location. Here's the code:
#!/bin/bash
echo "Put the IPs you want to lookup into a file named list."

url="http://www.geoiptool.com/en/?IP="
for i in `cat list`
do
lynx -dump $url$i > tmp
cat tmp | sed -n '/Host Name/,/Postal code/p'
rm tmp
done
Usage:
jamesk@HOME~/Desktop $ echo 198.6.1.5 > list
jamesk@HOME~/Desktop $ geo
Put the IPs you want to lookup into a file named list.
      Host Name: cache04.ns.uu.net
     IP Address: 198.6.1.5
        Country: [14]United States united states
   Country code: US (USA)
         Region: [15]Oregon
           City: Eugene
    Postal code:
[robg adds: Note that this hint requires the lynx text-only web browser, which you can install via Fink or MacPorts or probably many other methods. I'm sure there's probably a way to do this without lynx, but I'll leave that to those who actually know what they're doing...]
    •    
  • Currently 1.95 / 5
  You rated: 4 / 5 (19 votes cast)
 
[16,572 views]  

Geolocate a number of IP addresses via shell script | 13 comments | Create New Account
Click here to return to the 'Geolocate a number of IP addresses via shell script' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
Geolocate a number of IP addresses via shell script
Authored by: goatbar on Jan 13, '10 09:07:14AM
Geolocate a number of IP addresses via shell script
Authored by: alblue on Jan 13, '10 09:16:53AM

Why on earth would you want to cat arguments to a random file called 'list' before doing anything on them?

Just change it to:

for i in $*

and the run it as:

geo 127.0.0.1 127.0.0.2 ...

Alex



[ Reply to This | # ]
Geolocate a number of IP addresses via shell script
Authored by: alblue on Jan 13, '10 09:57:11AM
Here's a better version, which doesn't write to any files. It also only relies on programs that are already installed on all Mac OS X machines, not extra downloads.
#!/bin/bash

for IP in $*
do
  curl -s http://www.geoiptool.com/en/?IP=${IP} | textutil -convert txt -stdin -stdout -format html | sed -n '/Host Name/,/Postal code/p' 
done


[ Reply to This | # ]
Geolocate a number of IP addresses via shell script
Authored by: ctierney on Jan 13, '10 10:18:20AM

Almost all. I don't have textutil on 10.3.9.



[ Reply to This | # ]
Geolocate a number of IP addresses via shell script
Authored by: afb on Jan 14, '10 12:10:32AM
This seems to leave out data. I get this for the IP in the hint:

Host Name:
cache04.ns.uu.net
IP Address:
198.6.1.5
Country:
United States 
Country code:
US (USA)
Region:
Oregon
City:
Eugene
Postal code:


[ Reply to This | # ]
Geolocate a number of IP addresses via shell script
Authored by: jolohaga on Jan 13, '10 09:50:08AM

Nice idea. I wanted it to work without temp files, as a one liner, and with only default Mac OS X apps (curl instead of lynx). I also use Ruby to strip the HTML. The result is below. (I use the TCSH shell, but modifying for Bash should be trivial.) I made an alias of the command and pass it the IP addr argument as variable \!:1. In .tcshrc you would define it as:

alias ip_location 'curl "http://www.geoiptool.com/en/?IP=\!:1" | sed -n "/Host\ Name/,/Postal\ code/p" | ruby -
e "puts STDIN.read.gsub(/<\/?[^>]*>/,nil.to_s)"'

You can name it anything you want. I happen to name it ip_location.



[ Reply to This | # ]
Geolocate a number of IP addresses via shell script
Authored by: alblue on Jan 13, '10 10:59:14AM

textutil is installed on all macs, and can convert between html and text pretty easily.

[edit] From 10.4 onwards ;-) I think it uses the same parsing libraries that Apple uses to read .docx stuff, too.

                   fmt is one of:  txt, html, rtf, rtfd, doc, docx, wordml,
                                   odt, or webarchive

HISTORY
     The textutil command first appeared in Mac OS X 10.4.
Edited on Jan 13, '10 11:01:49AM by alblue


[ Reply to This | # ]
Geolocate a number of IP addresses via shell script
Authored by: ctierney on Jan 13, '10 10:09:20AM
Thanks for the hint. I look forward to including this in my work flow! Here's a version that reads from stdin, fetches with curl, and parses with awk:
#!/bin/sh
while read ip; do
    curl -s 'http://www.geoiptool.com/en/?IP='$ip | \
    awk -F '(</?[^>]+>)+' '/Host Name/,/Postal code/ {
        if (/:/) {printf("%13s ", $2); getline; print $2}
    } END {print}'
done


[ Reply to This | # ]
Geolocate a number of IP addresses via shell script
Authored by: tobylane on Jan 14, '10 08:05:57AM

It just hangs me for, for three minutes before I stopped it.



[ Reply to This | # ]
Geolocate a number of IP addresses via shell script
Authored by: ctierney on Jan 14, '10 08:28:28AM
It's reading from stdin, so it will appear to hang if you don't feed it any ip numbers. I named mine ip2geo:
echo 198.6.1.5 | ip2geo


[ Reply to This | # ]
Geolocate a number of IP addresses via shell script
Authored by: mdfischer on Jan 14, '10 09:31:08AM

A bit more involved than some the elegant one liners, but handles entries from stdin, a file or the command arguments, and formats the results a bit better.

<snip>
#! /bin/sh

if test $1 = -h
then
echo 'Usage: geoloc [[-f file] | [IP list]]'
echo '(reads list of IP numbers from STDIN if no argument)'
exit 0
fi

if test $# = 1
then
curl http://www.geoiptool.com/en/?IP=$1 2>/dev/null | awk '
/<td.*>(Host Name|IP Address|Country|Region|City|Postal|Calling|Longitude|Latitude)/ {
record="t";gsub("[\t ]*<[^>]*>",""); printf("%-13s ",$0);next;
}
record == "t" { gsub("[\t ]*<[^>]*>[\t ]*","");print $0;record="f";next}
{next}
END{print ""}
'
else
if test $# = 0;then flist=`cat`
elif test "$1" = -f; then flist=`cat $2`
else flist=$*
fi
for i in $flist
do
sh $0 $i
done
fi
exit

This script uses www.geoiptool.com to look up geolocation information for
IP numbers. You can suppress fields by removing them from the line
Host Name|IP Address|Country|Region|City|Postal|Calling|Longitude|Latitude
in Line 5 above.

I have named the command file geoloc. You can name it whatever. Syntax is

geoloc [[-f file] | IP list]]
(reads list of IP numbers from STDIN if no argument)

It should work on any standard Unix or Linux system with curl installed
as well as Mac OS X which includes curl in System 10.5. You will have to download
and install curl if you do not have it. You can find binaries for most systems at
http://curl.haxx.se/download.html
</snip>



[ Reply to This | # ]
Geolocate a number of IP addresses via shell script
Authored by: jrobert on Jan 20, '10 08:44:47AM
Very useful. This version (only the first 'if' test is changed) will keep it from tripping over itself if no args are typed and make no args synonymous with the -h flag:
#! /bin/sh

if test $# = 0 || test "$1" = "-h"
then
    echo 'Usage: geoloc [[-f file] | [IP list]]'
    echo '(reads list of IP numbers from STDIN if no argument)'
    exit 0
fi

if test $# = 1
then
    curl http://www.geoiptool.com/en/?IP=$1 2>/dev/null | awk '
/<td.*>(Host Name|IP Address|Country|Region|City|Postal|Calling|Longitude|Latitude)/ {
record="t";gsub("[\t ]*<[^>]*>",""); printf("%-13s ",$0);next;
}
record == "t" { gsub("[\t ]*<[^>]*>[\t ]*","");print $0;record="f";next}
{next}
END{print ""}
'
else
    if test $# = 0;then flist=`cat`
    elif test "$1" = -f; then flist=`cat $2`
    else flist=$*
    fi
    for i in $flist
    do
	sh $0 $i
    done
fi
exit


[ Reply to This | # ]
I prefer to use curl over lynx
Authored by: xargs on Jul 13, '10 10:21:28PM

A handy script, thanks!

I've adapted your script to use curl rather than lynx and removed the need to handle a temp file:

curl -s "http://www.geoiptool.com/en/?IP=${IP}" | 
textutil -stdin -format html -stdout -convert txt | 
sed -n "/Host Name/,/Postal code/p"

(This script requires the variable IP to be set)



[ Reply to This | # ]