29 апреля, 2016
Ещё немного про SteelSeries engine в OS X
25 февраля, 2016
Ломающий Steelseries Engine Client 3.6.6 в MacOS X
Выйти-зайти, перезагрузиться и прочие стандартные шаманства не возымели эффекта, равно как и переустановка злополучной софтины с предварительным выпиливанием родным uninstaller'ом.
Как оказалось, uninstaller халтурит, и удаляет далеко не все продукты жизнедеятельности сносимого приложения.
В общем, исправить проблему можно так: даёте uninstaller'у сделать своё дело, затем переходите в ~/Library/Application Support и удаляете папку SteelSeries Engine 3 Client, затем заново устанавливаете SteelSeries Engine.
После этого всё начинает работать, а новую папку для себя оно вовсе с другим именем создает - steelseries-engine-3-client
30 сентября, 2015
Mikrotik WAN Failover и «повисающий» SIP
Не так давно довелось столкнуться с довольно тривиальной ситуацией, решений для которой в рунете сходу найти, к моему удивлению, не удалось. Ситуация: есть офис, раздачей интернетов в котором занимается роутер под управлением RouterOS. В офисе есть некоторое количество SIP-телефонов, а также резервный канал доступа в интернет на случай проблем с основным.
И вроде ничего не предвещало, как говорится, но вылез один очень неприятный момент: при переключении на резервный канал те самые SIP-телефоны напрочь отказывались заново устанавливать соединение с PBX (находящейся за пределами офиса), что заставляло обитателей того офиса вручную перезагружать каждый телефон, да еще и стараться побыстрее заметить, что телефоны отвалились, чтоб не пропустить какой-нибудь важный звонок.
В чем же дело? Всё довольно просто: переключение на резервный канал было реализовано с помощью двух маршрутов с destination 0.0.0.0/0 и разным значением distance в зависимости от приоритета, а также с настроенными соответствующим образом опциями check-gateway. Но переключение переключением, а вот таблицу NAT роутер при этом не очищал, т.к. его об этом никто и не просил, что приводило к «повисанию» UDP-соединений на том дефолте, который по несчастью отвалился.
Избежать подобной ситуации можно несколькими способами (мне попадались даже разного рода скриптовые ады, отключающие-включающие connection tracking, и прочие душераздирающие зрелища), но лично я решил сделать решение без ненужного скриптинга, максимально простое и лаконичное.
Итак, из руководства к RouterOS нам известно, что check-gateway проверяет доступность шлюза каждые 10 секунд, и если ответа на проверочный запрос не поступило в течение 10 секунд, то проверка считается неудачной. А после двух таких таймаутов подряд шлюз помечается как недоступный, тут-то и происходит переключение на резерв.
Для простоты будем считать, что период переключения каналов у нас равен 30 секундам. Тогда создадим netwatch, который будет пингать нашу телефонную станцию с интервалом в 15 секунд (половина от тех 30, чтоб наверняка). И да, разумеется наша телефонная станция должна в нормальной ситуации отвечать на пинг:
/tool netwatch add host=адрес_нашей_PBX interval=15s timeout=1s up-script="/ip firewall connection remove [find where dst-address~\"5060\"]" down-script="/ip firewall connection remove [find where dst-address~\"5060\"]"
Теперь, если вдруг у нас пропадет пинг до IP-АТС, из таблицы соединений будет вычищено всё, что шло на порт 5060. Но вообще я бы рекомендовал написать в up/down скрипт что-нибудь такое:
/ip firewall connection remove [find where src-address~"192.168.88."]
Под 192.168.88 подразумевается диапазон локальных офисных ip-адресов. Это сбросит все клиентские соединения (при этом не затронув те, что инициировал сам роутер, например L2TP-туннель до провайдера или еще что-нибудь), что в свою очередь сделает процесс переключения на резервный канал и обратно более «бесшовным» для пользователей, т.к. коннекты будут оборваны и пакеты точно не будут пытаться идти по умершему маршруту.
Не стоит беспокоиться насчет того, что такое решение может рвать соединения излишне часто: netwatch-скрипты выполняются по одному разу (единожды, когда пингуемый хост стал виден, и точно так же единожды, когда из виду пропал), а не циклично.
Данное решение было всячески оттестировано с пристрастием (и без), и никаких проблем выявлено не было.
14 июня, 2015
Еще одна возможная причина возникновения ошибок «Uncorrectable parity/CRC error» и борьба с ней
(ada2:ahcich2:0:0:0): WRITE_FPDMA_QUEUED. ACB: 61 00 f0 2f 9b 40 38 00 00 01 00 00
(ada2:ahcich2:0:0:0): CAM status: Uncorrectable parity/CRC error
(ada2:ahcich2:0:0:0): Retrying command
то это у вас либо диск умирает, либо питальник, либо шлейф от контроллера к диску сделан из дешевой китайской лапши. Однако, довелось столкнуться с ситуацией, когда на одном из двух абсолютно новых WD Purple у меня сразу полезло это безобразие, хотя диски явно были в порядке, шлейфы – тоже, а значения выходного напряжения у блока питания гуляли в пределах 0.03В, т.е. всё было вроде бы идеально, но ошибки продолжали сыпаться.После долгих поисков виновника всё-таки удалось отыскать. Им оказался spread spectrum, включенный в настройках биоса материнской платы. Стоило отключить эту опцию, и ошибки исчезли, а волосы мои стали мягкими и шелковистыми.
20 мая, 2015
«Два конца»
Интересная и не совсем тривиальная задача подвернулась. Ситуация: в некоторой организации локальная сеть имеет адрес, скажем, 192.168.0.0/24, и нужно пробросить некоторый порт (пусть будет tcp/8080) для кофеварки, адрес которой 192.168.0.50.
Казалось бы, что в этом такого? Так уж сложилось, что у провайдера, через которого мы получаем доступ в интернет по L2TP, адрес VPN-сервера тоже 192.168.0.50. Соответственно, сделать так, чтобы роутер подключался к VPN через сеть провайдера, у нас есть маршрут для 192.168.0.50/32, но если попытаться пробросить порт на этот адрес, пакеты закономерно пойдут на VPN-сервер провайдера, а не на нашу кофеварку, что нам совсем не нужно.
Что же делать?
Сначала создадим маршрут:
/ip route add dst-address=192.168.0.50/32 gateway=bridge-local routing_mark=coffee_mark
Обратите внимание на routing_mark.
Теперь создадим правило в mangle:
/ip firewall mangle add chain=prerouting in-interface=WAN protocol=tcp dst-port=8080 \
action=mark-routing new-routing-mark=coffee_mark
Ну и dst-nat правило, с ним ничего необычного:
/ip firewall nat add chain=dstnat in-interface=WAN protocol=tcp dst-port=8080 action=dst-nat to-addresses=192.168.0.50
Вот и все. Теперь соединениям, идущим на нашу кофеварку по указанному порту, будет присваиваться routing_mark, с помощью которого наш роутер поймет, где искать ту кофеварку.
07 апреля, 2015
Организация a/b тестирования веб-проектов средставами nginx
В этом посте я напишу, как реализовать подобное распределение пользователей по разным версиям проекта средставми nginx.
Определимся с условиями нашей задачи:
- На новую версию сервиса мы должны направить ≈20% всех пользователей
- Есть ip-адреса клиентов, которые должны всенепременно попадать на старую версию
- То же самое, но – всенепременно на новую.
geo $mytest_participant {
default 1;
10.1.1.1 0;
192.168.45.2 2;
}
map $mytest_participant $resulting_upstream_name {
0 "old_version_upstream";
1 "distributed_upstream";
2 "new_version_upstream";
}
upstream distributed_upstream {
ip_hash;
server 1.1.1.1 weight=8; # Old version server, 80% of clients
server 2.2.2.2; # New version server
}
upstream old_version_upstream {
server 1.1.1.1;
}
upstream new_version_upstream {
server 2.2.2.2;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://$resulting_upstream_name;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Итак, первый блок (geo) описывает как раз распределение пользователей по апстримам.
28 октября, 2014
Ubuntu - обновленные библиотеки libicu с последними изменениями временных зон
Наши разработчики используют Symfony2, и кое-где версия фреймворка ниже 2.6, а значит Symfony forms использует icu, и обновлять последний как-то мало кто торопится.
Поводом для написсания данного поста стал пост об этой же проблеме на хабре, но там рассматривалось решение проблемы для CentOS.
Мы используем преимущественно ubuntu, поэтому я сделал PPA с обновленными библиотеками (для 12.04 и 14.04).
Возьмем тестовый скрипт из той статьи на хабре и проверим на Ubuntu с «родным» icu:
<?php
$dateIn = '27.10.2014';
$tz = 'Europe/Moscow';
date_default_timezone_set($tz);
$intlDateFormatter = new \IntlDateFormatter('ru_RU', 2, -1, $tz, 1, 'dd.MM.yyyy');
$timestamp = $intlDateFormatter->parse($dateIn);
var_dump($intlDateFormatter->format($timestamp));
var_dump(date('d.m.Y', $timestamp));
И выполним его:php ./icutz.php
string(10) "27.10.2014"
string(10) "26.10.2014"
Всё плохо. Теперь подключим ppa и обновим библиотеку из него:
sudo add-apt-repository -y ppa:rzz/icu && sudo aptitude update
Обновляем libicuДля Ubuntu 12.04: sudo aptitude safe-upgrade libicu48
Для Ubuntu 14.04: sudo aptitude safe-upgrade libicu52
Снова запускаем наш скрипт:
php ./icutz.php
string(10) "27.10.2014"
string(10) "27.10.2014"
Готово! Но вообще, конечно, я рекомендую помимо всего прочего обновить версию Symfony, чтобы отвязаться от icu насовсем.
UPD, 12 Ноября 2014: в связи с поступившими просьбами сделать обновленный пакет icu 5.2 для 12.04, icu 4.8 переехал в отдельный PPA: ppa:rzz/icu48