Pratham
Pratham

Reputation: 1713

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.

Upvotes: 52

Views: 147633

Answers (15)

Jayesh Bhoi
Jayesh Bhoi

Reputation: 25865

You can do as follows

ifconfig <Interface ex:eth0,eth1> | grep -o -E '([[:xdigit:]]{1,2}:){5}[[:xdigit:]]{1,2}'

Also you can get the MAC address for all interfaces as follows

cat /sys/class/net/*/address

For a particular interface like eth0

cat /sys/class/net/eth0/address

Upvotes: 103

Adrian
Adrian

Reputation: 1989

The -j flag of ip outputs in JSON format. You can parse that with jq:

ip -j link show enp3s0 | jq -r '.[].address'

Upvotes: 0

Daniel Mandelblat
Daniel Mandelblat

Reputation: 337

This is my solution:

 ip a | grep link/ether | awk -F " " '{print $2}'

Upvotes: 2

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}'

Upvotes: 0

Micael Illos
Micael Illos

Reputation: 492

This was the only thing that worked for me on Armbian:

dmesg | grep -oE 'mac=.*\w+' | cut -b '5-'

Upvotes: 0

Peter
Peter

Reputation: 3407

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

Upvotes: 2

Murdok
Murdok

Reputation: 126

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!

Upvotes: 5

Ibrahim Almahfooz
Ibrahim Almahfooz

Reputation: 317

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

Upvotes: 8

sk8forether
sk8forether

Reputation: 249

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.

Upvotes: -1

tripleee
tripleee

Reputation: 189327

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.)

Upvotes: 13

gerlos
gerlos

Reputation: 520

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:

Upvotes: 22

MajorTom
MajorTom

Reputation: 47

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

Upvotes: 3

Elismar Luz
Elismar Luz

Reputation: 629

$ 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

Upvotes: 52

e-info128
e-info128

Reputation: 4072

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

Upvotes: -2

Dave
Dave

Reputation: 3570

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.

Upvotes: 64

Related Questions