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

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


    В процессе постоянной работы, примерно раз в месяц, случалось так, что 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"\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
    
    export PATH="$PATH:/usr/sbin"
    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 -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 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, XX:XX:XX:XX:XX:XX
    

    Сразу скажу, скрипт очень далек от идеала, поэтому с радостью приму советы и обоснованную критику в свой адрес.
    Отдельно хочу поблагодарить пользователя с Toster.ru под ником @AlekseyNemiro, за оказанную помощь в оптимизации скрипта.

    UPD 22.01.16 Дополнил скрипт командой добавления пути в переменную PATH.
    Будет ли Вам полезен данный скрипт?

    Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

    • +6
    • 11,7k
    • 5
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 5
    • –6
      Никто watchdog не переводит как «Сторожевой таймер». Да и вообще не переводят, это уже устоявшийся термин.
      • 0
        В целом, неплохо.
        Когда-то писал нечто подобное, чтобы передергивать YOTA-модем, реализовывал путем отправки «0» в /sys/bus/usb/devices/DEV/power/autosuspend для выключения питания, и «auto» в /sys/bus/usb/devices/DEV/power/level для включения. И ведь помогало)
        • 0
          Просветите, пожалуйста, а все ли материнские платы умеют отключать питание USB?
          • 0
            Вроде как большинство умеет. А вот на бытовых роутерах, зачастую, обратная ситуация: мало кто умеет коммутировать USB питание, поскольку в целях экономии оно заведено напрямую. А значит для комбинаций роутер + модем приходится выдумывать альтернативные схемы.
            • 0
              Там может не отключение питания, а сброс шины USB возможен. При удалённом доступе к компу на Windows «передёргивали» устройство путём отключения/подключения USB-хаба в диспетчере задач.

            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.