LINUX.ORG.RU
ФорумAdmin

включение и отключение 3g модема из консоли

 , ,


2

2

задачей стоит на удаленном компе поддерживать круглые сутки VPN соединение через интернет от 3g модема. я написал скриптик который пингует сервер и если пингов нет выключает и заново подключается к модему и vpn. но это не работает как система, тоесть через 40 часов отваливается, к сожалению, хотя раз в 5-15 часов скрипт срабатывает и переподключается нормально. значит этого недостаточно. как же лучше это сделать? моей идеей стало выключить питание на модеме и включить его заново. только как реализовать - не знаю. а какие идеи вы можете подсказать? система - kubuntu. причем нельзя полностью отключать все usb, а только конкретный.

листинг скрипта:

#!/bin/bash

flag=«0»

inc=«1»

for i in 1 2 3 4 5 6 7 8 9 10; do #делаем 10 пингов до сервера

ping -c 1 192.168.10.18 || flag=$(($flag+$inc)) && echo «$flag» #пинг не прошел - инкрементируем счетчик

sleep 2

done

if [ «$flag» -gt «2» ]; then #если потерь пакетов больше 2х

sudo poff bivpn

sleep 3

while true #убиваем пока не убьем дозвонщик 3g модема

do

sudo killall wvdial || break #нечего убивать? вышли из цикла

sleep 5

done

sleep 20

sudo wvdial& sleep 40 && sudo pon bivpn #поднимаем дозвонщик и через полторы минуты VPN

fi

echo «потерь $flag»

К сожалению почему-то код не форматируется по строчкам...????

но самый главный вопрос -как выключить и включить питание usb устройства



Последнее исправление: cetjs2 (всего исправлений: 5)

for i in 1 2 3 4 5 6 7 8 9 10

через 40 часов отваливается

Всё правильно, через 10 попыток отвалится. Замени на while true, если надо бесконечно. Дальше скрипт не читал, ибо оформлен ужасно и нечитаемо.

gentoo_root ★★★★★
()

Lorcode

Модем можно выключать/включать AT-командой.

Kuzz ★★★
()
Ответ на: комментарий от bykva

перечитайте скрипт теперь. for ... - делает 10 пингов.

Перечитал. Вижу, что делается 10 пингов, если больше 2 потеряно, то убиваются программы и запускаются заново. Но я нигде не вижу, чтобы весь этот процесс повторялся больше одного раза, поэтому вопрос — кто запускает этот скрипт (руками, или по крону, или он из консоли запущен как «while true; do 3g-script.sh; done»?).

А вообще, это нехороший способ проверять соединение пингами. Pppd умеет вызывать скрипты из /etc/ppp/ip-down.d при потере соединения, а проверять его можно через ifconfig. А ещё pppd умеет автоматически переподключаться при потере соединения; если wvdial так не умеет, то на помойку его и заменить на pppd.

gentoo_root ★★★★★
()
Ответ на: комментарий от gentoo_root

bykva

скрипт запускается раз в 5 минут по кронтабу

wvdial как раз таки и использует демон pptpd, он умеет это делать (persist), но проблема в том что это не спасает. попробуйте сами подержать соединение 30-40 часов. интерфейс будет поднят, а работать не будет. соответственно и скрипты из id.down выполняться не будут. ну и к тому же я не гуру никсов, я смог придумать только такой вариант, если скажете что есть идея лучше, то готов выслушать

bykva
() автор топика
Ответ на: комментарий от zolden

это не самое страшное, что сделано криво. вопрос стоял в питании модема

bykva
() автор топика

а по хорошему надо конечно с причиной разбираться, а не нагромождать костыли.
что в логах видно?

zolden ★★★★★
()

Самый надёжный способ перезапустить 3G-модем - это обрубить ему питание при помощи реле. Более простой, но менее надёжный вариант - профилактическая перезагрузка, например раз в сутки. AT-команды для разных модемов могут быть разные, так что уточни производителя и модель своего модема. И естественно, если модем уже завис, то AT-команды не помогут.

Deleted
()

но самый главный вопрос -как выключить и включить питание usb устройства

если root hub позволяет то через sysfs можно или можно попытаться usb reset команду выполнить для порта.

надо гуглить и тестировать

dimon555 ★★★★★
()
Ответ на: комментарий от bykva

Погуглировал:
http://forums.gentoo.org/viewtopic-p-6378527.html
http://ubuntuforums.org/showthread.php?t=1586753
http://marc.info/?l=linux-usb-users&m=116827193506484&w=2
http://www.clearchain.com/blog/posts/resetting-the-usb-bus-under-linux
http://forum.mikrotik.com/viewtopic.php?f=3&t=42145

Похоже, есть четыре пути:
1) слать AT команды
например, «AT+CFUN=1,1» или «AT!RESET»
2) подправить /etc/ppp/options
например:

lcp-echo-failure 0
lcp-echo-interval 0
-vj
3) использовать альтернативную звонилку
например, Sakis3g вместо NetworkManager
4) сбрасывать с помощью самопальной утилитки
например скомпилировать gcc -o outputname resetusb.c -lusb:

#include <stdio.h>
#include <usb.h>

int main(void)
{
      struct usb_bus *busses;
      usb_init();
      usb_find_busses();
      usb_find_devices();
      busses = usb_get_busses();
      struct usb_bus *bus;
      int c, i, a;
      /* ... */
      for (bus = busses; bus; bus = bus->next) {
        struct usb_device *dev;
        int val;
        usb_dev_handle *junk;
        for (dev = bus->devices; dev; dev = dev->next) {
          char buf[1024];
          junk = usb_open ( dev );
          usb_get_string_simple(junk,2,buf,1023);
          if ( junk == NULL ){
            printf("Can't open %p (%s)\n", dev, buf );
          } else {
            val = usb_reset(junk);
            printf( "reset %p %d (%s)\n", dev, val, buf );
          }
          usb_close(junk);
        }
      }
}

Заюзал путь №2, но пока не понаблюдал.

Novator ★★★★★
()

Может я и наивен, но что-то захотелось напомнить про rfkill.

aleks13
()
Ответ на: комментарий от bykva

Автоматический сброс usb 3G модема при зависании

Решил-таки задачу, используя ссылку выше:
http://marc.info/?l=linux-usb-users&m=116827193506484&w=2

1) Пишем код на C в файл
nano usbreset.c

/* usbreset -- send a USB port reset to a USB device

You invoke it as either:
  usbreset /proc/bus/usb/BBB/DDD
or
  usbreset /dev/usbB.D
*/

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/usbdevice_fs.h>

int main(int argc, char **argv)
{
	const char *filename;
	int fd;
	int rc;

	if (argc != 2) {
		fprintf(stderr, "Usage: usbreset device-filename\n");
		return 1;
	}
	filename = argv[1];

	fd = open(filename, O_WRONLY);
	if (fd < 0) {
		perror("Error opening output file");
		return 1;
	}

	printf("Resetting USB device %s\n", filename);
	rc = ioctl(fd, USBDEVFS_RESET, 0);
	if (rc < 0) {
		perror("Error in ioctl");
		return 1;
	}
	printf("Reset successful\n");

	close(fd);
	return 0;
}

2) Компилируем
gcc -o usbreset usbreset.c

1-2) Или скачиваем скомпиленный мною 8-)
http://rghost.ru/39466254

3) Создаем новый супер-скрипт
nano resetmodem.sh

#!/bin/bash

MM="Modem"
M=`lsusb | grep $MM`

if [ "$M" != "" ]; then
flag="0"
for i in {1..5}; do #делаем 5 пингов до сервера
ping -c 1 yandex.ru || flag=$(($flag+1)) && echo "пинг:$i/5 (ош.:$flag)" #пинг не прошел - инкрементируем счетчик
sleep 1
done
echo "потерь пакетов: $flag из 5"

if [ "$flag" -gt "2" ]; then #если потерь пакетов больше 2х
echo "Будет сброшен модем:"
echo $M
#B="${M:4:3}"
#D="${M:15:3}"
M="${M#* }"
B="${M::3}"
M="${M#* }"
M="${M#* }"
D="${M::3}"
echo "на шине [$B], устройство [$D]"
F="/dev/bus/usb/$B/$D"
echo "полный путь:$F"
/mnt/data/Personal/C/usbreset/usbreset $F
sleep 1
nmcli con down id "Megafon RUS 1"
sleep 10
nmcli con up id "Megafon RUS 1"
#sleep 10
fi
else
echo "Модем не найден"
fi
Примечание: путь «/mnt/data/Personal/C/usbreset/» измените на свой.

4) Добавляем строчку в кронтаб для root'а
nano /etc/crontab

*/3 *<->* * *<->root    /mnt/data/Personal/C/usbreset/resetmodem.sh
Примечание: путь «/mnt/data/Personal/C/usbreset/» измените на свой.

5) Перезапускаем крон (под root)
/etc/init.d/cron restart
Примечание: это для убутны, для других линуков может быть по-другому.

1-5) или вручную под рутом перезапускай скрипт resetmodem.sh

Novator ★★★★★
()
Ответ на: комментарий от Novator

p.s.2. Ну и последнее замечание, строка:
MM=«Modem»
это маркер модема в списке устройств
lsusb

Вы можете ставить любой маркер, по вашему вкусу, например «Huawei» или что-то подобное.

Novator ★★★★★
()
Ответ на: комментарий от ArtSh

А на ядре 3.5 работает?! ;)

А в чем подвох? Не знаю. У меня 3.2 - работает, и кстати неплохо.
Лучше ответь на такой вопрос.

Иногда соединение замирает. Синий диод на модеме горит, ifconfig показывает соединение. Но когда запускаешь пинг - он зависает, и может минуты 2-3 просто думать.

Как можно ограничить время «думания» пинга, ну например 15 секундами, т.е. давать команде ping не более 15 сек. на отработку пинга?

Как вобще в линуксе ограничивать работу команды?

Novator ★★★★★
()
Ответ на: комментарий от ABW

resetmodem.sh

Уже нашел timeout, и даже доработал скрипт.
nano resetmodem.sh

#!/bin/bash

CN='Megafon RUS 1'   #название соединения в NetworkManager'е
MM="Modem"  #маркер модема, можно заменить на "Huawei" или подобное из команды lsusb

M=`lsusb | grep $MM`  #строка модема из lsusb

if [ "$M" != "" ]; then   #если модем выбран, можно проверять пинги
  echo "Делаем пинги..."
  flag="0"
  for i in {1..5}; do #делаем 5 пингов до сервера
    timeout -s KILL 8 ping -c 1 ya.ru || flag=$(($flag+1)) && echo "пинг:$i/5 (ош.:$flag)"
    sleep 1
  done
  echo "потерь пакетов: $flag из 5"

  if [ "$flag" -gt "2" ]; then #если потерь пакетов больше 2х
    M=`lsusb | grep $MM`   #на всякий случай снова глянем - вдруг модем выдернули
    echo "Будет сброшен модем:"
    echo $M
    #B="${M:4:3}"
    #D="${M:15:3}"
    M="${M#* }"  #отбрасываем слово с пробелом (Bus)
    B="${M::3}"  #берем 3 цифры
    M="${M#* }"  #отбрасываем слово с пробелом (цифры)
    M="${M#* }"  #отбрасываем слово с пробелом (Device)
    D="${M::3}"  #берем 3 цифры
    echo "на шине [$B], устройство [$D]"
    F="/dev/bus/usb/$B/$D"
    echo "полный путь:$F"
    /mnt/data/Personal/C/usbreset/usbreset $F   #сброс usb-устройства (3G модема)!

    sleep 1
    nmcli con down id "$CN"
    for i in {1..7}; do     #делаем 7 попыток поднять соединение
      echo "попытка соединения:"$i
      sleep 2
      timeout -k 5 -s TERM 25 nmcli con up id "$CN"
      nmcli con status id "$CN"
      Err=$?
      if [ $Err == 0 ]; then
        echo "Соединение установлено."
        break
      fi
    done
  fi
else
  echo "Модем [$MM] не найден."
  lsusb
fi

Novator ★★★★★
()
Ответ на: комментарий от Novator

А в чем подвох? Не знаю. У меня 3.2 - работает, и кстати неплохо.

usbfs — deprecated, и убрана из ядра 3.5

Иногда соединение замирает. Синий диод на модеме горит, ifconfig показывает соединение. Но когда запускаешь пинг - он зависает, и может минуты 2-3 просто думать.

Соединение не замирает, просто проблемы у оператора. У меня такое часто бывает в «часы пик».

Некоторые модемы, например мой Huawei E171, посылают состояние соединения в /dev/ttyUSB2 примерно раз в секунду и уровень сигнала и тип подключения приблизительно раз в минуту, или чаще если качество сигнала изменяется.

ArtSh ★★★
()
Ответ на: комментарий от ArtSh

usbfs — deprecated, и убрана из ядра 3.5

Т.е. файловые имена юсб исчезнут, и строчка:
fd = open(filename, O_WRONLY)
будет выглядеть как-то так:
fd = openusb(bus, device, O_WRONLY)

Не в курсе как конкретно?
Но вобще спасибо за-на-водку, буду знать )

посылают состояние соединения в /dev/ttyUSB2

ttyUSBX - это я так понимаю эмуляция последовательного порта. Тут выше говорили что модем может вобще перестать откликаться на AT-команды. В этом случае аппаратный сброс - единственное решение. Второй момент: модем может показывать что всё нормально, но соединение будет дохлое - а это проверяется только пингом.

Novator ★★★★★
()
Ответ на: комментарий от Novator

Т.е. файловые имена юсб исчезнут, и строчка:

Т.е. Вам надо разбираться с /sys/bus/usb/...

Тут выше говорили что модем может вобще перестать откликаться на AT-команды.

А почему Вы решили, что в таком случае он будет откликаться на команды USB-хаба? Далеко не факт, что все хабы могут отключать питание по команде (и что же это за команда, было бы интересно узнать).

ArtSh ★★★
()
Ответ на: комментарий от ArtSh

Вам надо разбираться с /sys/bus/usb/...

Не подскажите какой функцией это делать? (Я в сях не очень).

А почему Вы решили, что в таком случае он будет откликаться на команды USB-хаба?

Я не решал такого. Более того, из суточных наблюдений выяснилось, что модем иногда намертво зависает (один раз в сутки так завис), что даже команда..

(и что же это за команда, было бы интересно узнать).

..описанная выше в C-коде:
rc = ioctl(fd, USBDEVFS_RESET, 0);
не помогает.
Но эта команда, во-первых, более низкоуровневая, чем AT-команда, т.е. модем может не отвечать на AT, но на шине usb будет. Во-вторых, она применима для любого не то что модема, а даже для любого usb-устройства. Команды же AT могут отличаться для разных модемов.

Вот кстати другие аппаратные команды для usb (если интересно):
http://tali.admingilde.org/linux-docbook/usb/ch07s06.html

Novator ★★★★★
()
Ответ на: комментарий от Novator

Не подскажите какой функцией это делать? (Я в сях не очень).

в sysfs можно писать хоть на баше, хоть на питоне. В интернете можно встретить упоминание, что «сброс» устройства можно эмулировать как

# echo suspend > /sys/bus/usb/devices/.../power/level
# echo auto > /sys/bus/usb/devices/.../power/level

USBDEVFS_RESET

не отключает порт, а лишь запускает процедуру сброса. Если устройство не отвечает, то ему эта команда будет до лампочки, ведь питание то не отключается.

Команды же AT могут отличаться для разных модемов.

AT+CFUN должен понимать любой модем.

т.е. модем может не отвечать на AT, но на шине usb будет.

Выше Вы написали что это не помогает.

Более того в спецификации USB-2.0 (глава 11.11)сказано:

Self-powered hubs may have power switches that control delivery of power downstream facing ports but it is not required. Bus-powered hubs are required to have power switches. A hub with power switches can switch power to all ports as a group/gang, to each port individually, or have an arbitrary number of gangs of one or more ports.

Таким образом, не существует универсального способа программным образом эмулировать выдёргивание и втыкание модема. Если повезёт, то можно воспользоваться http://marc.info/?l=linux-usb-devel&m=113724451205634

ArtSh ★★★
()
Ответ на: комментарий от ArtSh

Интересная информация. Респект.

Я понял что хабы USB 2.0 с внешним питанием могут иметь программное управление питанием, но не обязаны. По ссылке краз приводится список из трех производителей и утилита для управления питанием и индикаторами портов.

Bus-powered hubs are required to have power switches.

Правильно ли я понял, что хабы USB 2.0 с питанием от шины ОБЯЗАНЫ иметь управление питанием?

p.s. Кстати, поглядел свой встроенный usb-хаб по lsusb -v, там явно указано:

Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Hub Descriptor:
  wHubCharacteristic 0x000a
    No power switching (usb 1.0)
т.е. - борода! )

p.s.2. По крайней мере описаное мной выше решение справляется с 99% зависаний. Ну а в идеале нужно иметь хаб усб 2.0 с поддержкой управления питанием.

Novator ★★★★★
()

Пока тема не закрылась, публикую последнюю версию скрипта resetmodem.sh:

#!/bin/bash

CN='Megafon RUS 1'   #название соединения в NetworkManager'е
MM="Modem"  #маркер модема, можно заменить на "Huawei" или подобное из команды lsusb
EP="3"      #число ошибочных пингов

ps -few | grep "resetmodem.sh"
RC=`ps -few | grep "resetmodem.sh" | wc -l`

if [ "$RC" -gt "4" ]; then
  echo "Уже запущена копия resetmodem.sh"
  exit 1
fi


M=`lsusb | grep $MM`  #строка модема из lsusb

if [ "$M" != "" ]; then   #если модем выбран, можно проверять пинги
  echo "Делаем пинги..."
  flag="0"
  for i in {1..5}; do #делаем 5 пингов до сервера
    timeout -k 2 -s TERM 16 ping -w 14 -s 8 -c 1 ya.ru || flag=$(($flag+1)) && echo "пинг:$i/5 (ош.:$flag)" #пинг не прошел - инкрементируем счетчик
    if [ "$flag" -ge "$EP" ]; then
      break
    else
      sleep 1
    fi
  done
  echo "потерь пакетов: $flag из $i"

  if [ "$flag" -ge "$EP" ]; then #если потерь пакетов больше 2х
    M=`lsusb | grep $MM`   #на всякий случай снова глянем - вдруг модем выдернули
    echo "Будет сброшен модем:"
    echo $M
    #B="${M:4:3}"
    #D="${M:15:3}"
    M="${M#* }"  #отбрасываем слово с пробелом (Bus)
    B="${M::3}"  #берем 3 цифры
    M="${M#* }"  #отбрасываем слово с пробелом (цифры)
    M="${M#* }"  #отбрасываем слово с пробелом (Device)
    D="${M::3}"  #берем 3 цифры
    echo "на шине [$B], устройство [$D]"
    F="/dev/bus/usb/$B/$D"
    echo "полный путь:$F"
    /mnt/data/Personal/C/usbreset/usbreset $F   #сброс usb-устройства (3G модема)!

    sleep 1
    nmcli con down id "$CN"
    sleep 6
    for i in {1..5}; do     #делаем 5 попыток поднять соединение
      echo "попытка соединения:"$i
      sleep 3
      timeout -k 5 -s TERM 15 nmcli con up id "$CN"
      nmcli con status id "$CN"
      Err=$?
      if [ $Err == 0 ]; then
        echo "Соединение установлено."
        break
      fi
    done
  fi
else
  echo "Модем [$MM] не найден."
  lsusb
fi

Что нового:
1) введена защита от одновременного запуска нескольких копий;
2) константы оптимизированы под реальную работу;
3) небольшие улучшения некоторых команд.

Скрипт запускается каждые две минуты по шедулеру от имени рута.
В целом решение работает хорошо. Почти всегда модем сбрасывается (по моим прикидкам раз 100 в суки), но иногда (раз в сутки) модем может намертво повиснуть. Чтобы побороть эту проблему, нужно покупать управляемый хаб, о чем чуть выше говорилось. Для меня в этом пока нет особой нужды.

Novator ★★★★★
()
3 ноября 2012 г.
Ответ на: комментарий от Novator

вообщем почти работает, доработал ваш скрипт,тк knetwork-manager не всегда хотел через команду nmcli con up id «$CN» включать соединение, проблема решалась так: for i in {1..5}; do #делаем 5 попыток поднять соединение echo «попытка соединения:»$i sleep 3 /etc/init.d/network-manager restart # перезапустить network-manager timeout -k 5 -s TERM 15 nmcli con up id «$CN» nmcli con status id «$CN» Err=$? if [ $Err == 0 ]; then echo «Соединение установлено.» break fi done и то в цикле тк network-manager на второй раз включал созданое соединение и уже сам поднимал созданное соединение, у меня зависания модема не было. моя проблема была в следующем: провайдер не обновлял трафик(безлимит) (не поднимал скорость в 00:00) и скачивание было на прежней скорости(малой), позвонил, они проблему не решили, только стали обрубать модем в 00:00 и все. По скрипту: не всегда командой поднималось соединение, пришлось перезагружать network-manager, и он уже сам поднимал соединение, и то не всегда(после ~попыток пяти) на второй раз. Все. Большое спасибо Novator.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.