Home » Linux » Linux bash script to extract IP address

Linux bash script to extract IP address

Posted by: admin November 29, 2017 Leave a comment

Questions:

I want to make big script on my Debian 7.3 ( something like translated and much more new user friendly enviroment ). I have a problem. I want to use only some of the informations that commands give me. For example my ifconfig looks like:

eth0      Link encap:Ethernet  HWaddr 08:00:27:a3:e3:b0  
          inet addr:192.168.1.103  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::a00:27ff:fea3:e3b0/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1904 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2002 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:1309425 (1.2 MiB)  T

I want to display only the IP address in line: echo “Your IP address is: (IP_ADDRESS )”. Is there any command that allow me to do such a thing, to search in stream for informations I want to get?. I know about grep and sed but I am not really good with them.

Edit: Firstly to say thank you for helping me with this problem, now I know much more. Secondly to say project is in progress. If anyone would be interested in it just pm me.

Answers:

To just get your IP address:

echo `ifconfig eth0 2>/dev/null|awk '/inet addr:/ {print $2}'|sed 's/addr://'`

This will give you the IP address of eth0.

Edit: Due to name changes of interfaces in recent versions of Ubuntu, this doesn’t work anymore. Instead, you could just use this:

hostname --all-ip-addresses or hostname -I, which does the same thing (gives you ALL IP addresses of the host).

Questions:
Answers:

ifconfig eth0 is not a good solution for all.

If the interface you have has another name, or if you have more than one interface, this will fail.

So to get the IP and interface that is used to communicate, do this:

ip route get 8.8.8.8
8.8.8.8 via 10.10.10.1 dev eno1 src 192.168.3.33
    cache

Then to get your IP, you can do:

ip route get 8.8.8.8 | awk 'NR==1 {print $NF}'
192.168.3.33

ip route does not open any connection out, it just shows the route needed to get to 8.8.8.8. 8.8.8.8 is Google’s DNS.


Why is this the best way to do it?

  1. Hostname -I sometimes get only the IP or as on my VPS it gets 127.0.0.2 143.127.52.130 2a00:dee0:ed3:83:245:70:fc12:d196
  2. Hostname -I does not work on all systems.
  3. Using ifconfig may not always give the IP you like.
    a. It will fail if you have multiple interfaces (wifi/ethernet) etc.
    b. Main IP may not be on the first found interface
  4. Searching of eth0 may fail if the interfaces have other name as in VPS server or wifi or newer Ubuntu

In Wily Werewolf, starting with systemd/udev will automatically assign predictable, stable network interface names for all local Ethernet, Wlan and Wwan interfaces.

The following different naming schemes for network interfaces are now supported by udev natively:

1) Names incorporating Firmware/BIOS provided index numbers for on-board devices (example: eno1)
2) Names incorporating Firmware/BIOS provided PCI Express hotplug slot index numbers (example: ens1)
3) Names incorporating physical/geographical location of the connector of the hardware (example: enp2s0)
4) Names incorporating the interfaces's MAC address (example: enx78e7d1ea46da)
5) Classic, unpredictable kernel-native ethX naming (example: eth0) - depreciated

If you like to store this into a variable, do:

my_ip=$(ip route get 8.8.8.8 | awk '/8.8.8.8/ {print $NF}')

my_interface=$(ip route get 8.8.8.8 | awk '/dev/ {f=NR} f&&NR-1==f' RS=" ")

Questions:
Answers:

If you want to get a space separated list of your IPs, you can use the hostname command with the --all-ip-addresses (short -I) flag

hostname -I

as described here: Putting IP Address into bash variable. Is there a better way?

Questions:
Answers:
ip -4 addr show eth0 | grep -oP "(?<=inet ).*(?=/)"

Questions:
Answers:

Take your pick:

$ cat file
eth0      Link encap:Ethernet  HWaddr 08:00:27:a3:e3:b0
          inet addr:192.168.1.103  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::a00:27ff:fea3:e3b0/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1904 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2002 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:1309425 (1.2 MiB)  T

$ awk 'sub(/inet addr:/,""){print $1}' file
192.168.1.103

$ awk -F'[ :]+' '/inet addr/{print $4}' file
192.168.1.103

Questions:
Answers:
  /sbin/ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'

Questions:
Answers:

Just a note, since I just spent some time trouble-shooting a botched upgrade on a server.
Turned out, that (years ago) I had implemented a test to see if dynamically added interfaces (e.g. eth0:1) were present, and if so, I would bind certain proggis to the ‘main’ IP on eth0. Basically it was a variation on the ‘ifconfig|grep…|sed… ‘ solution (plus checking for ‘eth0:’ presence).

The upgrade brought new net-tools, and with it the output has changed slightly:

old ifconfig:

eth0      Link encap:Ethernet  HWaddr 42:01:0A:F0:B0:1D
          inet addr:10.240.176.29  Bcast:10.240.176.29  Mask:255.255.255.255
          UP BROADCAST RUNNING MULTICAST  MTU:1460  Metric:1
          ...<SNIP>

whereas the new version will display this:

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1460
      inet 10.240.212.165  netmask 255.255.255.255  broadcast 10.240.212.165
      ...<SNIP>

rendering the hunt for ‘eth0:’ as well as ‘inet addr:’ search busted (never mind interfaces called ’em0′,’br0′ or ‘wlan0’…). Sure you could check for ‘inet ‘ (or ‘inet6’), and make the addr: part optional, but looking closer, you’ll see that more or less everything has changed, ‘Mask’ is now ‘netmask’,…

The ‘ip route …’ suggestion’s pretty nifty – so maybe:

_MyIP="$( ip route get 8.8.8.8 | awk 'NR==1 {print $NF}' )"
if [ "A$_MyIP" == "A" ]
then
    _MyIPs="$( hostname -I )"
    for _MyIP in "$_MyIPs"
    do
        echo "Found IP: \"$_MyIP\""
    done
else
    echo "Found IP: $_MyIP"
fi

Well, something of that sort anyway. Since all proposed solutions seem to have circumstances where they fail, check for possible edge cases – no eth, multiple eth’s & lo’s, when would ‘hostname -i’ fail,… and then decide on best solution, check it worked, otherwise 2nd best.

Cheers ‘n’ beers!

Questions:
Answers:
ip route get 8.8.8.8| grep src| sed 's/.*src \(.*\)$//g'

Questions:
Answers:

May be not for all cases (especially if you have several NIC’s), this will help:

hostname -I | awk '{ print $1 }'

Questions:
Answers:

In my opinion the simplest and most elegant way to achieve what you need is this:

ip route get 8.8.8.8 | tr -s ' ' | cut -d' ' -f7

ip route get [host] – gives you the gateway used to reach a remote host e.g.:

8.8.8.8 via 192.168.0.1 dev enp0s3  src 192.168.0.109

tr -s ' ' – removes any extra spaces, now you have uniformity e.g.:

8.8.8.8 via 192.168.0.1 dev enp0s3  src 192.168.0.109

cut -d' ' -f7 – truncates the string into ‘ ‘space separated fields, then selects the field #7 from it e.g.:

192.168.0.109