Сторожовий таймер для 4G модем в CentOS 7

Ця стаття є доповненням моїй попередній публікації створення домашнього роутера / файл-сервера. Тут мова піде про проблему автоматичного перепідключення до інтернету при зависанні 4G USB модему. На оригінальність ідеї не претендую, просто хочу поділитися з читачами своїм рішенням.


У процесі постійної роботи, приблизно раз на місяць, траплялося так, що USB модем зависав. Це приносило певні незручності: неможливість віддалено потрапити на домашній комп'ютер, заздалегідь поставити на закачку фільми. Віддалено цю проблему вирішити було неможливо, допомагала тільки перезавантаження модему по харчуванню. Вихід був єдиним написати сценарій, який у визначений час перевіряє доступність сайту в інтернеті і при необхідності перезавантажує модем.

В інтернеті я знайшов декілька реалізацій, але не одна з них у мене нормально не запрацювала. Тому я вирішив написати свій сторожовий таймер з преферансом і панянками. За основу був узятий скрипт з цієї теми. Переписаний, наскільки мені дозволяє моя кваліфікація, і доповнено новими можливостями такими як зовнішні опції.

Установка і настройка 4G USB модему в CentOS 7.Для початку необхідно завантажити відсутні пакети.
yum install usb_modeswitch usb_modeswitch-data

Підключити модем і подивитися як він визначається в системі.
dmesg
ip a

Далі необхідно налаштувати інтерфейс 4G модем.
vim /etc/sysconfig/network-scripts/ifcfg-wwp6s0u1i1

DEVICE="wwp6s0u1i1"
NAME="wwp6s0u1i1"
TYPE="Ethernet"
ONBOOT="так"
BOOTPROTO="dhcp"
HWADDR="XX:XX:XX:XX:XX:XX"
NM_CONTROLLED="ні"
DNS1=127.0.0.1
DNS2=127.0.0.1
DNS3=127.0.0.1
NOZEROCONF="так"
IPV4_FAILURE_FATAL="ні"
IPV6INIT="ні"
ZONE="external"

Створюємо скрипти для активації і де активації інтернету при включенні або відключенні інтерфейсу.
vim /sbin/ifup-pre-local

#!/bin/bash
#
PREUP="./etc/sysconfig/network-scripts/pre-up-${1:6}"
if [ -x $PREUP ]; then
exec $PREUP
fi

vim /sbin/ifdown-pre-local

#!/bin/bash
#
PREDOWN="./etc/sysconfig/network-scripts/pre-down-$1"
if [ -x $PREDOWN ]; then
exec $PREDOWN
fi

vim /etc/sysconfig/network-scripts/pre-up-wwp6s0u1i1

#!/bin/bash
#
echo -en 'AT^NDISDUP=1,1,"internet.yota"\r\n' > /dev/ttyUSB0

vim /etc/sysconfig/network-scripts/pre-down-wwp6s0u1i1

#!/bin/bash
#
echo -en 'AT^NDISDUP=1,0,"internet.yota"\r\n' > /dev/ttyUSB0

Тут ttyUSB0 це порт модему.

Піднімаємо інтерфейс і перевіряємо з'єднання.
ifup wwp6s0u1i1
ip a


Безпосередньо сам скрипт
#!/bin/bash

SN="$(basename "$0")"

function print_help() {
printf "\n"
printf "Використання: %s options...\n" "$SN"
printf "Параметри:\n"
printf " -s Перевіряється ресурс.\n"
printf " і Ім'я мережного інтерфейсу.\n"
printf " -d Шина і порт модему lsusb -t.\n"
printf " -n Число помилкових пінгів.\n"
printf " -m Маркер модему, з команди lsusb.\n"
printf " -h Довідка.\n"
printf "\n"
}

# Якщо скрипт запущено без аргументів, відкриваємо довідку.
if [[ $# = 0 ]]; then
print_help && exit 1
fi
while getopts ":s:i:d:n:m:h" opt ;
do
case $opt in
s) SITE=$OPTARG;
;;
i) IF=$OPTARG;
;;
d) DEV=$OPTARG;
;;
n) EP=$OPTARG;
;;
m) MM=$OPTARG;
;;
h) print_help
exit 1
;;
*) printf "Неправильний параметр\n";
printf "Для виклику довідки запустіть %s -h\n" "$SN";
exit 1
;;
esac
done

if [[ "$SITE" == "" ]] || [[ "$IF" == "" ]] || [[ "$DEV" == "" ]] || [[ "$EP" == "" ]] || [[ "$MM" == "" ]] ; then
printf "\n"
printf "Одна або кілька опцій не вказані.\n"
printf "Для довідки наберіть: %s -h\n" "$SN"
printf "\n"
exit 1
fi

M="$(lsusb | grep -w "$MM")" #рядок модему з lsusb


if [[ "$M" != "" ]]; then #якщо модем обраний, можна перевіряти пінги

if grep -w -q "$IF" /proc/net/dev; then #перевіряємо наявність мережного інтерфейсу
printf "\n"
printf "Перевірка доступності %s через інтерфейс %s\n" "$SITE" "$IF"
printf "\n"
if [[ "$EP" -ge 6 ]]; then
printf "Число помилкових пінгів повинно бути менше або дорівнює 5\n"
exit 1
else
printf "Робимо пінги...\n"
flag="0"
for i in {1..5}; do #робимо 5 пінгів до сервера
timeout -k 2 -s TERM 16 ping -w 14 -s 8 -c 1 -I "$IF" "$SITE" || flag=$((flag+1)) && printf "пінг:%s/5 (помилок:%s)\n" "$i" "$flag" #пінг не пройшов - інкрементуємо лічильник
if (("$flag" >= "$EP")); then
break
else
read -r -t 1 > /dev/null
fi
done
printf "втрат пакетів: %s з %s\n" "$flag" "$i"
printf "\n"

if (("$flag" >= "$EP")); then #якщо втрат пакетів більше 2х
M="$(lsusb | grep "$MM")" #на всяк випадок знову глянемо - раптом модем висмикнули
printf "Буде скинутий модем:\n"
printf "%s\n" "$M" | cut -c 34-
if ! [[ -d /sys/bus/usb/drivers/usb/"$DEV" ]]; then
printf "Невірно вказані Bus і Port модему.\n"
exit 1
else
ifdown "$IF" #деактивуємо інтерфейс
printf "%s" "$DEV" > "/sys/bus/usb/drivers/usb/unbind" && printf "%s" "$DEV" > "/sys/bus/usb/drivers/usb/bind" #перезегрузка модему
# read -r -t 1 > /dev/null
ifup "$IF" #активуємо інтерфейс
fi
fi
fi
else
printf "\n"
printf "Інтерфейс %s не існує\n" "$IF"
printf "\n"
exit 1
fi
else
printf "Модем %s не знайдений.\n" "$MM"
fi


Скрипт розташовується в /usr/local/bin/.
Щоб скрипт запускався автоматично, раз в п'ять хвилин, додамо завдання cron.
crontab -e

*/5 * * * * /usr/local/bin/watchdog -m Huawei -s ya.ru -i wwp6s0u2i1 -n 3 -d 1-1 > /dev/null 2 > &1

Це висновок dmesg, на ньому видно скидання модему при виконанні скрипта.
[181709.595498] option1 ttyUSB0: GSM modem (1-port) converter now disconnected from ttyUSB0
[181709.595568] option 1-1:1.0: device disconnected
[181709.595798] huawei_cdc_ncm 1-1:1.1 wwp6s0u2i1: unregister 'huawei_cdc_ncm' usb-0000:06:00.0-1, Huawei CDC NCM device
[181709.615005] option 1-1:1.0: GSM modem (1-port) converter detected
[181709.616597] usb 1-1: GSM modem (1-port) converter now attached to ttyUSB0
[181709.623449] usb 1-1: MAC-Address: 0c:5b:8f:27:9a:64
[181709.623958] huawei_cdc_ncm 1-1:1.1: cdc-wdm0: USB device WDM
[181709.624341] huawei_cdc_ncm 1-1:1.1 wwan0: register 'huawei_cdc_ncm' at usb-0000:06:00.0-1, Huawei CDC NCM device, 0c:5b:8f:27:9a:64

Відразу скажу, скрипт дуже далекий від ідеалу, тому з радістю прийму поради і обґрунтовану критику в свою адресу.
Окремо хочу подякувати користувача з Toster.ru під ніком @AlekseyNemiro, за надану допомогу в оптимізації скрипта.

Буде Вам корисний даний скрипт?

/>
/>


<input type=«radio» id=«vv70989»
class=«radio js-field-data»
name=«variant[]»
value=«70989» />
Так.
<input type=«radio» id=«vv70991»
class=«radio js-field-data»
name=«variant[]»
value=«70991» />
Немає.

Проголосувало 39 осіб. Утрималося 23 людини.


Тільки зареєстровані користувачі можуть брати участь в опитуванні. Увійдіть, будь ласка.


Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.