I have a host who can be connected by wifi or by ethernet. According to the link I want to make actions.
How to detect that with a script ?
答案1
The interface used for each type of link is different. Say, the ethernet interface could be eth0 and the WLAN interface could be wlan0. Knowing the names you could find which is active and act accordingly.
To list all interface and show their status use the command ip link show
. This command works in the modern flavors of Linux, and so the rest of the utils and Bash shell. I suppose you could adapt it to any OS (In Windows, I suggest using cygwin and awk or Python to parse the ipconfig or netsh output, or PowerShell Get-NetAdapter module).
Example output:
user@host$ ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether 00:50:56:9b:90:7d brd ff:ff:ff:ff:ff:ff
You could then filter the interface name/status using grep
looking for lines starting with a number:
user@host$ ip link show | grep "^[0-9]"
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
The active interfaces have the word UP, so to get the active one filter out the local interface localhost (lo:):
user@host$ ip link show | grep "^[0-9]" | grep -v "lo: " | grep "UP"
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
We need only the interface name, the second word:
user@host$ ip link show | grep "^[0-9]" | grep -v "lo: " | grep "UP" | cut -d ':' -f 2
ens32
You could store this result in some variable (in Bash):
ACTIVEIF=$(ip link show | grep "^[0-9]" | grep -v "lo: " | grep "UP" | cut -d ':' -f 2)
Of course, if you have more than one active interface store the list in an array of names adding parenthesis and spaces around the result. For example (from now on, I won't filter lo:, as I only have one physical interface):
ACTIVEIFACES=( $(ip link show | grep "^[0-9]" | grep "UP" | cut -d ':' -f 2) )
要检查数组变量内容:
user@host$ set | grep ^ACTIVEIFACES
ACTIVEIFACES=([0]="lo" [1]="ens32")
并在脚本中列出它们:
ACTIVEIFACES=( $(ip link show | grep "^[0-9]" | grep "UP" | cut -d ':' -f 2) )
NIFACES=${#ACTIVEIFACES[@]}
if [ $NIFACES -ne 0 ] ; then
echo "There exist $NIFACES active interfaces:"
for ((i=0; i<NIFACES; i++)) ; do
echo "${ACTIVEIFACES[$i]}"
done
else
echo "There is no active interfaces detected"
fi
(由于该for
命令使用数字表达式,因此您可以省略双括号之间的 $i 和 $NIFACES 中的 $)。
在我的例子中,脚本输出是:
There exist 2 active interfaces:
lo
ens32
我希望这个方法对你有用。祝你好运!
答案2
天真的答案是监视接口,但是当插入(以太网)或关联(wifi)时,第 2 层接口将注册为“启动”,但这本身并不能告诉您它是否会用于承载流量。
相反,监视默认路由的更改可能更有效。
该ip mon
命令可用于跟踪更改,但即使看起来没有任何更改,它也会定期提供状态更新,因此您需要做好忽略这些更改的准备。
(建议使用该-o
选项,以便每个报告都占一行;这使得解析更加简单。)
#!/bin/bash
ip -o mon |
sed -e 's/\\/ /g
s/ */ /g
s/^\(Deleted \|\)\([0-9]*\): \([^ :]*\) /\1addr \2 \3 /
s/^\(Deleted \|\)\([0-9]*\): \([^ :]*\): /\1link \2 \3 / ' |
while
IFS=' ' read -ra line
do
if [[ ${line[0]} = Deleted ]]
then
mode=delete
line=( "${line[@]:1}" ) # shift(line)
else
mode=update
fi
case "${line[*]}" in
addr) # added by 'sed' above
device_num=${line[1]}
device_name=${line[2]}
family=${line[3]} # 'inet' or 'inet6'
ip_address=${line[4]}
# ... handle address changes ...
;;
link) # added by 'sed' above
device_num=${line[1]}
device_name=${line[2]%:}
state=${line[3]} # eg '<BROADCAST,MULTICAST,UP,LOWER_UP>'
# ... handle link UP/DOWN ...
;;
default)
# ... handle default route changes ...
;;
prefix | local | broadcast | multicast | throw | unreachable | prohibit | blackhole )
# ... handle other route changes ...
;;
esac
done