15.06.2017

Восстановление базы MySQL из бинарных логов

Восстановление базы MySQL из бинарных логов
Простая статься на хабре, помогает быстренько восстановить утерянные insert в таблицы.

 

Восстановление базы данных из ib_logfile0

10.06.2017

SIPP Тестирование Asterisk

Решил провести тестирование Астериска на предмет максимального количества звонков.
Сразу скажу, у меня Астериск 1.4 и я просто посылаю на эхотест его, примеры эхотеста в астериска в sip.conf есть.

Чтобы провести тестирование нагрузки нам понадобится sipp

  1. yum install sipp
  2. копируем в локальный каталог сценарий с uac_pcap.xml из документации sipp
  3. копируем pcap файлы для астериск в каталог pcap текущей папки
  4. подбираем нужные параметры для sipp и должно работать

Здесь я опишу только 4 пункт:

в моем случае конфигурация рабочая выглядит так:

sipp -sf uac_pcap.xml -r 1 -mi 111.111.111.111 -i 111.111.111.111 -s 1005 222.222.222.222 -trace_msg -rtp_echo -d 5000

где
111.111.111.111 – внешний интерфейс вашей машины
222.222.222.222 – адрес астериска
1005 – номер для эхотеста
-d 5000 – пауза в 5 секунд (опционально)
и все погнали, в моей конфигурации сети, без особых проблем астериск успевает обслужить 50 вызовов в секунду и примерно 500 одновременных соединений, потом начинаются ретрансмиты сообщений.

9.06.2017

Memcached и ограничение соединений к нему

Столкнулся с тем, что клиенты получают ошибку вызванную тем что скрипты на сайте не могу подключиться к memcached

докопался до вот чего:

Огромное количество соединений к localhost остаются в состоянии time_wait в документации по memcached прекрасно сказано, что нужно проверить для увеличении производительности, а вот здесь был конкретный совет по поводу подвисших соединений:

Details of how to tune these variables are outside the scope of this document, but google for “Linux TCP network tuning TIME_WAIT” (or whatever OS you have) will usually give you good results. Look for the variables below and understand their meaning before tuning.

!THESE ARE EXAMPLES, NOT RECOMMENDED VALUES!
net.ipv4.ip_local_port_range = 16384 65534
net.ipv4.tcp_max_tw_buckets = 262144
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1

Я внес в систему только параметр net.ipv4.ip_local_port_range сделав его в два раза больше и дело пошло. Полезной оказалась статься про мониторинг memcached в частности утилита memcache-top и команда netstat которая показала кол-во еще ожидающих закрытия соединений.

9.06.2017

Автозапуск Debian 6 и Centos 6.8

Запуск программ при старте Debian:

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

Удаление скрипта из автозагрузки:

27.05.2017

О себе и реквизиты

Я рос хорошим мальчиком. Давным давно, работая в службе технической поддержки в небольшом интернет-провайдере, случилось так, что у моего коллеги не получилось настроить voip телефонию в компании и за дело взялся я. Это самая моя любимая работа разбираться в том, в чем я не разбираюсь. Если у меня появляется азарт в этом, то всё – ныряю с головой.

Так я начал работать с интернет-телефонией.

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

Но, немного расскажу про специфику… Во-первых, я не знаю почему, но мне в телефонии больше всего нравится разбираться и оптимизировать, чем создавать что-то большое и с нуля. Так получилось, что большая часть моей работы пока я был наемным рабочим состояла в том, чтобы разбираться с проблемами сети и телефонии. Поэтому, когда приходят клиенты не с тем, чтобы собрать что-то новое, а разобраться в проблемах или что-то оптимизировать – я прыгаю в это дело с радостью.

И вот я уже не хочу тратить много времени на статью про себя, просто скажу работаю на компанию ООО “ЮКСИ”.

Реквизиты:

ООО «ЮКСИ»

sip: 74952284411@did.yooxy.ru

fb: facebook.com/erewin

Юр. Адрес: 454021, ул Молодогвардейцев д.58 оф.1

Почтовый адрес: 454902, ул. Гостевая 3, оф. 002

ОГРН 1127447003386

ИНН/КПП 7447206406/744701001

Директор Еремин Павел Сергеевич, действует на основании Устава.

Расчетный счет № 40702810590000016075

в ОАО «ЧЕЛЯБИНВЕСТБАНК»

БИК 047501779 ИНН 7421000200 КПП 745301001

Кор/счет 30101810400000000779

27.05.2017

Куда я попал?

Добро пожаловать в обновленную версию записной книжки voip-инженера.

Давно начал вести записи по поводу решений разных задач области ip-телефонии. И несмотря на то, что задача это достаточно занудна, лично для меня конечно, часто ей пользовался. Моя работа связана как правила с разными задачами, от программирования до развертывания нескольких серверов для телефонии.

Что можно здесь найти, в первую очередь конечно меня, как консультанта, но и заметки по решениям разных задач. Вот список рубрик в которых приходилось решать те или иные задачи и решения которых, находятся на старом адресе http://opensips-blog.yooxy.ru

  • Asterisk
  • SQL запросы
  • Unix вопросы
  • Безопасность
  • Городские номера
  • Готовые решения
  • Идеи
  • Проблемы в коде
  • Проблемы при настройке
  • Спорт
  • Гитара

 

3.02.2016

Ограничение вызовов для exten

Ограничение одновременных вызовов в Астериске . Смысл прост: Ищем каналы по выражению “116-” а потом считаем кол-во элементов в массиве.

same => n,GotoIf($[“${FIELDQTY(CHANNELS(${CALLERID(num)}-), )}” > “1”]?busy-custom,s,1)

3.02.2016

Asterisk. Annoucement. Dialplan. ChannelRedirect. Elastix. Part 2.

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

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

Итак, для начала скрипт АМИ, которым осуществляется вызов:

Action: Login
Username: admin
Secret: werkjnfgopw

 

Action: Originate
ActionID: 12345
Channel: Local/117@tapi
Context: agent-custom
Exten: 12122396200
Priority: 1

Ранее смысл решения основывался на том, чтобы сохранить внутренний номер телефона, привязать к нему имя правильного канала (то куда позвонили) и собственно воспроизвести в этот канал файлик с названием “extension_x”.

Для реализации у нас в  файле extension_custom.conf:

Этот контекст ловит определенный номер формата #*00x  и записывает приветствие в файлик “extension_x”. Тут все просто.

[custom-record] ; Context for recording voice messages
exten => _#*00X,1,Noop(${EXTEN})
same => n,Set(CHANNEL(language)=ru)
same => “”n,Set(MONITOR_FILENAME=${DIR}${CALLERID(num)}_${EXTEN:4})
same”” => n,Playback(beep)
same => n,Answer
same => n,Record(${MONITOR_FILENAME}:wav)
same => n,Playback(vm-msgsaved)
same => n,Playback(${MONITOR_FILENAME})
same => n,Playback(vm-goodbye)

этот макрос выполняется когда мы совершаем вызов вручную в функцию Dial встроен код ‘M^(testsub)’ делалось это прям через веб инфтерфейс Эластикса.

[macro-testsub]
exten => s,1,NoOp(${CHANNEL})
exten => s,n,NoOp(${MYVAR})
exten => s,n,Set(DB(br/${MYVAR})=${CHANNEL})
exten => s,n,NoOp(${DB(br/${MYVAR})})

Этот контекст должен вызываться когда с ext приходит команда ##X что означает, что ext хочет воспроизвести приветствие.

[transfer-context]
exten => “” _##X,1,NoOp(${DB(br/${CALLERID(num)})})
exten”” => “”_##X,2,Set(DB(from_ext/last_ext)=${CALLERID(num)})
exten”” => “”_##X,3,ChannelRedirect(${DB(br/${CALLERID(num)})},play-context,${EXTEN},1)
exten”” => _##X,4,Playback(${DIR}${CALLERID(num)}_${EXTEN:-1}) ;
exten => _##X,5,Hangup()

А Это вспомогательный контекст, в него мы перескакием, когда собственно случается событие приоритета 3 в transfer-context. До сих пор не понятно, почему нельзя передать переменную через channelredirect – приходит ее сохранять в DB затем извлекать…

[play-context]
exten => _##X,1,noop(${DB(from_ext/last_ext)})
exten => _##X,2,Playback(${DIR}${DB(from_ext/last_ext)}_${EXTEN:-1}) ;
exten => _##X,3,Set(DB(from_ext/last_ext)=”0″)
exten => _##X,4,Hangup()

 

Итак, при вызове функции AMI Originate как я описал выше, вызывается два пользователя: внутренний 116 например и внешний внутренний вызывается в контексте [tapi]

[tapi]

exten => 116,1,Answer
exten => 116,n,SIPAddHeader(Alert-Info: Ring Answer)
exten => 116,n,NoOp(Context: agent)
exten => 116,n,Dial(SIP/116)
exten => 116,n,hangup

а затем вызывается контекст [agent-custom]: Это все делает тот AMI скрипт. В подчеркнутых строчках сохранение переменной какой внутренний номер позвонил и вызов макроса dialer-dial, который…

exten => _1XXXXXXXXXX,1,Answer

exten => _1XXXXXXXXXX,n,NoOp(Context: agent)
exten => _1XXXXXXXXXX,n,noop(CALLERID: “””${CALLERID(all)})
exten””” => _1XXXXXXXXXX,n,NoOp(EXTEN: ${EXTEN})
exten => _1XXXXXXXXXX,n,noop(SIP_to: ${SIP_HEADER(TO)})
exten => _1XXXXXXXXXX,n,noop(SIP_from: ${SIP_HEADER(FROM)})
exten => _1XXXXXXXXXX,n,Set(__FROM_EXT=${CHANNEL(name)})
exten => _1XXXXXXXXXX,n,Dial(SIP/t1/991${EXTEN},60,r^M(dialer-dial))
exten => _1XXXXXXXXXX,n,noop(DIALSTATUS= ${DIALSTATUS})
exten => _1XXXXXXXXXX,n,gotoif($[“${DIALSTATUS}”= “BUSY”]?busy-custom,s,1)
exten => _1XXXXXXXXXX,n,gotoif($[“${DIALSTATUS}”= “CONGESTION”]?congestion-custom,s,1)
exten => _1XXXXXXXXXX,n,gotoif($[“${DIALSTATUS}”= “CHANUNAVAIL”]?congestion-custom,s,1)
exten => _1XXXXXXXXXX,n,gotoif($[“${DIALSTATUS}”= “NOANSWER”]?congestion-custom,s,1)
exten => _1XXXXXXXXXX,n,hangup

 

который… сохранит для нас связку внутреннего номера и канала который мы вызываем  в базу Астериска.

[macro-dialer-dial]

exten => s,1,NoOp(${FROM_EXT:6:3})
exten => s,n,Set(MYVAR_A=${FROM_EXT:6:3})
exten => s,n,Set(DB(br/${MYVAR_A})=${CHANNEL})

26.12.2015

Asterisk. Annoucement. Dialplan. ChannelRedirect. Elastix.

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

Задача: Записать заранее приветствие в нескольких вариантах, и затем воспроизводить его абонентку по нажатию на кнопки быстрого набора.

Проблема: Быстрый набор – это просто очередной INVITE с заранее запрограммированным кодом, поэтому, для астериска это выглядит как поступление нового звонка.

Решение: Я решил эту задачу как для DTMF так и для использования speed-dial.

Ключ к решению: Основная проблема это заставить астериск воспроизводить заранее записанное приветствие нужному абоненту, если просто внести в dialplan запись вида ##1, где номер приветствия то астериск его проиграет тому кто прислал вызов, а нам нужно воспроизвести его абоненту, да еще и в терминологии Asterisk в другой канал.

Коротенько: Записывать приветствия мы будем формата XXXX_N.wav , XXXX- номер эксентшина который записывает приветствие, а N – это номер самого приветствия, таким образом мы можем записывать несколько приветствий для одного экстеншина.

[custom-record] ; Context for recording voice messages
exten => _#*00X,1,Noop(${EXTEN})
same => n,Set(CHANNEL(language)=ru)
same => “”n,Set(MONITOR_FILENAME=${DIR}${CALLERID(num)}_${EXTEN:4})
same”” => n,Playback(beep)
same => n,Answer
same => n,Record(${MONITOR_FILENAME}:wav)
same => n,Playback(vm-msgsaved)
same => n,Playback(${MONITOR_FILENAME})
same => n,Playback(vm-goodbye)

Воспроизведение:  При звонке мы сохраняем данные кто звонил и имя канала куда позвонили   : ${CALLEDRID(num)} – ${CHANNEL}, Делать это нужно в время команды Dial поэтому используется pre_dial_handler, для Эластикс это просто Опции в разделе General Setting. Tt – дает возмоножсть пользоваться DTMF, а ^M(testsub) выполняет макрос testsub.

[macro-testsub]
exten => s,1,NoOp(${CHANNEL})
exten => s,n,NoOp(${MYVAR})
exten => s,n,Set(DB(br/${MYVAR})=${CHANNEL})
exten => s,n,NoOp(${DB(br/${MYVAR})})

Чтобы запомнить переменную кто звонил мы добавляем строчку “exten => s,n,Set(__MYVAR=${CALLERID(number)})”  в macro-user-callerid и отправляем этот макрос в файл extensions_override_elastix Это означает, что Эластикс будет читать его их этого файла, чтобы не случилось в конфигурации. __ – означает что эта переменная будем передана вновь создаваемому каналу командой Dial.

И теперь при получении кода ##N от пользователя мы просто смотрим есть такая переменная в DB Астериска, если есть, то переводим сохраненный ранее канал в место где начинается воспроизведение.

[transfer-context]
exten => “”_##X,1,NoOp(${DB(br/${CALLERID(num)})})
exten”” => “”_##X,2,ChannelRedirect(${DB(br/${CALLERID(num)})},transfer-context,${EXTEN},3)
exten”” => _##X,3,Playback(${DIR}${MYVAR}_${EXTEN:-1}) ;
exten => _##X,4,Hangup()

Таким образом никаких скриптов, все гибко, красиво, изящно.

Бай.

 

PS: http://asteriskfaqs.org/2010/09/09/asterisk-users/set-channel-variable-from-within-other-channel.html

PS: https://wiki.asterisk.org/wiki/display/AST/Function_DB

 

 

 

 

16.08.2015

SOX. WAV. ASTERISK. BATCH. Конвертнуть файлы для астериска.

Привет!

Дали wavки для заливки на астериск, если честно понятия не имею что там и как устроено в астере, но Астериск сам предлоагает сервис для конвертации WAV файлов во все нужные ему форматы. при помощи CLI “file convert”.

1. WAV нужно преобразовать в 8000 Khz и 1 канал, делается это командой: “sox input.wav -c 1 -b 8000 outout.wav”

лично я не смог потратить время с делать одной командой конвертацию файлов в каталоге поэтому поступил тупейшим образом: ls -a *.wav

скопировал результат в файлик, там произвел замену при помощи регулярных выражений например из строчки: 1.wav я получил

sox  1.wav -r 8000 -c 1 new/1.wav

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

2.далее я создаю файлик с командами типа ” asterisk -x “file convert    transfering.wav           res/transfering.g729”

и все, в каталоге res получаются файлики с нужными кодеками. Астериск сам понимает в какой кодек надо перекинуть файл, если вы указывается расширение. В моем случае это g729.

Кодеки должны присутствовать и быть активными конечно.

Бай.