#bash #for-loop
Вопрос:
Я взял этот скрипт где-то в Интернете, который автоматически переключается на лучшую сеть Wi-Fi. Еще несколько недель назад все работало нормально. Я немного изменил его, чтобы попытаться выяснить, в чем проблема, и, похоже, цикл for неправильно повторяется в списке доступных сетей Wi-Fi. Любые идеи будут оценены по достоинству. Вот сценарий:
#!/bin/bash
threshold=10
# Lets do a scan first
sudo /usr/bin/nmcli -t -f ssid,signal,rate,in-use dev wifi rescan
# And get the list of known networks
known_networks_info=$(/usr/bin/nmcli -t -f name connection show | sed -e 's/^Auto //g')
echo "knowm networks"
echo $known_networks_info
# What's the current network, yet?
current_network_name=$(/usr/bin/nmcli -t -f ssid,signal,rate,in-use dev wifi list | grep ':*' | cut -d ':' -f1)
current_network_strength=$(/usr/bin/nmcli -t -f ssid,signal,rate,in-use dev wifi list | grep ':*' | cut -d ':' -f2)
echo "current net $current_network_name, strength $current_network_strength"
# Now see if we have a better network to switch to. Networks are sorted by signal strength so there's no need to check them all if the first signal's strength is not higher than current network's strength threshold.
network_list=$(/usr/bin/nmcli -t -f ssid,signal,rate,in-use dev wifi list | grep -v $current_network_name | sort -nr -k2 -t':')
echo "network list"
echo $network_list
typeset -p network_list
for network in "$network_list" ; do
network_name=$(echo $network | cut -d ':' -f1)
network_strength=$(echo $network | cut -d ':' -f2)
echo "net $network_name, strength $network_strength"
# if [[ "$network_name" == "" ]]; then continue ; fi # MESH hotspots may appear with an non existent SSID so we skip them
# if [[ "$known_networks_info" == *"$network_name"* ]]; then
# if [ $network_strength -ge $(($current_network_strength $threshold)) ]; then
# notification="Switching to network $network_name that has a better signal ($network_strength>$(($current_network_strength $threshold)))"
# echo $notification
# notify-send "$notification"
# sudo /usr/bin/nmcli device wifi connect $network_name
# else
# notification="Network $network_name is well known but its signal's strength is not worth switching"
# echo $notification
# notify-send "$notification"
# exit 0
# fi
# fi
done
Это результат приведенного выше сценария:
knowm networks
Amara Amara_EXT Kira Kira_5g Kira_5G Kira_5GEXT Kira_EXT RedmiGao RedmiKira VTR-2201458 VTR-2201458_EXT VTR-2201458_EXT2 VTR-9329907 VTR-9329907_EXT Wired connection 1
current net Amara, strength 82
network list
HUAWEI-B2368-472705:80:270 Mbit/s: HUAWEI-B2368-5G-472706:70:270 Mbit/s: Mi 10T Pro:62:130 Mbit/s: Irene.:50:130 Mbit/s: C L E Y A 5G:32:540 Mbit/s: C L E Y A:32:540 Mbit/s: Irene.:25:540 Mbit/s: Irene. 5G:22:540 Mbit/s: Mateo:15:130 Mbit/s:
declare -- network_list="HUAWEI-B2368-472705:80:270 Mbit/s:
HUAWEI-B2368-5G-472706:70:270 Mbit/s:
Mi 10T Pro:62:130 Mbit/s:
Irene.:50:130 Mbit/s:
C L E Y A 5G:32:540 Mbit/s:
C L E Y A:32:540 Mbit/s:
Irene.:25:540 Mbit/s:
Irene. 5G:22:540 Mbit/s:
Mateo:15:130 Mbit/s: "
net HUAWEI-B2368-472705, strength 80
Комментарии:
1. основной проблемой является
for
цикл разбивается$network_list
на пробелы, но не могу сказать из этого примера, если это связано с вашими изменен вывод вnmcli
выходной или пропавших двойных кавычек в первуюfor
петлю; соедините предложения: добавитьtypeset -p network_list
перед основнымfor
петлю (так мы сможем увидеть, что на самом деле в$network_list
; попробуйте добавить двойные кавычки в первомfor
цикле, например,for network in "$network_list"
(это должно2. @markp-fuso спасибо за ваши комментарии. Я обновил вопрос в соответствии с вашим первым вопросом, добавил соответствующий вывод. Я пытаюсь понять, как сделать ваш второй комментарий.
3. проигнорируйте мой 2-й комментарий (теперь удален) … Я забегал вперед; подумайте о замене внешнего
for
контура наwhile read -r network; do ... ; done <<< "${network_list}"
4. @markp-fuso спасибо, что сработало, я опубликую ответ с вашим решением
5. На самом деле, я бы рекомендовал использовать
while IFS=: read -r network_name network_strength network_speed; do ...
и пропустить использованиеcut
для извлечения этих полей.
Ответ №1:
Спасибо @markp-fuso и @GordonDavisson за комментарии, вот исправленный скрипт:
#!/bin/bash
threshold=10
# Lets do a scan first
sudo /usr/bin/nmcli -t -f ssid,signal,in-use dev wifi rescan
# And get the list of known networks
known_networks_info=$(/usr/bin/nmcli -t -f name connection show | sed -e 's/^Auto //g')
echo "knowm networks"
echo $known_networks_info
# What's the current network?
current_network_name=$(/usr/bin/nmcli -t -f ssid,signal,rate,in-use dev wifi list | grep ':*' | cut -d ':' -f1)
current_network_strength=$(/usr/bin/nmcli -t -f ssid,signal,rate,in-use dev wifi list | grep ':*' | cut -d ':' -f2)
echo "current net $current_network_name, strength $current_network_strength"
# Now see if we have a better network to switch to. Networks are sorted by signal strength so there's no need to check them all if the first signal's strength is not higher than current network's strength threshold.
network_list=$(/usr/bin/nmcli -t -f ssid,signal,rate,in-use dev wifi list | grep -wv $current_network_name | sort -nr -k2 -t':')
echo "network list"
echo $network_list
echo "checking each network"
while IFS=: read -r network_name network_strength network_rate; do
echo "net $network_name, strength $network_strength"
if [[ "$network_name" == "" ]]; then continue ; fi # MESH hotspots may appear with an non existent SSID so we skip them
if [[ "$known_networks_info" == *"$network_name"* ]]; then
if [ $network_strength -ge $(($current_network_strength $threshold)) ]; then
notification="Switching to network $network_name that has a better signal ($network_strength>$(($current_network_strength $threshold)))"
echo $notification
notify-send "$notification"
sudo /usr/bin/nmcli device wifi connect $network_name
else
notification="Network $network_name is well known but its signal's strength is not worth switching"
echo $notification
notify-send "$notification"
fi
exit 0
fi
done <<< "${network_list}"