给定 MAC 地址,如何判断接口是否为 wifi

给定 MAC 地址,如何判断接口是否为 wifi

有没有办法在命令行上给出网络接口的 MAC 地址(例如01:23:45:67:89:ab),来确定该接口是 wifi 还是有线?

我正在尝试在 shell 脚本中执行此操作。

答案1

除了他们的方法(我认为)也可以将虚拟无线接口报告为真实无线接口(这又我认为/sys/class/net/*/只需进一步检查就可以轻松解决)@PhilippWendler 有更简单的方法下面只需检查一下/sys/class/net,我相信这很简单,所以也请查看他们的答案。


另一种方法是使用lshw+ jq;它应该相当强大,因为它依赖lshw于检测和依赖jq于解析。

这假设bash(由于&>/dev/null重定向;&>/dev/null可以更改为>/dev/null 2>&1用于不bash兼容的 shell 和 POSIX 遵从性):

{
    LANG=C lshw -json -class network | 
    jq -e --arg serial '01:23:45:67:89:ab' '.[] | select(.description == "Wireless interface" and .serial == $serial)'
} &>/dev/null && echo yes || echo no

仅当“网络”设备被归类为“无线接口”并且其 MAC 地址为“01:23:45:67:89:ab”时,此答案才会为echo“是”;当然,最好将其重构为一个函数以方便使用:

is_wireless_adapter() {
    {
        LANG=C lshw -json -class network | 
        jq -e --arg serial "$1" '.[] | select(.description == "Wireless interface" and .serial == $serial)'
    } &>/dev/null && echo yes || echo no
}

用法:

is_wireless_adapter <MAC_ADDRESS>
% ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host noprefixroute 
    valid_lft forever preferred_lft forever
2: enp100s0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN group default qlen 1000
    link/ether 48:21:0b:3d:b7:87 brd ff:ff:ff:ff:ff:ff
3: wlo1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether e0:d0:45:66:b0:c5 brd ff:ff:ff:ff:ff:ff
    altname wlp0s20f3
    inet 192.168.1.3/24 brd 192.168.1.255 scope global dynamic noprefixroute wlo1
    valid_lft 86077sec preferred_lft 86077sec
    inet6 fe80::1c63:81ea:f46a:b3db/64 scope link noprefixroute 
    valid_lft forever preferred_lft forever
% is_wireless_adapter '48:21:0b:3d:b7:87'
no
% is_wireless_adapter 'e0:d0:45:66:b0:c5'
yes

您还可以删除echos以便让函数返回状态代码,并能够对其执行一些不同的逻辑:

is_wireless_adapter() {
    {
        LANG=C lshw -json -class network | 
        jq -e --arg serial "$1" '.[] | select(.description == "Wireless interface" and .serial == $serial)'
    } &>/dev/null
}

答案2

/sys无需任何特殊工具就可以很容易地提取这些信息:

for i in /sys/class/net/*/; do 
  [[ 01:23:45:67:89:ab = $(cat "$i/address") && -d "$i/wireless" ]] && 
    echo "Device is wireless"
done

答案3

Kos 的回答是一种更好的方法,请使用它。我在这里依赖于简单的文本解析,因此如果 MAC 地址字符串偶然出现在我解析的输出的其他部分,我会错误地声称它是无线设备。例如,如果您在ff:ff:ff:ff:ff:ff的输出中搜索ip addr,您会找到它,但这不是现有无线设备的有效 MAC。Kos 的答案可以优雅地处理这个问题。


这是一种方法,但我不确定它有多强大:

mac=01:23:45:67:89:ab
iwconfig 2>/dev/null | grep -w "$mac" && echo "Is wireless" || echo "Is not wireless"

iwconfig命令仅显示无线网卡的信息,因此如果您的 MAC 不在其输出中,那么它就不应该来自无线设备。

或者,你可以做一些更迂回的事情,比如从中获取设备名称/proc/net/wireless,然后检查输出中的 MAC ip。像这样:

device=$(awk -F":" '!/\|/{print $1}' /proc/net/wireless )
ip addr show dev "$device" |
  grep -wq "$mac" && echo "Is wireless" || echo "Is not wireless"

在我的系统上,/proc/net/wireless看起来像这样:

$ cat /proc/net/wireless
Inter-| sta-|   Quality        |   Discarded packets               | Missed | WE
 face | tus | link level noise |  nwid  crypt   frag  retry   misc | beacon | 22
wlp9s0: 0000   40.  -70.  -256        0      0      0      0   1249        0

因此,该awk命令使用:作为字段分隔符,因此第一个字段$1将是wlp9s0,并且!/\|/确保我们只打印不包含的行|,因此我们只获取设备行而不是标题。接下来,的输出ip addr如下所示:

$ ip addr show dev wlp9s0
3: wlp9s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 70:cd:0d:57:0a:6c brd ff:ff:ff:ff:ff:ff
    inet 192.168.178.57/24 brd 192.168.178.255 scope global dynamic noprefixroute wlp9s0
       valid_lft 846797sec preferred_lft 846797sec
    inet6 2a02:8012:de3:1:929a:6dd0:d7df:53b1/128 scope global dynamic noprefixroute 
       valid_lft 5503sec preferred_lft 1903sec
    inet6 2a02:8012:de3:1:b9ec:8f1a:9da8:2c47/64 scope global dynamic noprefixroute 
       valid_lft 6907sec preferred_lft 3307sec
    inet6 fe80::929a:6dd0:d7df:53b1/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

因此,如果该输出包含您的 MAC 地址,您可以假设它确实来自无线设备。有点。如果您将 MAC 地址设置为ff:ff:ff:ff:ff:ff

当然,您可能拥有多个无线设备,因此这可能是解决这种可能性的更好的选择:

devices=( $(awk -F":" '!/\|/{print $1}' /proc/net/wireless ) )
for device in "${devices[@]}"; do
  ip addr show dev "$device" |
   grep -wq "$mac" && echo "Is wireless" || echo "Is not wireless"
done

答案4

在使用 NetworkManager 的系统上,您可以考虑使用nmcli来获取设备 MAC(称为 HWADDR)和 TYPE:

$ nmcli -e no -g GENERAL.HWADDR,GENERAL.TYPE dev show
08:00:27:8E:46:AB
ethernet

BC:AE:C5:7D:A0:AA
wifi

08:00:27:A7:C4:90
ethernet

00:00:00:00:00:00
loopback

它似乎不允许通过 MAC 直接轮询设备,因此仍然需要后期处理 - 例如awk

$ nmcli -e no -g GENERAL.HWADDR,GENERAL.TYPE dev show | 
    awk -vRS= -v mac='BC:AE:C5:7D:A0:AA' '$1 == mac {print $2}'
wifi

$ nmcli -e no -g GENERAL.HWADDR,GENERAL.TYPE dev show | 
    awk -vRS= -v mac='08:00:27:A7:C4:90' '$1 == mac {print $2}'
ethernet

如果您想将其转变为某种指示函数,您可以执行以下操作:

$ declare -f -p isWifi
isWifi () 
{ 
    nmcli -e no -g GENERAL.HWADDR,GENERAL.TYPE dev show | awk -vRS= -v mac="$1" '
    $1 == mac {found = 1; wifi = ($2 == "wifi"); exit} 
    END {exit(found == 1 ? (wifi == 1 ? 0 : 1) : 2)}
  '
}

然后

$ isWifi BC:AE:C5:7D:A0:AA; echo "$?"
0

(已找到 MAC BC:AE:C5:7D:A0:AA 且为 wifi)

$ isWifi 08:00:27:A7:C4:90; echo "$?"
1

(找到 MAC 08:00:27:8E:46:AB 但不是 wifi)

$ isWifi FF:FF:FF:FF:FF:FF; echo "$?"
2

(未找到 MAC FF:FF:FF:FF:FF:FF)。

相关内容