How to find network interface name - linux

I have a bash script that runs on a variety of different Ubuntu Linux machines. Its job is to find out the LAN IPv4 address of the localhost.
The script is using
ip addr show eth0 | sed -n '/inet /{s/^.*inet \([0-9.]\+\).*$/\1/;p}'
which is fine, but some machines for some reason use eth1 instead of eth0. I would like to be able to discover the LAN iface name, so I can substitute it in here instead of eth0.
Of course, if you can come up with a different oneliner that does the same thing, all good.

The main NIC will usually have a default route. So:
ip -o -4 route show to default
The NIC:
ip -o -4 route show to default | awk '{print $5}'
The gateway:
ip -o -4 route show to default | awk '{print $3}'
Unlike ifconfig, ip has a consistent & parsable output. It only works on Linux; it won't work on other Unixen.

Not sure if this helps, but it seems that ip route get will show which interface it uses to connect to a remote host.
ubuntu#ip-10-40-24-21:/nail/srv/elasticsearch$ ip route get 8.8.8.8
8.8.8.8 via <gateway address> dev eth0 src <eth0 IP Address>
of course you could automate that in shell script with something like,
ip route get 8.8.8.8 | awk '{ print $NF; exit }'

Most recenttly systemd/udev has automatically started to assign interface names for all local Ethernet, WLAN and WWAN interfaces to something that we're all accustomed to . This is a departure from the traditional interface naming scheme ("eth0", "eth1", "wlan0", ...) .. now we have to check first what the local interface name is before we can use it while previously we it was a pretty accurate guess that "eth0" was the right name. What you're asking for is the network NAME .. Here's a small script to solve the problem
Use "ip route get 8.8.8.8 " to figure out which ACTIVE interface has the route to internet ( or currently being used )
Output should look like :
8.8.4.4 via 10.10.1.1 dev enp0s3 src 10.10.1.118
cache
Use awk to print the 5th text block for Interface NAME
]# ip route get 8.8.8.8 | awk -- '{print $5}'
Output : enp0s3
Use awk to print the 7th text block for Interface Address
]# ip route get 8.8.8.8 | awk -- '{print $7}'
Output : 10.10.1.118

How about searching for the string inet and brd (for broadcast)? That would give you:
ip addr show|egrep '^ *inet'|grep brd|awk -- '{ print $2; }'|sed -e 's:/[0-9]*$::'
Note that I'm using more commands than necessary; you can probably achieve the same thing with sed and a more complex regexp but I prefer a command that makes it obvious by which steps I arrive at the result.
If you want to run it in a single command, I suggest to try awk:
ip addr show|awk -- '$1 == "inet" && $3 == "brd" { split($2,a,"/"); print a[1]; }'
which isn't much longer than the sed version but more readable.
+1 Slightly more readable:
ip addr show | awk '$1 == "inet" && $3 == "brd" { sub (/\/.*/,""); print $2 }'

Believe it or not, there is no standard, easy way to get this information. There is no standard give me the current IP and Interface Name command. There isn't even a standard format for the information returned by ifconfig.
I was going to recommend forgoing pure shell and go with a scripting language like Python where you can do this:
import socket
socket.gethostbyname(socket.gethostname())
Except it doesn't work on most Linux systems because there's usually an entry in the /etc/host file pointing to 127.0.0.1, the loopback address. Perl has the same issues.
You have a firm grasp on the scripting involved, and you've seen the issues. The only thing I can recommend is to test this on each machine you're going to run it on, and see what pops out. There isn't going to be a general purpose one liner that works with all operating systems, or even with different systems on the same operating system because of the way the network is setup and the way interfaces may be named by each location.

I'd still like to know if there was an easier way to do this, but this is my workaround: I know the LAN subnet, so...
ip addr show | grep "inet 10.67.5." \
| sed -n '/inet /{s/^.*inet \([0-9.]\+\).*$/\1/;p}'

1) This one print only interface names (I needed that for handing upcoming and downcoming PPP links):
for i in $( ifconfig | grep 'ppp' | awk '{print $1}' );
do
printf "$i "; ## Or echo
done
Result:
ppp0 ppp1 ppp2
2) This one prints interface names and IP
declare -a IPADDR
index=0
for i in $( ifconfig | grep 'inet addr' | awk '{print $2}'| sed 's#addr:##g' );
do
IPADDR[$index]=$i
let "index += 1"
done
index=0
for i in $( ifconfig | grep 'ppp' | awk '{print $1}' );
do
echo $i
let "index += 1"
done
Result:
ppp0 addr:IP
ppp1 addr:IP
ppp2 addr:IP

Related

Display ethernet interface and its corresponding IP address from Linux "ip a s"

I am trying to list all the ethernet device names and its assigned IP address available in the RHEL node using the output of ip addr show command
I print all the network interfaces names only with the following:
ip a s | awk -F: '/^[^ ]/ {print $2}'
I am trying to get the output in the below format by applying more logic and coding in the above awk command (or anything preferably sed or perl possibly a one-liner):
eth0: 10.xx.xx.xx
eth1: 172.xx.xx.xx
Also, loopback lo device has to be ignored in the output as this output goes to ansible inventory file after verification
Try
ip --oneline addr show
which should be reasonably convenient to parse with Awk.
ip --oneline addr show | awk '$3 == "inet" && $2 != "lo" { print $2 ": " $4 }
Maybe see also ip --brief which is even more compact.
For more advanced usage, there is also ip --json addr show which outputs very detailed information about all interfaces in JSON format. See also the ip manual page.

A confusion about the alias area of bashrc file

I want write my own alias called oepnserver. The functions of the oepnserver are:
show my ip address
use python module to start a server on current folder.
The detailed code is listed below:
alias openserver="ifconfig wlan0 |grep inet\ |awk '{print $2}' && python3 -m http.server 54188"
When I type oepnserver, my terminal only shows:
inet 172.34.162.200 netmask 255.255.224.0 broadcast 172.34.191.255
Serving HTTP on 0.0.0.0 port 54188 (http://0.0.0.0:54188/) ...
However, my expectation was
172.34.162.200
Serving HTTP on 0.0.0.0 port 54188 (http://0.0.0.0:54188/) ...
I also try to use the ifconfig wlan0 |grep inet\ |awk '{print $2}' along, and I get the correct output.
Should I use another way to combine these two commands instead of &&? Or I just made some typo?
Based on your shown code I am trying to optimize it which could be done by single awk.
ifconfig wlan0 | awk '/inet /{print $2}' && your python code
Also IMHO you should try to make this as a function rather than alias.

changing no_proxy environment variable value with awk

I want to read IP address of all interface and set it to no_proxy variable in centos machine.
i can do it manual by running ifconfig
this is the ip address in one of my vagrant box,
192.168.10.2
10.0.1.13
192.168.84.18
but i have around 13 boxes and ips are dynamically set everytime box is brought up.
i tried,
ifconfig | grep 192* and it gives me ip but not of all the interfaces available.
how can i set all the interface ip and assign them to no_proxy variable?
you can use awk with grep to get the ip address in your CentOS machines, and then tr command to remove \n
noip="$(ifconfig | grep inet | awk '{print $2","}' | tr -d '\n')"
it will give you,
192.168.10.2,10.0.1.13,192.168.84.18,
export it as follows including localhost and loopback address, i.e. 127.0.0.1,
export no_proxy=${noip}localhost,127.0.0.1
So your complete code will be,
noip="$(ifconfig | grep inet | awk '{print $2","}' | tr -d '\n')"
export no_proxy=${noip}localhost,127.0.0.1
I grabbed regular expression from https://www.brianparsons.net/FindIPAddresseswithawk/
~$ ips=$(ifconfig | awk '{match($0,/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/); if(RLENGTH > 0) { ip = substr($0,RSTART,RLENGTH); print ip}}')
~$ echo $ips
127.0.0.1 10.65.240.107

Retrieve the name of a Network Interface using an IP Address and AWK Bash

I am trying to use Bash on CentOS 6.4 to retrieve the network interface name attached to an IP address using AWK. I have a bit of command from a Solaris box, but I'm not sure how to convert it to Linux output.
The command looks like this:
ifconfig -a | awk '
$1 ~ /:/ {split($1,nic,":");
lastif=sprintf("%s:%s",nic[1],nic[2]);}
$2 == "'$1'" { print lastif ; exit; }
'
Its part of a script, so it takes commandline argument like monitor.sh x.x.x.x y.y.y.y and it uses the first x.x.x.x to get the interface name, then makes $1 == $2 so then it can ping y.y.y.y later. I'm guessing that in Solaris the ifconfig -a output is different than CentOS. I can get the interface name if the IP and interface are on the same line, but in linux, they're on two different lines. Any ideas.
I don't have CentOS, but in RHEL, IP address is listed as inet address. I believe they should be same.
The following command should give you the interface name which has a IP address.
export iface=$(ifconfig | grep -B1 "inet addr:x.x.x.x" | awk '$1!="inet" && $1!="--" {print $1}')
echo "$iface" # To get the interface name for x.x.x.x ip
And this one should show the IP including localhost :
ifconfig | grep "inet addr:" | sed -e 's/addr:/addr: /g' | awk '{print $3}'
geting ifname for 127.0.0.1 (or any other IP)
ifconfig | awk '/127.0.0.1/ {print $1}' RS="\n\n"
lo
getting ip:
ifconfig | awk -F"[ :]+" '/inet addr:/ {print $4}'
Post the output of ifconfig, and I can help you fine tune for your OS

How do I get the IP of only one Interface

When I tried ifconfig it gives me the whole all the information regarding the Network Adapter.
I tried :
system( "ifconfig -a | grep inet | "
"sed 's/\\([ ]*[^ ]*\\)\\([ ]*[^ ]*\\).*$/\\1 \\2/' "
" > address.txt" ) ;
which output two Ips :
inet addr:17.24.17.229
inet addr:127.0.0.1
But I need just the 1st one , How can I filter this out.
You might use head but...
I might be mistaking of course, but my guess is that you don't really need the first one.
You're probably looking for the one that is connected to the gateway (or the Internet).
As far as I know, the order of the IP addresses or interfaces is unspecified.
What do you want to achieve exactly ?
If you want to know what interface is "connected to the internet", a more reliable approach is to find the interface which has the default route (using route) then to use ifconfig <interface> to directly get the correct IP address.
you can reduce the use of grep and head
ifconfig -a | sed -nr -e '/inet\b/{s|^.*inet\s+addr:(.[^ \t]*).*|\1|;h}' -e '${x;p}'
I'd use iproute2's ip:
ip -o addr show dev eth0 | while read IFNUM IFNAME ADDRTYPE ADDR REST; do [ "$ADDRTYPE" == "inet" ] && echo $ADDR; done
9.87.65.43/21
(Not only because it's easier to parse, but it'll also show e.g. secondary IPs, which ifconfig can't.)
Don't look at all of the adapters, just the one you want.
system( "ifconfig -a eth0 | grep inet | "
"sed 's/\\([ ]*[^ ]*\\)\\([ ]*[^ ]*\\).*$/\\1 \\2/' "
" > address.txt" ) ;
If the output of ifconfig or ip ever changes, your program will break.
Why not not just use the SIOCGIFCONF ioctl() and get it directly from the source?
ETA: It's also unsafe to assume that any given system will have just one loopback interface and just one Ethernet with a single address.
How about 'ifconfig eth0'?
hostname -I | awk '{print $1}'

Resources