Find distance between 2 IPs using BASH

In this tutorial, we will show how to calculate the distance between 2 IPs using geographical coordinates provided by any IP2Location database, except DB1, DB2, DB3, DB3 and DB7, as you can see at https://www.ip2location.com/databases

The programming language for this tutorial is BASH and you have to know a little scripting. The prerequisites for running this tutorial are:

  • You must have any distribution of Linux as Operation System
  • You must have Bash as shell
  • You must have bc installed (It comes by default with the majority of distributions)
  • You must compile a simple demo program similar with the one from the following link:https://www.ip2location.com/developers/c which just outputs latitude and longitude for one IP. The code is written in C:
#include "IP2Location.h"
 
 
int main(int argc,char**argv)
{
    if (argc!=3)
    {
        fprintf(stderr,"%s BinFile IP\n",argv[0]);
        return 0;
    }
    char *szBinFile=argv[1];
    char *szIp=argv[2];
 
    IP2Location *IP2LocationObj = IP2Location_open(szBinFile);
    if (IP2LocationObj==NULL)
    {
        fprintf(stderr,"Obj is NULL\n");
        return 0;
    }
 
    IP2LocationRecord *record = IP2Location_get_all(IP2LocationObj, szIp);
    if(record==NULL)
    {
        fprintf(stderr,"Record is NULL\n");
    }
    printf("%f,%f\n",
        record->latitude,
        record->longitude);
    IP2Location_free_record(record);
    IP2Location_close(IP2LocationObj);
    return 0;
}
  • The following steps are neccesary to compile this program:
    • Step 1: Download IP2Location_C_Library and follow the steps to compile and install it.
    • Step 2: Save the demo program shown above as ip2locationLatLong.c
    • Step 3: Compile it as ip2locationLatLong .
    • Step 4: You can run the program: ./ip2locationLatLong db5.bin 89.89.89.89

This tutorial has four steps for implementing the BASH script, that calculates the distance between 2 IPs and one for testing.

R = 6371; // km
distance = Math.acos(Math.sin(lat1)*Math.sin(lat2) +
Math.cos(lat1)*Math.cos(lat2) *
Math.cos(lon2-lon1)) * R;

 

Step 1. For the beginning of this tutorial, we will start by showing you how to calculate the distance between any 2 points knowing the latitude and longitude of the points. The formula uses The Spherical Law of Cosines, because nowadays, float is very precise. The formula for this task is the following: (The code is taken from http://www.movable-type.co.uk/scripts/latlong.html).

Step 2. We can implement this formula in Bash in the following way using bc: (bc is a precision calculator language)

EARTH_RADIUS="6371"
PI="3.141592653589793"
 
#Converts degrees in radians (
deg2rad() {
        bc -l <<< "$1 * $PI / 180"
}
 
#Converts radians in degrees
rad2deg()  {
        bc -l <<< "$1 * 180 / $PI"
}
 
#Calculates acos($radians), because bc has no acos function
acos()  {
        bc -l <<<"$PI / 2 - a($1 / sqrt(1 - $1 * $1))"
}
 
#Applies The Spherical Law of Cosines for finding distance between 2 coordinates
getDistance() {
 
    delta_lat=$(bc <<<"$LAT2 - $LAT1")
    delta_lon=$(bc <<<"$LONG2 - $LONG1")
    LAT1=$(deg2rad "$LAT1")
    LONG1=$(deg2rad "$LONG1")
    LAT2=$(deg2rad "$LAT2")
    LONG2=$(deg2rad "$LONG2")
    delta_lat=$(deg2rad "$delta_lat")
    delta_lon=$(deg2rad "$delta_lon")
 
    DISTANCE=$(bc -l <<< "s($LAT1) * s($LAT2) + c($LAT1) * c($LAT2) * c($delta_lon)")
 
    DISTANCE=$(acos "$DISTANCE")
    DISTANCE=$(bc -l <<< "$DISTANCE * $EARTH_RADIUS")
    DISTANCE=$(bc <<<"scale=4; $DISTANCE / 1")
}

Step 3. In this step, we will show how to combine the simple demo program with the BASH script and how to find the distance between two IPs, which is the goal of this tutorial. For this step, we must parse the output of ip2locationLatLong program with cut.

#!/bin/bash
 
#This is the location of bin file
#You must modify for your system
BIN_FILE="db5.bin"
 
 
EARTH_RADIUS="6371"
PI="3.141592653589793"
 
#Converts degrees in radians (
deg2rad() {
        bc -l <<< "$1 * $PI / 180"
}
 
#Converts radians in degrees
rad2deg()  {
        bc -l <<< "$1 * 180 / $PI"
}
 
#Calculates acos($radians), because bc has no acos function
acos()  {
        bc -l <<<"$PI / 2 - a($1 / sqrt(1 - $1 * $1))"
}
 
#Applies The Spherical Law of Cosines for finding distance between 2 coordinates
getDistance() {
 
    delta_lat=$(bc <<<"$LAT2 - $LAT1")
    delta_lon=$(bc <<<"$LONG2 - $LONG1")
    LAT1=$(deg2rad "$LAT1")
    LONG1=$(deg2rad "$LONG1")
    LAT2=$(deg2rad "$LAT2")
    LONG2=$(deg2rad "$LONG2")
    delta_lat=$(deg2rad "$delta_lat")
    delta_lon=$(deg2rad "$delta_lon")
 
    DISTANCE=$(bc -l <<< "s($LAT1) * s($LAT2) + c($LAT1) * c($LAT2) * c($delta_lon)")
 
    DISTANCE=$(acos "$DISTANCE")
    DISTANCE=$(bc -l <<< "$DISTANCE * $EARTH_RADIUS")
    DISTANCE=$(bc <<<"scale=4; $DISTANCE / 1")
}
 
#Retrieves the coordinates for the 2 IPs
getCoordinate()
{
    #Call ip2locationLatLong for $IP1
    output=$(./ip2locationLatLong "$BIN_FILE" "$IP1")
 
    #Parse the output to obtain both coordinates
    LAT1=$(echo "$output" | cut -d ',' -f 1)
    LONG1=$(echo "$output" | cut -d ',' -f 2)
 
    #Call ip2locationLatLong for $IP2
    output=$(./ip2locationLatLong "$BIN_FILE" "$IP2")
 
    #Parse the output to obtain both coordinates
    LAT2=$(echo "$output" | cut -d ',' -f 1)
    LONG2=$(echo "$output" | cut -d ',' -f 2)
}
 
#Prints the coordinates for the 2 IPs
printCoordinate()
{
    echo "Coordinates for $IP1: ($LAT1,$LONG1)"
    echo "Coordinates for $IP2: ($LAT2,$LONG2)"
}
 
#Checks if the coordinates are not empty
validCoord()
{
    ip=$1
    coord=$2
 
    if [ "$coord" = "" ]; then
        echo "$ip is not a good address"
        exit 0
    fi
}
 
#Checks if the script is run with 2 parameters
if [ $# -ne 2 ]; then
    echo "Usage: $(basename $0) IP1 IP2"
    exit 0;
fi
 
IP1=$1
IP2=$2
 
#Retrieves and validates the coordinates
getCoordinate
printCoordinate
validCoord $IP1 $LAT1
validCoord $IP1 $LONG1
validCoord $IP2 $LAT2
validCoord $IP2 $LONG2
 
#Calculate and print the distance
getDistance
echo "Distance between $IP1 and $IP2 is $DISTANCE km"

Step 4. You can now run the script.

bash getDistance.sh 89.89.89.89 30.13.56.34

 

Step 5. You can validate the output distance running the script from http://www.movable-type.co.uk/scripts/latlong.html which calculates the distance between two points.

Was this article helpful?

Related Articles