17

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?

5

Simply issue

    ifconfig

List all network interfaces and their status.

  • True - each record contains a status field that either has active or inactive as a value. – nwinkler Jun 17 '15 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" – Harshal Chaudhari Jan 2 '17 at 10:18
  • 3
    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 May 19 '17 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. – Chris Rymer Nov 16 '17 at 21:28
  • This simply lists all network interfaces not network services. – algal Sep 3 '18 at 22:55
13

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

#!/bin/bash

services=$(networksetup -listnetworkserviceorder | grep 'Hardware Port')

while read 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 <<< "$(echo "$services")"

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
  • 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 Aug 1 '16 at 22:07
  • @ghr that doesn't make any sense, networksetup -listnetworkserviceorder already outputs "the most preferred device" first... – Motsel Mar 1 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 Mar 2 at 16:59
5

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

  • That looks useful - I'll play around with that! – nwinkler Jun 16 '15 at 20:15
2

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.

2

Just incase 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 at https://www.kittell.net/code/mac-os-x-get-network-information/

#!/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
  • 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 May 1 '17 at 16:09
  • Great suggestion – David Kittell May 2 '17 at 19:32
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

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

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

You must log in to answer this question.

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