10

I am trying to write a bash script to get all IP addresses on a server. The script should work on all major distros. Here is what I have:

ifconfig | grep 'inet addr:' | awk {'print $2'}

Resulting in:

addr:10.1.2.3
addr:50.1.2.3
addr:127.0.0.1

How can I first remove the addr: prefix? Second, how I can exclude 127.0.0.1?

Asclepius
  • 57,944
  • 17
  • 167
  • 143
Justin
  • 42,716
  • 77
  • 201
  • 296
  • not sure if my answer is of help for you, but do you know how to accelerate my little script below ? - it would last at least 5 hours to run through. – dschinn1001 Oct 09 '13 at 19:25

12 Answers12

17

ifconfig was obsoleted by ip. It also has the flag -o that write outputs easy to parse. Use ip -4 to show only IPV4 addresses. Note the simpler script, it already exclude the loopback address:

ip -o addr | awk '!/^[0-9]*: ?lo|link\/ether/ {print $2" "$4}'

Or if you don't want the networks:

ip -o addr | awk '!/^[0-9]*: ?lo|link\/ether/ {gsub("/", " "); print $2" "$4}'
Pedro Lacerda
  • 1,098
  • 9
  • 23
7

There's no need for grep. Here's one way using awk:

List only addr:

ifconfig | awk -F "[: ]+" '/inet addr:/ { if ($4 != "127.0.0.1") print $4 }'

List device and addr:

ifconfig | awk -v RS="\n\n" '{ for (i=1; i<=NF; i++) if ($i == "inet" && $(i+1) ~ /^addr:/) address = substr($(i+1), 6); if (address != "127.0.0.1") printf "%s\t%s\n", $1, address }'
Asclepius
  • 57,944
  • 17
  • 167
  • 143
Steve
  • 51,466
  • 13
  • 89
  • 103
  • How hard would it be, to get the `device` eth0, eth1, etc, along with the ip-address? – Justin Sep 21 '12 at 03:52
  • I would change the `awk` part like this: `ifconfig | awk -F "[: ]+" '/inet addr:/ && $4 != "127.0.0.1" { print $4 }'` (if is not required) --- You can also use `-F":| +"` as a delimiter. – Yaron Mar 31 '15 at 08:06
7

Simply using hostname you can get a list of all your IP addresses, using the -I flag.

i.e.

$ hostname --all-ip-addresses || hostname -I
10.10.85.100 10.20.85.100 10.30.85.100

whereas

$ hostname --ip-address || hostname -i
::1%1 127.0.0.1

Centos7 (k3.10.0)

Matt Clark
  • 27,671
  • 19
  • 68
  • 123
  • 1
    The man page warns `Do not make any assumptions about the order of the output.` That doesn't matter in the scope of the question, but it could matter if you want to use the first IP in the output and assume it is eth0. – jimp Jan 03 '17 at 21:43
  • Hmm, doesn't seem very portable. I see this works on Ubuntu because `hostname` is provided by the independent package `hostname`, but on Arch `hostname` is provided by the GNU package `inetutils`, which doesn't have `--all-ip-addresses`. – Vladimir Panteleev Jul 12 '23 at 15:12
2

This is merely a distillation of several prior answers and comments. Sample output is included.

To list IPs:

Using ip:

(Restricted to IPv4 and global)

$ /sbin/ip -4 -o addr show scope global | awk '{gsub(/\/.*/,"",$4); print $4}'
192.168.82.134
138.225.11.92
138.225.11.2

Using ifconfig:

(Excluding 127.0.0.1)

$ /sbin/ifconfig | awk -F "[: ]+" '/inet addr:/ { if ($4 != "127.0.0.1") print $4 }'
192.168.82.134
138.225.11.92
138.225.11.2

To map IPs to hostnames, see this answer.

Community
  • 1
  • 1
Asclepius
  • 57,944
  • 17
  • 167
  • 143
1

Here is a similiar script for what I have tested to get an ip-range of addresses, but it is slowly - somebody might give a hint, how to accelerate this ? (the ip-range here is an example for to get all lines, who seems to be up - between Vancouver and Korea) :

#!/bin/bash

for ip in {209..210}.{125..206}.{5..231}.{65..72} # any ip between 209.126.230.71 and 210.205.6.66

do

printf ' === %s ===\n' "$ip"

whois "$ip" >> /home/$user/test001.txt

done

If this is too trivial or some mistake in it here, simply answer or comment.

This script would last until finish about 5 to 8 hours.

dschinn1001
  • 133
  • 10
0

I would to introduce you to a command-line tool called OSQuery by Facebook which helps you get system info by making SQL-like queries. For your case for instance, you would have enter;

osquery> select * from interface_addresses; 

Which would output something like;

interface = wlan0
       address = 192.168.0.101
          mask = 255.255.255.0
     broadcast = 192.168.0.255
point_to_point = 

Which I find a lot more neat and convenient.

David Okwii
  • 7,352
  • 2
  • 36
  • 29
-1

Use grep -v to ignore 127.0.0.1

ifconfig | grep 'inet addr:' | awk {'print $2'} | grep -v '127.0.0.1'

Use sed to edit out the 'addr:'

ifconfig | grep 'inet addr:' | awk {'print $2'}  | grep -v '127.0.0.1' | sed -e 's/addr://'
John3136
  • 28,809
  • 4
  • 51
  • 69
-1

ifconfig | grep 'inet addr:' | awk {'print $2'} | awk 'BEGIN{FS=":"}{print $2}' | grep -v '127.0.0.1'

Marcus
  • 6,701
  • 4
  • 19
  • 28
-1

It's a very tricky solution but it works:

ip a | awk ' !/[0-9]+\: lo/ && /^[0-9]\:/ || /inet / && !/127\.0\.0\.1/ {print $2}'

Output:

eth0: 192.168.0.1/24

Better yet:

ip a | awk ' !/[0-9]+\: lo/ && /^[0-9]\:/ || /inet / && !/127\.0\.0\.1/ {print $2}' | perl -i -pe "s/:\n/: /g;" -pe "s/\/[\d]+$//"

Output:

eth0: 192.168.0.1

I don't have a machine with several non loopback interfaces I can check it with, feel free to post your findings.

Yaron
  • 1,199
  • 1
  • 15
  • 35
-1

if it is only the "addr:" word that you'd like to remove I would use sed instead of awk like

ifconfig | grep 'inet addr:' | awk {'print $2'}| grep -v 127.0.0.1 | sed -e 's/addr://'
-1

I'm always surprised to see people using sed and awk instead of perl.

But first, using both grep and awk with an extra option, feel free to just:

ifconfig | grep 'inet addr:' | awk {'print $2'} | awk -F: {'print $2'} | grep -v '127.0.0.1'

replacing the awks with perl:

ifconfig | grep 'inet addr:' | perl -F\\s\|: -ane 'print "$F[2]\n"' | grep -v '127.0.0.1'

replacing the greps within the same perl script:

ifconfig | perl -F\\s\|: -ane 'next if !/^inet addr:/ or /127\.0\.0\.1/; print "$F[2]\n"'

and lastly just using the power of perl's regex:

ifconfig | perl -ne 'next if !/inet addr:(?<ip>[0-9.]+)/ or $+{ip} == "127.0.0.1"; print "$+{ip}\n"'
Gerard ONeill
  • 3,914
  • 39
  • 25
-2
ifconfig | grep 'inet addr:' | awk {'print $2'} | cut -d ":" -f 2
timoph
  • 1