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

в 9:23, , рубрики: 4g модем, bash, centos 7, linux, watchdog, Настройка Linux

Эта статья является дополнением моей предыдущий публикации о настройке домашнего роутера / файл-сервера. Здесь речь пойдет о проблеме автоматического переподключения к интернету при зависании 4G USB модема. На оригинальность идеи не претендую, просто хочу поделиться с читателями своим решением.
Сторожевой таймер для 4G модема в CentOS 7 - 1

В процессе постоянной работы, примерно раз в месяц, случалось так, что USB модем зависал. Это доставляло мне определенные неудобства: невозможность удаленно попасть на домашний компьютер, заранее поставить на закачку фильмы. Удаленно эту проблему устранить было невозможно, помогала только перезагрузка модема по питанию. Выход был единственным написать сценарий, который в определенное время проверяет доступность узла в интернете и при необходимости перезагружает модем.

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

Установка и настройка USB 4G модема в 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="yes"
BOOTPROTO="dhcp"
HWADDR="XX:XX:XX:XX:XX:XX"
NM_CONTROLLED="no"
DNS1=127.0.0.1
DNS2=127.0.0.1
DNS3=127.0.0.1
NOZEROCONF="yes"
IPV4_FAILURE_FATAL="no"
IPV6INIT="no"
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"rn' > /dev/ttyUSB0

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

#!/bin/bash
#
echo -en 'AT^NDISDUP=1,0,"internet.yota"rn' > /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 "  -i         Имя сетевого интерфейса.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 -hn" "$SN";
            exit 1
            ;;
        esac
done

if [[ "$SITE" == "" ]] || [[ "$IF" == "" ]] || [[ "$DEV" == "" ]] || [[ "$EP" == "" ]] || [[ "$MM" == "" ]] ;  then
 printf "n"
 printf "Одна или несколько опций не указаны.n"
 printf "Для справки наберите: %s -hn" "$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 через интерфейс %sn" "$SITE" "$IF"
   printf "n"
    if [[ "$EP" -ge 6 ]]; then
     printf "Число ошибочных пингов должно быть меньше или равно 5n"
     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 из %sn" "$flag" "$i"
     printf "n"

     if (("$flag" >= "$EP")); then #если потерь пакетов больше 2х
      M="$(lsusb | grep "$MM")"   #на всякий случай снова глянем - вдруг модем выдернули
      printf "Будет сброшен модем:n"
      printf "%sn" "$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 WDM device
[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, за оказанную помощь в оптимизации скрипта.

Автор: wmlex

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js