34

I would like to find out which of the available network services (e.g. Ethernet or Wi-Fi) is currently active. In this screenshot from the Network Preferences, you can see that Wi-Fi is currently active (the green dot):

Network Preferences

How can I get that information from the command line?

The networksetup command allows me to list the available network services:

$ networksetup -listallnetworkservices
An asterisk (*) denotes that a network service is disabled.
Ethernet
FireWire
Wi-Fi

It can also show some details on the service, like the device name:

$ networksetup -listnetworkserviceorder
An asterisk (*) denotes that a network service is disabled.
(1) Ethernet
(Hardware Port: Ethernet, Device: en0)

(2) FireWire
(Hardware Port: FireWire, Device: fw0)

(3) Wi-Fi
(Hardware Port: Wi-Fi, Device: en1)

Unfortunately, the info on which service is active (the green dot from the screenshot) is not available in this info. Is there another command that I could use to get this information?

11 Answers 11

8

Simply issue

    ifconfig

List all network interfaces and their status.

5
  • True - each record contains a status field that either has active or inactive as a value.
    – nwinkler
    Commented Jun 17, 2015 at 6:18
  • 1
    It will give you false result if you are sharing your internet. Suppose your are sharing ethernet internet via wifi then status for both Ethernet and wifi will be "active" Commented Jan 2, 2017 at 10:18
  • 6
    This doesn't show you which service is being used - both wifi and ethernet will show as 'active' if you have both enabled and an ethernet cord plugged in.
    – tog22
    Commented May 19, 2017 at 18:00
  • 1
    This is quite handy for checking if a connection is not connected. For example my ethernet is generally only connected at work. So I can deduce I am at home by this not being in the list. ifconfig | grep $(networksetup -listnetworkserviceorder | grep 'Ethernet, Device' | sed -E "s/.*(en[0-9]).*/\1/"). Then I can switch locations based on the above being empty. Commented Nov 16, 2017 at 21:28
  • This simply lists all network interfaces not network services.
    – algal
    Commented Sep 3, 2018 at 22:55
25

Put it all together, I wrote a script to accomplish this task:

#!/bin/bash

while read -r line; do
    sname=$(echo "$line" | awk -F  "(, )|(: )|[)]" '{print $2}')
    sdev=$(echo "$line" | awk -F  "(, )|(: )|[)]" '{print $4}')
    #echo "Current service: $sname, $sdev, $currentservice"
    if [ -n "$sdev" ]; then
        ifout="$(ifconfig "$sdev" 2>/dev/null)"
        echo "$ifout" | grep 'status: active' > /dev/null 2>&1
        rc="$?"
        if [ "$rc" -eq 0 ]; then
            currentservice="$sname"
            currentdevice="$sdev"
            currentmac=$(echo "$ifout" | awk '/ether/{print $2}')

            # may have multiple active devices, so echo it here
            echo "$currentservice, $currentdevice, $currentmac"
        fi
    fi
done <<< "$(networksetup -listnetworkserviceorder | grep 'Hardware Port')"

if [ -z "$currentservice" ]; then
    >&2 echo "Could not find current service"
    exit 1
fi

The script first get a service list from networksetup command, then check if each service is in active status from ifconfig.

Name the script to networkservice.sh for example, then execute it to get the current network service you are on.

$ bash networkservice.sh
USB 10/100/1000 LAN, en4, 00:e0:4a:6b:4d:0c
Wi-Fi, en0, 8c:85:90:a0:4b:ec
5
  • I had to pipe the first line to tac to iterate through the interfaces in reverse order because I often have WiFi connected as well as a USB ethernet adapter (which is the preferred device in Network). In this case I want the most preferred active devise to be printed: services=$(networksetup -listnetworkserviceorder | grep 'Hardware Port' | tac)
    – ghr
    Commented Aug 1, 2016 at 22:07
  • @ghr that doesn't make any sense, networksetup -listnetworkserviceorder already outputs "the most preferred device" first...
    – Motsel
    Commented Mar 1, 2019 at 10:37
  • Looks like I ended up modifying the above script a little so that it only prints out 1 service, rather than any connected. I had to tac so that later (non-preferred) services wouldn't overwrite $currentservice. Should have been clearer in that original comment.
    – ghr
    Commented Mar 2, 2019 at 16:59
  • 1
    can confirm that this is still the best answer in these trying times when most computers are connected to VPN, either fully tunnelled or not, where other answers may return the device name for the VPN tunnel tunX. Commented Jun 3, 2020 at 2:01
  • Note this script uses hardware port names which are generally the same as service names, but can fail if you manually rename or if you have multiple services with the same hardware port name, typical for USB Ethernet. This gist has an amended version to fix this issue. Commented Feb 11, 2022 at 20:38
20

I won't pretend to have the answer to this question sorted, but this but this maybe helpful.

You can ask how it currently will route packets to something:

$ route get example.com | grep interface
interface: en8

And then you can ask what "Network Service" is managing that interface:

$ networksetup -listnetworkserviceorder | grep en8
(Hardware Port: Broadcom NetXtreme Gigabit Ethernet Controller, Device: en8)

But honestly, I doubt that a "Network Services" is one to one with a hardware port. And some interfaces, tun0 for example, do not have a "Network Service". Well at least sometimes they don't.

8

The scutil --nwi command lists interfaces and scutil --dns command gives you all the network routing information you'll need to map hardware interface labels to network routes.

A little awk and grep can pretty it up if you need to script the information or pare it down. Start with gripping for "if_index" if you're curious.

There’s not much that is simple about networking since you can have multiple addresses assigned to one interface and more than one connection to the internet. The default route is often the correct answer, but with VPN and apps hard coding things like DNS over HTTP and more, default Carrie’s less weight than it did ten years ago when macOS was called OS X.

1
  • That looks useful - I'll play around with that!
    – nwinkler
    Commented Jun 16, 2015 at 20:15
4

Building on the other answers and comments (read: I didnt make this), this can be condensed into a single line:

networksetup -listnetworkserviceorder |grep -B1 "$(route get example.com | awk "/interface/ {print \$2}")"

All it does is tell us which interface is being used, within the context of your configured Interface Order.

I use it in a shell alias:

# determine which network interface is being used
alias whichif='networksetup -listnetworkserviceorder  |grep -B1 "$(route get example.com | awk "/interface/ {print \$2}")"'

Usage

$> whichif
(1) Thunderbolt Ethernet Slot 2
(Hardware Port: Thunderbolt Ethernet Slot 2, Device: en7)

After switching interfaces:

$> whichif
(2) Wi-Fi
(Hardware Port: Wi-Fi, Device: en0)
6
  • the second grep can be done inside awk: networksetup -listnetworkserviceorder |grep -B1 "$(route get example.com | awk "/interface/ {print \$2}")"
    – ccpizza
    Commented Jan 24, 2022 at 9:43
  • @ccpizza I love it!!
    – mikewaters
    Commented Jan 25, 2022 at 15:10
  • @ccpizza Yours is better, as its the same command on the cli and in the shell alias (wrt ~~quoting~~ escaping). I've updated our answer.
    – mikewaters
    Commented Jan 25, 2022 at 15:14
  • 4
    If you want just the network service name: networksetup -listnetworkserviceorder | awk "/$(route get example.com | awk '/interface/ {print $2}')/{sub(/\([0-9]+\)\ /,\"\",a); print a} {a=\$0}"
    – Pierz
    Commented May 10, 2022 at 9:25
  • This also work for just getting the network service name: networksetup -listnetworkserviceorder |grep -B1 "$(route get 1.1.1.1 | awk '/interface/ {print $2}')" | awk -F'\\) ' '/\([0-9]+\)/ {print $2}'
    – Chris
    Commented Oct 25, 2022 at 20:18
3

Just in case someone else stumbles across this like I did the code below may be more of what you are looking for.

This is to expand on PeterVP's answer; also visible here.

#!/bin/sh

clear
sExternalMACALService="http://dns.kittell.net/macaltext.php?address="

# List all Network ports
NetworkPorts=$(ifconfig -uv | grep '^[a-z0-9]' | awk -F : '{print $1}')
#echo $NetworkPorts

# Function to convert IP Subnet Mask to CIDR
mask2cdr ()
{
# Assumes there's no "255." after a non-255 byte in the mask
local x=${1##*255.}
set -- 0^^^128^192^224^240^248^252^254^ $(( (${#1} - ${#x})*2 )) ${x%%.*}
x=${1%%$3*}
echo $(( $2 + (${#x}/4) ))
}

# Get remote/public IP address
remoteip=$(dig +short myip.opendns.com @resolver1.opendns.com)

# Get computer name
computername=$(scutil --get ComputerName)

# Get serial number
sSerialNumber=$(system_profiler SPHardwareDataType |grep "Serial Number (system)" |awk '{print $4}'  | cut -d/ -f1)
#echo $sSerialNumber

# Get operating system name and version - Start
OSvers1=$( sw_vers -productVersion | cut -d. -f1 )
OSvers2=$( sw_vers -productVersion | cut -d. -f2 )
OSvers3=$( sw_vers -productVersion | cut -d. -f3 )
case $OSvers2 in
8)
OSName="Mountain Lion"
;;
9)
OSName="Mavericks"
;;
10)
OSName="Yosemite"
;;
11)
OSName="El Capitan"
;;
12)
OSName="Sierra"
;;
default)
OSName="Unknown"
;;
esac
# Get operating system name and version - Stop


echo "$computername"
echo "--------------"
echo "      Computer OS:  Mac OS X - $OSName $OSvers1.$OSvers2.$OSvers3"
echo "    Computer Name:  $computername"
echo "Current User Name:  $(whoami)"
echo "    Serial Number:  $sSerialNumber"

if [[ $remoteip ]]; then
echo "Remote IP Address:  $remoteip\n"
else
echo "Remote IP Address:  Unable To Determine\n"
fi

for val in $NetworkPorts; do   # Get for all available hardware ports their status
activated=$(ifconfig -uv "$val" | grep 'status: ' | awk '{print $2}')
#echo $activated
label=$(ifconfig -uv "$val" | grep 'type' | awk '{print $2}')
#echo $label
#ActiveNetwork=$(route get default | grep interface | awk '{print $2}')
ActiveNetworkName=$(networksetup -listallhardwareports | grep -B 1 "$label" | awk '/Hardware Port/{ print }'|cut -d " " -f3- | uniq)
#echo $ActiveNetwork
#echo $ActiveNetworkName
state=$(ifconfig -uv "$val" | grep 'status: ' | awk '{print $2}')
#echo $state
ipaddress=$(ifconfig -uv "$val" | grep 'inet ' | awk '{print $2}')
# echo $ipaddress

if [[ -z $(ifconfig -uv "$val" | grep 'link rate: ' | awk '{print $3, $4}' | sed 'N;s/\n/ up /' ) ]]; then
networkspeed="$(ifconfig -uv "$val" | grep 'link rate: ' | awk '{print $3}' ) up/down"
else
networkspeed="$(ifconfig -uv "$val" | grep 'link rate: ' | awk '{print $3, $4}' | sed 'N;s/\n/ up /' ) down"
fi

#echo $networkspeed
macaddress=$(ifconfig -uv "$val" | grep 'ether ' | awk '{print $2}')
#echo $macaddress
macal=$(curl -s "$sExternalMACALService$macaddress")
#echo $macal
quality=$(ifconfig -uv "$val" | grep 'link quality:' | awk '{print $3, $4}')
#echo $quality
netmask=$(ipconfig getpacket "$val" | grep 'subnet_mask (ip):' | awk '{print $3}')
#echo $netmask
router=$(ipconfig getpacket "$val" | grep 'router (ip_mult):' | sed 's/.*router (ip_mult): {\([^}]*\)}.*/\1/')
#echo $router
DHCPActive=$(networksetup -getinfo "Wi-Fi" | grep DHCP)
#echo $DHCPActive
dnsserver=$(networksetup -getdnsservers "$ActiveNetworkName" | awk '{print $1, $2}' | sed 'N;s/\n//' )
#echo $dnsserver

if [ "$activated" = 'active' ]; then
#echo "Network Port is Active"
if [[ $ipaddress ]]; then
echo "$ActiveNetworkName ($val)"
echo "--------------"
# Is this a WiFi associated port? If so, then we want the network name
if [ "$label" = "Wi-Fi" ]; then
WiFiName=$(/System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport -I | grep '\sSSID:' | sed 's/.*: //')
#echo $WiFiName
echo "     Network Name:  $WiFiName"
fi

echo "       IP Address:  $ipaddress"
echo "      Subnet Mask:  $netmask"
echo "           Router:  $router"
echo "          IP CIDR:  $ipaddress/$(mask2cdr $netmask)"

if [[ -z $dnsserver ]]; then
if [[ $DHCPActive ]]; then
echo "       DNS Server:  Set With DHCP"
else
echo "       DNS Server:  Unknown"
fi
else
echo "       DNS Server:  $dnsserver"
fi

echo "      MAC-address:  $macaddress ($macal)"
echo "    Network Speed:  $networkspeed"
echo "     Link quality:  $quality"
echo " "
fi

# Don't display the inactive ports.
fi

done
3
  • In my script I've replaced public query with: set public (dig +short myip.opendns.com @resolver1.opendns.com) My reasoning for this is that a dns server (like opendns) is less likely to be down than a website and is faster. And I removed the sleep statement. No need to wait for the dns-server reply. Execution time for my script 177 ms. Yours takes 5.237 seconds, but does more of course. Still a big difference.
    – PeterVP
    Commented May 1, 2017 at 16:09
  • Great suggestion Commented May 2, 2017 at 19:32
  • This assumes that network services have the same names as their underlying hardware ports. networksetup -getdnsservers ... takes a network service name, which can sometimes be different than the hardware port passed to it in this script. You can see them all with -listnetworkserviceorder
    – Chris
    Commented Sep 13, 2021 at 21:28
2

Not sure if this is helpful to anyone, but as I was tinkering with the same question, I came to this solution:

ifconfig | grep flags=8863 | grep -v bridge

The output will look something like this, and lists only the ethernet ports and wifi that are in active use:

en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
en1: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500

If you'd like to see the assigned IPv4 address as well:

ifconfig | grep 'flags=8863\|inet ' | grep -v 'bridge\|127.0.0.1'

Which produces something like this;

en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    inet 192.168.2.147 netmask 0xffffff00 broadcast 192.168.2.255
en1: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    inet 192.168.2.244 netmask 0xffffff00 broadcast 192.168.2.255

Another alternative:

scutil --nwi

Which shows the online network devices the last line actually shows the currently active network interfaces:

Network information

IPv4 network interface information
     en0 : flags      : 0x5 (IPv4,DNS)
           address    : 192.168.2.147
           reach      : 0x00000002 (Reachable)
     en1 : flags      : 0x5 (IPv4,DNS)
           address    : 192.168.2.244
           reach      : 0x00000002 (Reachable)

   REACH : flags 0x00000002 (Reachable)

IPv6 network interface information
   No IPv6 states found


   REACH : flags 0x00000000 (Not Reachable)

Network interfaces: en0 en1

Further processing, if needed, is up to you. :-)


Note:

Mind you that I'm not an expert on the flags (8863). You can find the flag details in the if.h header file - Spotlight is your friend in finding "if.h". I found mine for example here:

/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/Kernel.framework/Versions/A/Headers/net/if.h

which will show you what the flags mean (keep in mind: hexadecimal);

#define IFF_UP          0x1             /* interface is up */
#define IFF_BROADCAST   0x2             /* broadcast address valid */
#define IFF_DEBUG       0x4             /* turn on debugging */
#define IFF_LOOPBACK    0x8             /* is a loopback net */
#define IFF_POINTOPOINT 0x10            /* interface is point-to-point link */
#define IFF_NOTRAILERS  0x20            /* obsolete: avoid use of trailers */
#define IFF_RUNNING     0x40            /* resources allocated */
#define IFF_NOARP       0x80            /* no address resolution protocol */
#define IFF_PROMISC     0x100           /* receive all packets */
#define IFF_ALLMULTI    0x200           /* receive all multicast packets */
#define IFF_OACTIVE     0x400           /* transmission in progress */
#define IFF_SIMPLEX     0x800           /* can't hear own transmissions */
#define IFF_LINK0       0x1000          /* per link layer defined bit */
#define IFF_LINK1       0x2000          /* per link layer defined bit */
#define IFF_LINK2       0x4000          /* per link layer defined bit */
#define IFF_ALTPHYS     IFF_LINK2       /* use alternate physical connection */
#define IFF_MULTICAST   0x8000          /* supports multicast */
1

Taken from Find Detailed Wi-Fi Connection History from Command Line of Mac OS X | OSXDaily:

For modern versions of Mac OS X, OS X Yosemite 10.10 and newer, use the following:

defaults read /Library/Preferences/SystemConfiguration/com.apple.airport.preferences |grep LastConnected -A 7

Hit return and you’ll instantly see the comprehensive listing of wireless network connection details.

You get a lot of info on the history of connections, including the details for current one.

Not perfect but you get the info that you're looking for - and a lot of extra info more!

1
  • 1
    You are assuming a Wi-Fi connection which is not necessarily the case for all scenarios.
    – ccpizza
    Commented Dec 16, 2021 at 18:01
1

Here's a fish shell script I wrote:

function netinfo -d "get network information"

  # Get public ip address
  set public (dig +short myip.opendns.com @resolver1.opendns.com)
  set hostname (uname -n)

  if test -z "$public" # We got an empty string, meaning:
    set public "No Internet connection available"
  end

  echo ''
  echo "    Public IP: $public"
  echo "     Hostname: $hostname"
  echo ''

  # Get all available hardware ports
  set ports (ifconfig -uv | grep '^[a-z0-9]' | awk -F : '{print $1}')

  # Get for all available hardware ports their status
  for val in $ports
    set activated (ifconfig -uv $val | grep 'status: ' | awk '{print $2}')

    # We want information about active network ports...
    if test $activated = 'active' ^/dev/null
      set ipaddress (ifconfig -uv $val | grep 'inet ' | awk '{print $2}')

      # and of these, the ones with an IP-address assigned to it
      if test -n "$ipaddress" ^/dev/null

        # Do we have an IP address?
        # Then give us the information
        set label (ifconfig -uv $val | grep 'type' | awk '{print $2}')
        set macaddress (ifconfig -uv $val | grep 'ether ' | awk '{print $2}')
        set quality (ifconfig -uv $val | grep 'link quality:' | awk '{print $3, $4}')
        set netmask (ipconfig getpacket $val | grep 'subnet_mask (ip):' | awk '{print $3}')
        set router (ipconfig getpacket $val | grep 'router (ip_mult):' | sed 's/.*router (ip_mult): {\([^}]*\)}.*/\1/')
        set dnsserver (ipconfig getpacket $val | grep 'domain_name_server (ip_mult):' | sed 's/.*domain_name_server (ip_mult): {\([^}]*\)}.*/\1/')

        # Header for the network interfaces
        echo -n $label ; echo -n ' ('; echo -n $val ; echo ')'
        echo "--------------"

        # Is this a WiFi associated port? If so, then we want the network name
        switch $label
          case Wi-Fi
            # Get WiFi network name
            set wifi_name (/System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport -I | grep '\sSSID:' | sed 's/.*: //')
            echo " Network Name: $wifi_name"
            # Networkspeed for Wi-Fi
            set networkspeed (/System/Library/PrivateFrameworks/Apple80211.framework/Versions/A/Resources/airport -I | grep lastTxRate: | sed 's/.*: //' | sed 's/$/ Mbps/')
          case '*'
            # Networkspeed  for other ports
            set networkspeed (ifconfig -uv $val | grep 'link rate:' | awk '{print $3, $4}')
        end

        echo "   IP-address: $ipaddress"
        echo "  Subnet Mask: $netmask"
        echo "       Router: $router"
        echo "   DNS Server: $dnsserver"
        echo "  MAC-address: $macaddress"
        echo "Network Speed: $networkspeed"
        echo " Link quality: $quality"
        echo ''
      end

      # Don't display the inactive ports.
    else if test $activated = 'inactive' ^/dev/null
    end
  end
end

It shows all active network interfaces and relevant data.

Comment out what you don't want/need

3
  • 2
    Might be easier to define a echo_italic shell function instead of wrapping all these echos in set_color calls.
    – nohillside
    Commented May 2, 2017 at 11:54
  • All set_color commands can be removed. They're just 'decorative'.
    – PeterVP
    Commented May 6, 2017 at 18:14
  • 1
    Removed set_color commands & put variables inside echo statements
    – PeterVP
    Commented Nov 20, 2017 at 20:04
1

Solution based on the input provided in all the other answers.

#################################
# get MacOS network device name
function get_network_device() {
  scutil --nwi | awk -F': ' '/Network interfaces/ {print $2;exit;}'
}

#################################
# get MacOS network service name: takes network device name as 1st arg
function get_service_name() {
  /usr/sbin/networksetup -listnetworkserviceorder | awk -v DEV="$1" -F': |,' '$0~ DEV  {print $2;exit;}'
}

NETWORK_DEVICE_NAME="$(get_network_device)"
NETWORK_SERVICE_NAME="$(get_service_name "$NETWORK_DEVICE_NAME")"

echo "${NETWORK_SERVICE_NAME}"

The exit in in the first line makes sure only the first active network device is taken in case there are more than one.

0

list all connected network service name:

#!/bin/bash

# gsed: brew install gnu-sed
scutil --nwi | awk -F': ' '/Network interfaces/ {print $2;}' | gsed 's/ /\n/g' | while read interface; 
do
    echo "interface: $interface"
    # awk: print pre line of matched line
    networksetup -listnetworkserviceorder | awk "/$interface/{print a}{a=\$0}" | gsed 's/([0-9])//g' | while read networkservicename; do
        
        echo "networkservicename: $networkservicename"
        
    done;
done;

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .