Get mac address for alive interface - linux

Iam trying to get the mac_address for the interface which is up till now iam able to get this
ifconfig | grep HWaddr
eth0 Link encap:Ethernet HWaddr 98:BE:94:24:41:62
eth1 Link encap:Ethernet HWaddr 98:BE:94:24:41:63
eth2 Link encap:Ethernet HWaddr 98:BE:94:24:41:64
eth3 Link encap:Ethernet HWaddr 98:BE:94:24:41:65
usb0 Link encap:Ethernet HWaddr 9A:BE:94:24:41:61
Is there any one line command to get the mac_address for the interface link which is up ?

cat /sys/class/net/$(ip route show default | awk '/default/ {print $5}')/address
ip route show default | awk '/default/ {print $5}' prints your default interface name. Then you get your mac from /sys/class/net/IFACE_NAME/address

You can try these solutions:
For interfaces which are Up Use ifconfig with a Regular Expression for MAC
pattern:
ifconfig | grep -o -E '([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}'
Some OS like CentOS doesn't provide ifconfig, so you can use ip like this:
ip add | grep link/ether | awk '{print $2}'
For all interfaces you can just simply: cat /sys/class/net/*/address

You can try this to get the mac address of your interface. If you check the interface name and the MAC address are the first and last fields on a line with no leading whitespace.
ifconfig -a |
awk '/^[a-z]/ { iface=$1; mac=$NF; next }
/inet addr:/ { print iface, mac }'
or very simplistic, you can use this
cat /sys/class/net/$(ip route show default | awk '/default/ {print $5}')/address
this actually return: bc:f8:6b:bd:55:00 (sample macaddress of the eth0)

Related

Get MAC address using shell script

Currently all the solution mentioned for getting the MAC address always use eth0.
But what if instead of eth0 my interfaces start with eth1. Also on OS X the interface names are different.
Also the interface eth0 may be present but is unused. i.e. not active, it doesn't have an IP.
So is there a way I could get the MAC address for the first available interface that is Active.(i.e. it has an inet address, I even don't want one having inet6).
For E.g
eth0 Link encap:Ethernet HWaddr <some addr>
inet6 addr: <some addr> Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:123
RX packets:123 errors:123 dropped:123 overruns:123 frame:123
TX packets:123 errors:123 dropped:123 overruns:123 carrier:123
collisions:123 txqueuelen:123
RX bytes:123 (123 MB) TX bytes:123 (123 KB)
Interrupt:123 Memory:00000000-00000000
eth1 Link encap:Ethernet HWaddr <some addr>
inet addr:<some addr> Bcast:<some addr> Mask:<some addr>
inet6 addr: <some addr> Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:123 Metric:123
RX packets:123 errors:123 dropped:123 overruns:123 frame:123
TX packets:123 errors:123 dropped:123 overruns:123 carrier:123
collisions:123 txqueuelen:123
RX bytes:123 (123 MB) TX bytes:123 (123 KB)
Interrupt:123 Memory:00000000-00000000
NOTE : I have changed the values of the output.
So in this case I want the HWaddr for eth1 and not eth0.
How do I find it ? Also it should work on all the Linux flavours.
You can do as follows
ifconfig <Interface ex:eth0,eth1> | grep -o -E '([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}'
Also you can get MAC for all interface as follows
cat /sys/class/net/*/address
For particular interface like for eth0
cat /sys/class/net/eth0/address
The best Linux-specific solution is to use sysfs:
$ IFACE=eth0
$ read MAC </sys/class/net/$IFACE/address
$ echo $IFACE $MAC
eth0 00:ab:cd:12:34:56
This method is extremely clean compared to the others and spawns no additional processes since read is a builtin command for POSIX shells, including non-BASH shells. However, if you need portability to OS X, then you'll have to use ifconfig and sed methods, since OS X does not have a virtual filesystem interface like sysfs.
$ ip route show default | awk '/default/ {print $5}'
return: eth0 (my online interface)
$ cat /sys/class/net/$(ip route show default | awk '/default/ {print $5}')/address
return: ec:a8:6b:bd:55:05 (macaddress of the eth0, my online interface)
Terminal image
On a modern GNU/Linux system you can see the available network interfaces listing the content of /sys/class/net/, for example:
$ ls /sys/class/net/
enp0s25 lo virbr0 virbr0-nic wlp2s0
You can check if an interface is up looking at operstate in the device directory. For example, here's how you can see if enp0s25 is up:
$ cat /sys/class/net/enp0s25/operstate
up
You can then get the MAC address of that interface with:
$ cat /sys/class/net/enp0s25/address
ff:00:ff:e9:84:a5
For example, here's a simple bash script that prints MAC addresses for active interfaces:
#!/bin/bash
# getmacifup.sh: Print active NICs MAC addresses
D='/sys/class/net'
for nic in $( ls $D )
do
echo $nic
if grep -q up $D/$nic/operstate
then
echo -n ' '
cat $D/$nic/address
fi
done
And here's its output on a system with an ethernet and a wifi interface:
$ ./getmacifup.sh
enp0s25
ff:00:ff:e9:84:a5
lo
wlp2s0
For details see the Kernel documentation
Remember also that from 2015 most GNU/Linux distributions switched to systemd, and don't use ethX interface naming scheme any more - now they use a more robust naming convention based on the hardware topology, see:
Predictable Network Interface Names
systemd/src/udev/udev-builtin-net_id.c
Observe that the interface name and the MAC address are the first and last fields on a line with no leading whitespace.
If one of the indented lines contains inet addr: the latest interface name and MAC address should be printed.
ifconfig -a |
awk '/^[a-z]/ { iface=$1; mac=$NF; next }
/inet addr:/ { print iface, mac }'
Note that multiple interfaces could meet your criteria. Then, the script will print multiple lines. (You can add ; exit just before the final closing brace if you always only want to print the first match.)
Simply run:
ifconfig | grep ether | cut -d " " -f10
OR
ip a | grep ether | cut -d " " -f6
These two example commands will grep all lines with "ether" string and cut the mac address (that we need) following the number spaces (specified in the -f option) of the grepped portion.
Tested on different Linux flavors
I know that is a little bit dated, but with basic commands, we can take the mac address of an interface:
ip link show eth0 | grep link/ether | awk '{print $2}'
Have a nice day!
oh, if you want only the mac ether mac address, you can use that:
ifconfig | grep "ether*" | tr -d ' ' | tr -d '\t' | cut -c 6-42
(work on macintosh)
ifconfig -- get all info
grep -- keep the line with address
tr -- clean all
cut -- remove the "ether" to have only the address
None of the above worked for me because my devices are in a balance-rr bond. Querying either would say the same MAC address with ip l l, ifconfig, or /sys/class/net/${device}/address, so one of them is correct, and one is unknown.
But this works if you haven't renamed the device (any tips on what I missed?):
udevadm info -q all --path "/sys/class/net/${device}"
And this works even if you rename it (eg. ip l set name x0 dev p4p1):
cat /proc/net/bonding/bond0
or my ugly script that makes it more parsable (untested driver/os/whatever compatibility):
awk -F ': ' '
$0 == "" && interface != "" {
printf "%s %s %s\n", interface, mac, status;
interface="";
mac=""
};
$1 == "Slave Interface" {
interface=$2
};
$1 == "Permanent HW addr" {
mac=$2
};
$1 == "MII Status" {
status=$2
};
END {
printf "%s %s %s\n", interface, mac, status
}' /proc/net/bonding/bond0
This was the only thing that worked for me on Armbian:
dmesg | grep -oE 'mac=.*\w+' | cut -b '5-'
I have used command hciconfig with two greps to separate the PC Mac address and I saved the MAC address to variable:
PCMAC=$( hciconfig -a | grep -E 'BD Address:' | grep -Eo '[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}' )
You can also use this command to check if MAC address is in valid format. Note, that only big chars A-F are allowed and also you need to add input for this grep command:
grep -E '[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}'
This is my solution:
ip a | grep link/ether | awk -F " " '{print $2}'
Here's an alternative answer in case the ones listed above don't work for you. You can use the following solution(s) as well, which was found here:
ip addr
OR
ip addr show
OR
ip link
All three of these will show your MAC address(es) next to link/ether. I stumbled on this because I had just done a fresh install of Debian 9.5 from a USB stick without internet access, so I could only do a very minimal install, and received
-bash: ifconfig: command not found
when I tried some of the above solutions. I figured somebody else may come across this problem as well. Hope it helps.
Get MAC adress for eth0:
$ cat /etc/sysconfig/network-scripts/ifcfg-eth0 | grep HWADDR | cut -c 9-25
Example:
[me#machine ~]$ cat /etc/sysconfig/network-scripts/ifcfg-eth0 | grep HWADDR | cut -c 9-25
55:b5:00:10:be:10

Linux bash script to extract IP address

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.
If the goal is to find the IP address connected in direction of internet, then this should be a good solution.
Edit 2021: Added "sed" and "grep" versions and new "awk" versions (some are gnu)
To find what IP adders is used connected to internet, we can use the ip route command. With newer version of Linux you get more information with a typical output some like this:
ip route get 8.8.8.8
8.8.8.8 via 10.36.15.1 dev ens160 src 10.36.15.150 uid 1002
cache
so to get IP you need to find the IP after src, using awk, sed or grep
ip route get 8.8.8.8 | awk -F"src " 'NR==1{split($2,a," ");print a[1]}'
ip route get 8.8.8.8 | awk 'match($0,/src (\S*)/,a)&&$0=a[1]'
ip route get 8.8.8.8 | awk '{for(i=1;i<=NF;i++)if($i~/src/)$0=$(i+1)}NR==1'
ip route get 8.8.8.8 | sed -E 's/.*src (\S+) .*/\1/;t;d'
ip route get 8.8.8.8 | sed 's/.*src \([^ ]*\).*/\1/;t;d'
ip route get 8.8.8.8 | sed -nE '1{s/.*?src (\S+) .*/\1/;p}'
ip route get 8.8.8.8 | grep -oP 'src \K[^ ]+'
10.36.15.150
and if you like the interface name using awk, sed or grep
ip route get 8.8.8.8 | awk -F"dev " 'NR==1{split($2,a," ");print a[1]}'
ip route get 8.8.8.8 | awk 'match($0,/dev (\S*)/,a)&&$0=a[1]'
ip route get 8.8.8.8 | awk '{for(i=1;i<=NF;i++)if($i~/dev/)$0=$(i+1)}NR==1'
ip route get 8.8.8.8 | sed -E 's/.*?dev (\S+) .*/\1/;t;d'
ip route get 8.8.8.8 | sed 's/.*dev \([^ ]*\).*/\1/;t;d'
ip route get 8.8.8.8 | sed -nE '1{s/.*?dev (\S+) .*/\1/;p}'
ip route get 8.8.8.8 | grep -oP 'dev \K[^ ]+'
ens192
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.
If you like to store this into a variable, do:
my_ip=$(ip route get 8.8.8.8 | awk -F"src " 'NR==1{split($2,a," ");print a[1]}')
my_interface=$(ip route get 8.8.8.8 | awk -F"dev " 'NR==1{split($2,a," ");print a[1]}')
Why other solution may fail:
ifconfig eth0
If the interface you have has another name (eno1, wifi, venet0 etc)
If you have more than one interface
IP connecting direction is not the first in a list of more than one IF
Hostname -I
May get only the 127.0.1.1
Does not work on all systems.
Give all IP not only the one connected to internet. -I, --all-ip-addresses all addresses for the host
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).
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?
ip -4 addr show eth0 | grep -oP "(?<=inet ).*(?=/)"
May be not for all cases (especially if you have several NIC's), this will help:
hostname -I | awk '{ print $1 }'
ip route get 8.8.8.8| grep src| sed 's/.*src \(.* \)/\1/g'|cut -f1 -d ' '
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
/sbin/ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'
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!
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
A slight modification to one of the previous ip route ... solutions, which eliminates the need for a grep:
ip route get 8.8.8.8 | sed -n 's|^.*src \(.*\)$|\1|gp'
awk '/inet addr:/{gsub(/^.{5}/,"",$2); print $2}' file
192.168.1.103
If You want to use only sed to extract IP address:
ifconfig eth0 2>/dev/null sed -n 's/.*[[:space:]]\([[:digit:]][[:digit:]]*\.[[:digit:]][[:digit:]]*\.[[:digit:]][[:digit:]]*\.[[:digit:]][[:digit:]]*\).*/\1/p'
A slight modification to one of the previous ip route ... solutions that uses only ip and sed and properly isolates just the IPv4 IP:
ip -4 route get 1.1.1.1 | sed -n 's/^.*src \([0-9.]*\).*$/\1/p'

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 to use pipe to parse output of a command

I want to process the output of a process, say ifconfig. As you all know output of ifconfig is a list of lines containing inet addr: mask: etc. But I want to extract the ip alone[from inet addr: field] and list it. is it possible with pipe command? like
ifconfig | What should be here?
I want the output of this command as list of inet addresses (of different access points if present).
You can achieve this using awk as shown on this site. I've posted an excerpt here which produces your desired result:
ifconfig | awk '/dr:/{gsub(/.*:/,"",$2);print$2}'
You can do
ifconfig -a|grep inet| awk -F' ' '{print $2}'

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