有没有办法在命令行上给出网络接口的 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)。