Network Manager, wvdial и T-Mobile

Давненько я ничего не писал. Сейчас я в отпуске, в солчнечной Черногории. И интернет у меня мобильный, от местного оператора T-mobile. Обычно я использую для выхода в интернет свой телефон с местной симкой в качестве модема, и звонилку wvdial со следующими настройками:

# cat /etc/wvdial.conf
[Dialer Defaults]
Init1 = ATZ
Init2 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0
Init3 = AT+CGDCONT=1,”IP”,”tmcg-wnw”
Modem = /dev/ttyACM0
Phone = *99#
Idle Seconds = 30000
Modem Type = USB Modem
Stupid Mode = 1
Compuserve = 0
Baud = 460800
Auto DNS = on
New PPPD = Yes
Dial Command = ATDT
Ask Password = 0
ISDN = 0
Password = 38167
Username = 38167

Это отлично работает, если сеть управляется через Wicked в OpenSuSe Leap 42.1. Но если сеть управляется через Network Manager, то при использовании звонилки настройки DNS сетью не подхватываются. Однако, в Network Manager предусмотрена возможность подключения к сети через модем, только стандартные настройки для оператора T-Mobile в Черногории не подходят. Для этого оператора указана точка доступа для тарифных планов Postpaid, требующих заключение договора с оператором. Для Prepaid необходимо поменять настройки точки доступа с tmcg-data на tmcg-wnw:

Настройки T-Mobile

Про формат дампов mysql

Смеркалось. Прилетела задача, залить в mysql таблицу, в которой есть несколько миллиардов записей. Консольная утилита отказывалась ее заливать, с очень непонятным сообщением об ошибке:

mysql -u root -p -D dbname <dump.sql
ERROR 2006 (HY000) at line 2024: MySQL server has gone away

Выяснилось, что за количество вносимых записей за один оператор отвечает параметр настройки max_allowed_packet, и его значение рекомендуется увеличить. Однако, выставить его в число, превышающее 4194304, не получается; и 4 млн записей за раз оказалось недостаточно для загрузки в базу такого дампа.

Выход был найден, пришлось дамп снять со следующими параметрами:

mysqldump -u root -p --opt --skip-extended-insert --skip-quick  dbname tablename >dump.sql

Дамп очень сильно разросся, зато теперь он имел отдельный insert на каждую строчку таблицы. Загружался он очень долго, но все-таки загрузился.

Логирование трафика в tcpdump

tcpdump уже давно стал незаменимым инструментом логирования трафика для последующего его анализа, например, в wireshark. Однако есть проблема, трафик идет постоянно и записываемый файл может стать огромным и съесть все доступное дисковое пространство. Для того, чтобы избежать подобных неприятностей, в tcpdump предусмотрено ограничение на размер файла и количество файлов для ротации. В общем, скрипт логирования будет выглядеть примерно так:

nohup /usr/sbin/tcpdump -vvv -C 50 -W 5 -s0 'host 192.168.0.15 and port 5060' -w /tcpdump_logs/192.168.0.15.cap >/dev/null 2>/dev/null &

Директория /tcpdump_logs должна быть доступна для записи для пользователя pcap

Firefox 40 и проигрывание mp3 в браузере

Случайно заметил, при открытии mp3 файла в firefox 40 файл не проигрывался, при этом выдавалось следующее сообщение об ошибке:

Video can’t be played because file is corrupt

При этом прослушивать перевод, например, в Google Translate или в Яндекс.Словари не представлялось возможным, файлы просто не проигрывались.

Я довольно долго разбирался, в чем дело, и выяснил — в Firefox внедрили нативную поддержку некоторых audio форматов, в том числе и mp3. Но не все кодеки доступны из коробки, некоторые требуют лицензионной чистоты, что не соответствует политике Mozilla Foundation. В общем, надо было браузеру явным образом указать на возможность fallback на плагин, умеющий проигрывать неподдерживаемый кодек. В Linux это делается путем установки 2-х настроек в about:config:

media.gstreamer.enabled => true
media.gstreamer.enable-blacklist => false

После указанных манипуляций firefox стал проигрывать mp3 файлы, даже при запуске из командной строки.

Логирование HTTP трафика для отладки запросов AJAX в Linux

Часто разработчику требуется видеть весь обмен трафиком между клиентом и сервером, не только заголовки HTTP, но и тело запроса и ответа. Я довольно долго разыскивал подходящий инструмент для этих целей. Но оказалось, что удобнее всего пользоваться не какими-то плагинами для браузера, а простейшим прокси и перехватом трафика с помощью tcpdump.

Выглядит это так:

1. В браузере прописываем использование прокси по адресу 127.0.0.1 порт 5678
2. В терминале открываем сессию ssh с локальным порт-форвардингом (можно и со сжатием трафика), например так:

$ ssh -C -D 5678 username@myhost.com

3. В другом терминале запускаем tcpdump и слушаем трафик на интерфейсе lo порт 5678:

# tcpdump -vvv -s0 ‘port 5678′ -w “/home/username/http.pcap” -i lo

Далее в браузере выполняем необходимые действия, после чего останавливаем tcpdump. Смотреть записанный трафик лучше всего с помощью strings:

$ strings /home/username/http.pcap

Иногда в выводе может быть немного мусора из-за keepalive запросов, но в целом видно все, что требовалось узнать.

Запуск джоба чаще, чем 1 раз в минуту

Старый добрый cron не позволял ставить в расписание задачи, которые бы запускались чаще, чем 1 раз в минуту. Приходилось решать подобные задачи совсем другими способами. Но теперь есть systemd, который умеет это делать.

Пример такой конфигурации:

server:/etc/systemd/system # cat my.service
[Unit]
Description=My Script

[Service]
Type=simple
ExecStart=/path/to/my/script.sh
StartLimitInterval=0
StartLimitBurst=0

server:/etc/systemd/system # cat my.timer
[Unit]
Description=Runs job every 10 seconds

[Timer]
OnBootSec=1sec
OnCalendar=*-*-* *:*:0,10,20,30,40,50
Unit=my.service

[Install]
WantedBy=multi-user.target

Запуск таймера:

# systemctl start my.timer

Добавление в автозагрузку:

# systemctl enable my.timer

Мониторинг работы:

# journalctl -f

Новый сервис: онлайн форматирование JSON

Давненько я не писал что-нибудь общественно-полезного. А тут как раз пришлось писать очердной вебсервис с блэкджеком и шлюхами, который должен выплевывать неотформатированный JSON, и в целях отладки мне пришлось его форматировать скриптами.

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

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

В качестве теста можно использовать строку JSON, например, такую:

{"data":[{"t1":"John","t2":"Doe"},{"t1":"Anna","t2":"Smith" },{"t1":"Peter" ,"t2":"Jones"}]}

На выходе будет удобно читаемый JSON:

{
   "data" : [
      {
         "t2" : "Doe",
         "t1" : "John"
      },
      {
         "t2" : "Smith",
         "t1" : "Anna"
      },
      {
         "t2" : "Jones",
         "t1" : "Peter"
      }
   ]
}

Обычным людям такой сервис вряд ли будет не нужен, но программистам – пригодится.

Как сделать скриншот страницы с нестандартным разрешением в Firefox

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

В меню заходим в Tools / Web Developer / Developer Toolbar (или жмем Shift + F2), и в консоли пишем:

resize to 1920 5000
screenshot /tmp/output.png

И все, в /tmp/output.png будет сохранен скриншот области Firefox разрешением 1920×5000

Оживление почти убитого D-Link DNS 320l

У меня этот чудо девайс работает уже полтора года. Работает отлично, и особых нареканий к нему нет. Разве что стоковая прошивка совсем уж бедная по своим возможностям, и чтобы более полноценно использовать D-Link DNS 320l, желательно установить на него fun_plug, или прошить альтернативной прошивкой Alt-f.

fun_plug я поставил в первую очередь, и он мне очень понравился. Можно ставить дополнительные программы, использовать всю мощь доступа по ssh, в том числе и для бэкапа важных данных через rsync. Все просто замечательно было с fun_plug, если бы не сильно урезанное ядро системы. Уж не знаю зачем, но D-Link в своем firmware из ядра выпилил модуль iptables, и без него невозможно настроить nat, маскарадинг и прочие прелести. А мне вот что-то вдруг захотелось развернуть на своем аппарате OpenVPN, и я решил таки сменить прошивку на Alt-f.

Кстати, Alt-f — молодцы, сделали весьма качественный продукт. Комьюнити проекта пока не очень большое, но оно динамично развивается. Мне прошивка в целом понравилась, но в ней есть и минусы:

1. Веб интерфейс D-Link DNS 320l в прошивке Alt-F весьма убог по сравнению с родым firmware D-Link. Это не так критично, если конфигурировать устройство через консоль, но все равно — неприятно.

2. По умолчанию после установки прошивки у меня не запустился важны демон — dns320l-daemon. Он снимает показания с датчиков температуры и без него вентилятор охлаждения просто не запустится. А это уже серьезно, поскольку чревато перегревом как процессора, так и винчестеров и выходом их из строя. Проблема эта легко устраняется, но надо знать, что проблема существует.

3. Самое раздражающее в новой прошивке — это невозможность выключить сетевое хранилище программно. Нажатие на кнопку Power не выключает его, но останавливает работу всех сервисов и переводит коробочку в режим ожидания. И выключить хранилище по расписанию уже не представляется возможным, оно просто уйдет в спячку и дальше будет гудеть своим вентилятором.

В общем, поигравшись вдоволь с прошивкой Alt-F, я все-таки решил откатиться к прошивке оригинальной D-Link. И тут случилось страшное, во время перепрошивки хранилища пропало питание — и D-Link DNS 320l перестал загружаться. Совсем. Кнопка сброса к заводским установкам не помогла — достучаться до хранилища не было никакой возможности.

Последней надеждой была возможность подключения к хранилищу через serial console, для этого надо было найти соответствующие места на плате хранилища и припаять к ним провода. Но пайка проводов — это полбеды; настоящей проблемой было найти переходник RS232-ttl или USB-ttl. Причем DNS 320l использует низковольтный ttl (3.3 вольта), поэтому далеко не факт, что подойдет переходник на 5-вольтовый TTL. У нас в городе так и не удалось найти ни одного готового переходника, или подходящего телефонного дата-кабеля для создания такого переходника. Пришлось заказывать переходник в Китае, на AliExpress.

Удивительно, но покупка двух переходников на микросхеме PL2303 в Китае с доставкой в Россию оказалась намного выгоднее, чем покупка отдельных деталей и сборка своими силами. Я отдал меньше 1 доллара за каждый из переходников, а заказал я их 2 штуки — поскольку предполагал, что своими неумелыми действиями я могу спалить этот переходник. В общем, мне удалось подключить переходник к плате хранилища, и при включении питания хранилища я мог видеть все сообщения загрузки системы.

Выяснилось, что загрузчик u-boot был в полном порядке, а вот при попытке загрузки ядра выскакивало следующее сообщение:

...
starting pid 538, tty '': '/etc/rc.sh'
** Mounting /etc/fstab
umount: proc: not mounted
umount: proc: not mounted
umount: /usr/local/modules: not mounted
sh: can't open /usr/sbin/pre_usb.sh
umount: /usr/local/tmp/image.cfs: not found
umount: /usr/local/tmp: not mounted
first good block is 0
image len = 1835626867 , image checksum = 5f656761
kernel or ramdisk error
...

Образ рамдиска или ядра был битым во флеш-памяти, я мне надо было его перезаписать по новой. Говорят, как-то можно перезаписать флеш-память командами из u-boot, но я поступил по-другому.

Сначала я скачал firmware Alt-f, и с помощью утилиты dns323-firmware-tools-master извлек из firmware образ ядра и рамдиска:

splitdns323fw -k uKernel -i uInitrd -d uDefaults -s uSquashfs Alt-F-0.1RC4-DNS-320L-rev-A1.bin

На выходе получил файлы uKernel, uInitrd, uDefaults и uSquashfs (последние 2 не понадобились). Далее, развернул сервер tftp и в его корень положил полученные файлы. Потом, при загрузке хранилища в нужном месте нажал пробел и единицу, в результате получил доступ к командной строке u-boot:

 ** MARVELL BOARD: DB-88F6702A-BP LE
U-Boot 1.1.4 (Aug 22 2012 - 17:06:54) Marvell version: 3.6.0.DNS-320L.01
U-Boot code: 00600000 -> 0067FFF0  BSS: -> 006CFB00
Soc: 88F6702 A1 CPU running @ 1000Mhz L2 running @ 500Mhz
SysClock = 400Mhz , TClock = 166Mhz
DRAM (DDR2) CAS Latency = 5 tRP = 5 tRAS = 18 tRCD=6
DRAM CS[0] base 0x00000000   size 256MB
DRAM Total size 256MB  16bit width
Addresses 8M - 0M are saved for the U-Boot usage.
Mem malloc Initialization (8M - 7M): Done
NAND:128 MB
Flash:  0 kB
CPU : Marvell Feroceon (Rev 1)
Streaming disabled
Write allocate disabled
USB 0: host mode
PEX 0: interface detected no Link.
Net:   egiga0 [PRIME]
Hit any key to stop autoboot:  0
Marvell>>

Про «Hit any key to stop autoboot» они конечно переврали, надо нажимать строго Пробел и потом цифру 1. Дальше последовательность действий была такой:

setenv ipaddr 192.168.1.7 # прописываю IP адрес сетевого хранилища
setenv serverip 192.168.1.9 # прописываю IP адрес tftp-сервера
tftp 0xa00000 uKernel # загружаю образ ядра в формате u-boot в память по адресу 0xa00000
tftp 0xf00000 uInitrd # загружаю initrd в память по адресу 0xf00000
bootm 0xa00000 0xf00000 # запускаю операционную систему БЕЗ перешивания флеш памяти — если что-то пойдет не так, всегда можно перезагрузиться.

Через некоторое время загрузился интерфейс Alt-F по адресу http://192.168.1.7 В нем уже есть возможность полноценно залить прошивку Alt-F или D-Link во флеш-память. После перепрошивки перезагрузился — и все заработало. Правда, при перепрошивке слетели все настройки — но это уже мелочи, сетевое хранилище удалось оживить.

Perl: как избавиться от Wide character in print

Как известно, при запуске программы на Perl автоматически открываются 3 файловых дескриптора: STDIN, STDOUT и STDERR. По умолчанию они не используют кодировку utf8, поэтому print вполне может выдавать вот такой вот warning при выводе кириллических символов:

Wide character in print at line …

Ничего страшного в этом нет, но такие предупреждения засоряют вывод и раздражают меня. Лечится это довольно просто, например, привязкой режима utf8 к уже открытому файловому дескриптору в начале программы:

binmode(STDOUT,’:utf8′);

Но есть и более элегантное решение. Можно прописать в самом начале программы флаг, который скажет интерпретатору Perl открывать файловые декрипторы при запуске программы сразу в utf8, примерно так:

#!/usr/bin/perl -CS

И больше никаких манипуляций с binmode не потребуется