среда, мая 28, 2014

perl 5.20

Сегодня релизнулся. В perlbrew себе собрал, играюсь.
На ЛОР новость ожидаемо вызвала срач адептов, неосилянтов и простомимопроходящих ))

суббота, апреля 19, 2014

*sh: перевод списка пакетов из стобца в строку

Иногда требуется удалить и вычистить определённый список пакетов, притом, хочется получить и список пакетов по-быстрому и без лишних тыканий мышкой. Например, потребовалось удалить все пакеты, относящиеся к libreoffice. Если делать долго, то сначала надо получить список пакетов командой
dpkg -l | grep libreoffice
потом вручную из списка выбрать пакеты и вставить их в команду удаления. Но есть способ ускорить эту операцию переведя список пакетов, относящихся к libreoffice(или к нужному вам пакету) из столбца в строку воспользовавшись командой
dpkg -l | grep libreoffice | awk '{print $2}' | tr '\n' ' '
данная команда переведёт список пакетов из столбца в строку, которую затем можно вставить в команду aptitude purge

вторник, декабря 10, 2013

Git-шпаргалка


1. Переключиться на удалённую ветку минуя master:
1.1. Для начала обновим список веток на удалённом сервере:
git remote update origin --prune
1.2. Затем переключимся на ветку
git checkout --track origin/<имя ветки>
или для старых версий Git
git checkout -b <имя ветки> origin/<имя ветки>
или так
git checkout master
git pull
git checkout <имя ветки>

2. Убрать файл/папку из индексации
git rm -r --cached FILE
git commit -m "delete file from index"
git push origin master
3. Посмотреть файл командой blame до указанного коммита
git blame commitID~1 filename
4. Удалить ветку на сервере
git push -d origin [имя ветки]
5. Посмотреть историю между коммитами
git log --oneline commitID1..commitID2

вторник, мая 07, 2013

Gnome shell

После очередного обновления дебьяна на ноуте перестал запускаться gdm3. Вместо стартового окна наблюдаю картинку о том, что произошла ошибка. Ну да ладно, мы не пальцем деланные - переключился в консоль, погасил gdm3, стартанул иксы через startx.
Вместо привычного fallback-режима запустился стандартный Gnome Shell. После некоторого времени плевания и матюгов вдруг ощутил, что пользоваться им можно и даже с удовольствием. Да, непривычно устроено расположение элементов, до тех, что раньше запускались с одного щелчка, приходится щёлкать дополнительные разы. Но к этому привыкаешь.
Поставил себе несколько расширений с сайта https://extensions.gnome.org и моё рабочее окружение заиграло новыми красками)
Само оформление мне очень нравится, всё такое плавное и изящное, выглядит гораздо удобнее, нежели compiz в своё время.
В общем, для себя решил, что даже когда починят баг с gdm, на fallback-режим уже не вернусь. Надо идти в ногу со временем)

четверг, апреля 18, 2013

Perl. Сортировка ключей хеш-массива по значениям этих ключей



В процессе выполнения тестовых заданий для новой работы столкнулся с задачей вывода сортированных данных.
Итак, имеем структуру:
$VAR1 = bless( {
                 'DOMAINS' => {
                                'yandex.ru' => 1,
                                'INVALID' => 5,
                                'rambler.ru' => 1,
                                'vk.com' => 1,
                                'mail.ru' => 2
                              }, 
               }, 'MyModule' );
необходимо выводить данные хеш-массива DOMAINS, отсортированные по значениям(values) данного массива.
Недолго думая обратился за ответом к замечательной книге Perl: изучаем глубже, в которой было найдено решение:
foreach my $domain (sort { $self->{DOMAINS}->{$b} cmp $self->{DOMAINS}->{$a} } 
                keys $self->{DOMAINS}) {
        print $domain . "\t" . $self->{DOMAINS}->{$domain} . "\n";
    }
В результате получаем то, что требовалось:
INVALID 5
mail.ru 2
yandex.ru 1
rambler.ru 1
vk.com 1

Perl. Перехват warn'ов и carp'ов



Сейчас немного про перл.
В перле есть замечательная функция eval, которая умеет перехватывать критические ошибки, которые были вызваны die и/или croak. Но эта функция не умеет работать с предупреждениями, которые генерируются с помощью функций warn и carp. Ну и что такого, спросите вы, предупреждения для того и существуют, чтобы информировать пользователя/разработчика о некорректной работе скрипта или модуля. Но порой всё-же требуется, чтобы наш скрипт, написанный на перле, умел перехватывать подобные сообщения, сгенерированные модулями или функциями, чтобы, например, обрабатывать подобные сообщения особым образом.

Отображение киррилицы(cp1251/win1251) в Sublime Text 2


Файлы в редакторе Sublime Text 2 по умолчанию открываются в кодировке UTF8, но иногда требуется работать с файлами, которые были созданы в кодировке cp1251(кодировка, используемая по умолчанию в операционных системах семейства Windows).
Для этих целей вы можете переназначить fallback-кодировку, которую будет использовать сублим текст, если файл не в кодировке UTF8.
Для этой цели откройте меню Preferences -> Settings - Default. В открывшемся окне воспользуйтесь поиском(ctrl-f), найдите строку
"fallback_encoding": "Western (Windows 1252)",
и замените её на
"fallback_encoding": "Cyrillic (Windows 1251)", (запятая в конце строки обязательна!).
Сохраните файл. Отлично! Теперь сублим текст умеет открывать файлы в кодировке cp1251 корректно и ваша жизнь станет чуточку проще)

воскресенье, апреля 14, 2013

Добавление в Sublime Text 2 горячих клавиш для работы с языком Perl


В повседневной работе использую этот замечательный редактор. Всем он хорош - подсветка синтаксиса, скорость работы, автоподстановка. Только сильно не хватало мне горячих клавиш для проверки синтаксиса и запуска скрипта на perl. Sublime Text 2 позволяет в данном случае забиндить на стандартную комбинацию(ctrl-b) только одно действие.
После недолгого гугления было найдено решение, написанное для языка Go и без проблем адаптированное для Perl.
Для начала необходимо создать свой плагин. Для этого открываете Tool->New Plugin. Вводите следующий код:
import sublime, sublime_plugin 
   
class RunBuildCommand(sublime_plugin.WindowCommand): 
    def run(self, build_system): 
        self.window.run_command( "set_build_system", {"file": build_system } )
        self.window.run_command( "build" )

Сохраняете данный плагин под именем RunBuild.py
После этого в папке ~/.config/sublime-text-2/Packages/User создаёте два файла следующего содержания:
~/.config/sublime-text-2/Packages/User/Perl-build.sublime-build :
{
    "cmd": ["/usr/bin/perl", "$file"],
    "file_regex": ".* at (.) line ([0-9])",
    "selector": "source.perl"
}

~/.config/sublime-text-2/Packages/User/Perl-check.sublime-build :
{
    "cmd": ["/usr/bin/perl", "-c", "$file"],
    "file_regex": ".* at (.) line ([0-9])",
    "selector": "source.perl"
}

После этого открываете Preferences->Key Binding - User и добавляете следующие строчки:
[
    {
        "keys": ["alt+c"],
        "command": "run_build",
        "args": {
                "build_system": "Packages/User/Perl-check.sublime-build"
        }
    },
    {
        "keys": ["alt+b"],
        "command": "run_build",
        "args": {
                "build_system": "Packages/User/Perl-build.sublime-build"
        }
    }
]
После этого у вас на комбинациях alt-c и alt-b появляются проверка синтаксиса и выполнение скрипта соответственно.

среда, апреля 10, 2013

Меняю направление деятельности


Решил поменять сферу деятельности, переквалифицироваться в программиста.
Если честно, давно уже думал соскочить с админства, т.к. всё это обслуживание телефонного парка порядком приелось, хочется чего-то нового.
Сегодня(уже вчера, получается) было небольшое собеседование по телефону. Отныне буду перловым разработчиком в одной крупной компании. Для того, чтобы меня окончательно взяли на работу необходимо выполнить 2 тестовых задания. Одно уже сделал, со вторым разбираюсь, курю мануалы по фреймворку catalyst. Но с телефонией я не прощаюсь, хочу лишь подойти к ней с другой стороны, с позиции разработчика. Для этого сейчас активно прокачиваю свои навыки в программировании, в частности, читаю умные книги по C/C++. В общем, посмотрим, что будет дальше. Удачи мне.

понедельник, апреля 08, 2013

Проблема с работой Mantis после обновления Postgresql


Столкнулся на работе с такой неприятностью - после обновления СУБД Postgresql с версии 8.4 до версии 9.1 перестали подгружаться прикреплённые файлы в тикетах мантиса. После того, как спала паника начался судорожный поиск решения проблемы. Был даже запилен трабл-тикет на багтрекере мантиса. Но в итоге всё оказалось проще.
В 9-й версии поменяли формат вывода данных типа bytea. Для того, чтобы решить проблему потребовалось ввести в базе мантиса следующий запрос:
ALTER DATABASE bugtracker SET bytea_output='escape'
Данный запрос устанавливает формат вывода bytea таким же, какой был в версии 8.4. После проделанной процедуры всё успешно заработало.

четверг, июня 14, 2012

K&R Язык программирования C. Упражнение 1.19. Напишите функцию reverse(s), которая переписывает свой строковый аргумент в обратном порядке

Занялся на досуге изучением языка си по книжке K&R. Дошёл до задания 1.19. По итогу выполнения решил написать данное сообщение, как памятку себе. Итак, программа выглядит следующим образом:
/* программа, реверсирующая входные строки */
#include <stdio.h>
#define MAXLINE 1000

void reverse(char s[]);
int my_getline(char s[], int);

int main()
{
    int len;
    char line[MAXLINE];

    while((len = my_getline(line, MAXLINE)) > 0) {
        printf("Исходная строка выглядит так: %s", line);
        reverse(line);
        printf("Реверсированная строка выглядит так: %s", line);
    }
    return 0;
}

int my_getline(char s[], int lim)
{
    int i, c;

    for(i = 0; i < lim -1 && (c = getchar()) != EOF && c != '\n'; ++i) {
        s[i] = c;
    }
    if(c == '\n') {
        s[i] = c;
        ++i;
    }
    s[i] = '\0';
    return i;
}

/* функция reverse: переписывает строки в обратном порядке. Суть работы в следующем:
 т.к. мы знаем, что любая строка заканчивается символом '\0', можно на время удалить
 из строки данный символ и занять его место первым элементом массива. После этого можно
 осуществить последовательный перенос всех элементов. В последствии необходимо будет
 "сдвинуть" полученную строку влево */
void reverse(char s[])
{
    int n, i, c, j;

    c = n = 0;
    while(s[n] != '\0') {
        ++n;
    }
    if(s[n-1] == '\n') {
        c = s[n-1]; //c теперь содержит символ перехода на новую строку
        n = n - 2; //не будем подставлять в качестве первого символа переход на новую строку
    }
    /* выясняем, какое у нас число символов в строке: чётное или нечётное */
    if((n%2) == 0) {
        j = n/2;
    } else {
        j = n/2 + 1;
    }
    /* переносим крайние элементы в массиве */
    s[n+1] = s[0];
    s[0] = s[n];
    /* переносим остальные элементы */
    for(i = 0; i < j; ++i) {
        s[i] = s[n-i];
        s[n-i] = s[i+1];
    }
    /* нужно "сдвинуть" символы влево, начиная с середины */
    for(i = j; i < n + 1; ++i) {
        s[i] = s[i+1];
    }
    if(c == '\n') {
        n = n + 1;
        s[n] = '\n';
    }
    s[n+1] = '\0';
}

понедельник, мая 14, 2012

Генерация ложных гудков в трубку после перевода звонка в отвеченное состояние


Настраивал недавно одному клиенту Asterisk. До этого у них стоял тоже астериск, который был настроен каким то "умельцем" - настолько запутанного диалплана я, наверное, не видел ни разу за свою шестилетнюю практику работы. Но пост не об этом. В общем, переводили мы клиента с "их" астериска на "наш" астериск. Вроде бы всё перенесли и система удачно запустилась, но возник один нюанс - у клиента есть 2 GSM-модема, подключенных к FXO-портам шлюзов Linksys SPA3102. И через эти модемы осуществляются звонки на Московские мобильные. На старой системе, при звонке через модемы, в трубку абоненту генерился ложный гудок до тех пор, пока не начинал генерироваться настоящий гудок вызываемой стороной. Ничего сложного, подумал я - поставим опцию r и дело с концом. Но всё оказалось несколько сложнее.Оказывается, при звонке на порт FXO линксис, GSM-модем, подключенный к этому порту сразу же переводил канал в отвеченное состояние и давал в трубку тишину в течение ~20 секунд до тех пор, пока не начинала "гудеть" вызываемая сторона. Скажу честно, с такой проблемой я столкнулся впервые, а клиент говорил, что на старой системе всё работало.
После нескольких дней курения диалпланов предыдущей системы и мануалов в интернете я был в тупике, но, к счастью, интуиция и опыт подсказали ответ - опция G в команде Dial. В описании этой опции говорится:
G(context^exten^pri): If the call is answered, transfer both parties to the specified context and extension. The calling party is transferred to priority x, and the called party to priority x+1. This allows the dialplan to distinguish between the calling and called legs of the call (new in v1.2). You cannot use any options that would affect the post-answer state if this option is used.
что в примерном переводе на русский язык означает следующее:
Если вызов отвечен, он переводится на специальный контекст и указанный экстеншен. Притом, звонящий канал будет переведён на приоритет x, а вызываемый канал на приоритет x+1
В итоге, был составлен "специфичный" контекст следующего содержания:
[custom-test-out-ring]
exten => s,1,Goto(chan_a)
exten => s,n,Goto(chan_b)
exten => s,n(chan_a),Ringing()
exten => s,n,Wait(20)
exten => s,n,Bridge(${DIALEDPEERNAME})
exten => s,n,Hangup()
exten => s,n(chan_b),Wait(50)
exten => s,n,Hangup()
Вызов данного контексте осуществляется следующим образом:

exten => _8XXXXXXXXXX,n,Dial(SIP/linksys/${EXTEN},3,tTG(custom-test-out-ring^s^1))

В итоге, когда осуществляется вызов на указанное направление, при ответе на вызов звонок перекидывается в контекст custom-test-out-ring, в котором звонящий канал переводится на именованный приоритет chan_a, а вызываемый канала - на chan_b. Опытным путём была измерена задержка, которую даёт модем перед тем, как начинает посылать сигналы вызова в трубку и, соответствующее значение было установлено в команду Wait для канала А. Вот таким бесхитростным, вобщем то способом, была решена довольно нетривиальная задача.

воскресенье, июля 11, 2010

Приём/отправка факсов в asetrisk с помощью Hylafax

Встала задача - настроить приём и отправку факсов через астериск. Была выбрана связка iaxmodem + hylafax. Причина такого выбора банальна: в ветке 1.4 астериска нет встроенного аппликейшена для приёма/отправка факсов. С rxfax/ReceiveFax заморачиваться не хотелось.
Итак, имеем сервер с Debian Lenny, asterisk-1.4.33.1 + freepbx-2.7. Ставим доп пакеты:
ip-pbx:~# aptitude install g++ libtiff-tools libtiff4 libtiff4-dev dpkg-dev
Заводим iax-абонентов на астериске, в моём случае это были номера 8001-8007. Не забываем также в конфиге iax_general_custom.conf указать calltokenoptional=<ваша подсеть>. Далее, качаем и ставим iaxmodem:
ip-pbx:~# cd /usr/src
ip-pbx:/usr/src# wget http://sourceforge.net/projects/iaxmodem/files/iaxmodem/iaxmodem-1.2.0/iaxmodem-1.2.0.tar.gz/download
ip-pbx:/usr/src# tar xzvf iaxmodem-1.2.0.tar.gz
ip-pbx:/usr/src# cd iaxmodem-1.2.0
ip-pbx:/usr/src/iaxmodem-1.2.0# ./configure && make
ip-pbx:/usr/src/iaxmodem-1.2.0# cp iaxmodem /usr/local/bin
ip-pbx:/usr/src/iaxmodem-1.2.0# mkdir /etc/iaxmodem

Здесь пропишу настройки для одного иаксмодема, остальные заводятся аналогично:
ip-pbx:/usr/src/iaxmodem-1.2.0# touch /etc/iaxmodem/ttyIAX0
ip-pbx:/usr/src/iaxmodem-1.2.0# echo "iax1:2345:respawn:/usr/local/bin/iaxmodem ttyIAX0" >> /etc/inittab
ip-pbx:/usr/src/iaxmodem-1.2.0# cd /etc/iaxmodem

Далее, прописываем в ttyIAX0 параметры для модема:
ip-pbx:/etc/iaxmodem# vim ttyIAX0

device /dev/ttyIAX0
owner uucp:uucp
mode 660
port 4570
refresh 50
server [ip астериска]
peername [peername]
secret [secret]
codec alaw


Здесь, [ip астериска] - айпишник, на котором стоит астериск, [peername] - имя иакспира, которого мы завели на астериске, [secret] - это, соответственно, пароль для авторизации этого пира.
Ставим и настраиваем hylafax:
ip-pbx:/etc/iaxmodem# cd /usr/src
ip-pbx:/usr/src# wget ftp://ftp.hylafax.org/source/hylafax-6.0.4.tar.gz
ip-pbx:/usr/src# tar xzvf hylafax-6.0.4.tar.gz
ip-pbx:/usr/src# cd hylafax-6.0.4
ip-pbx:/usr/src/hylafax-6.0.4# dpkg-buildpackage
ip-pbx:/usr/src/hylafax-6.0.4# dpkg -i ../hylafax*deb

ip-pbx:/usr/src/hylafax-6.0.4# faxsetup

[...]

Update /var/spool/hylafax/status/any.info.

HylaFAX configuration parameters are:

[1] Init script starts faxq: yes
[2] Init script starts hfaxd yes
[3] Start old protocol: no
[4] Start paging protocol: no

Are these ok [yes]?

[...]

Do you want to run faxaddmodem to configure a modem [yes]?
Serial port that modem is connected to [ttyS0]? ttyIAX0

[...]


Далее, вам будет предложено ввести параметры модема. Тут можете прописать свои значения. Сетап создаст в папке /var/spool/hylafax/etc файл config.ttyIAX0. У меня он выглядит следующим образом:

CountryCode: 7
AreaCode: 495
FAXNumber: +7.495.555.1234
LongDistancePrefix: 1
InternationalPrefix: 011
DialStringRules: etc/dialrules
ServerTracing: 1
SessionTracing: 11
RecvFileMode: 0600
LogFileMode: 0600
DeviceMode: 0600
RingsBeforeAnswer: 1
SpeakerVolume: off
GettyArgs: "-h %l dx_%s"
LocalIdentifier: "NothingSetup"
TagLineFont: etc/lutRS18.pcf
ModemType: Class1
ModemResetCmds: AT+VCID=1
PagerTTYParity: none
Class1Cmd: AT+FCLASS=1.0 # command to enter class 1.0
Class1PPMWaitCmd: AT+FTS=7 # command to stop and wait before PPM
Class1TCFWaitCmd: AT+FTS=7 # command to stop and wait before TCF
Class1EOPWaitCmd: AT+FTS=9 # command to stop and wait before EOP
Class1SwitchingCmd: AT+FRS=7 # command to stop and listen for silence
Class1RecvAbortOK: 200 # wait 200ms for abort response
Class1FrameOverhead: 4 # 4 byte overhead in recvd HDLC frames
Class1RecvIdentTimer: 40000 # 35+5secs waiting for ident frames
Class1TCFMaxNonZero: 10 # max 10% of data may be non-zero
Class1TCFMinRun: 1000 # min run is 2/3rds of TCF duration
CallIDPattern: "NMBR="
CallIDPattern: "NAME="
CallIDPattern: "ANID="
CallIDPattern: "NDID="


Можно подправить данный файл. Далее, прописываем
ip-pbx:/usr/src/hylafax-6.0.4# echo "t0:2345:respawn:/usr/sbin/faxgetty ttyIAX0" >> /etc/inittab
ip-pbx:/usr/src/hylafax-6.0.4# vim /etc/rc.local, сюда добавляем строчки
/usr/local/sbin/hfaxd
/usr/local/sbin/faxq
, после этого ребутаем серв:
ip-pbx:/usr/src/hylafax-6.0.4# reboot

После загрузки сервера проверьте, что у вас нормально работают hylafax и iaxmodem:
команда ps aux | grep iax должна выдать что то похожее на
uucp 5288 0.0 0.0 3084 1312 pts/3 Ss+ Jul07 1:07 /usr/local/bin/iaxmodem ttyIAX0
а команда ps aux | grep fax должна выдать
uucp 5059 0.0 0.0 4372 1108 ? Ss Jul07 0:00 /usr/sbin/faxq
uucp 5063 0.0 0.0 4704 1536 ? S Jul07 0:00 /usr/sbin/hfaxd -d -i 4559
uucp 5295 0.0 0.0 4944 2196 ? Ss Jul07 0:21 /usr/sbin/faxgetty ttyIAX0

Если этого нет, то что то вы сделали не так. Если у вас показывает так же как и у меня, то всё нормально и можно двигаться дальше.

Отправка факсов

По умолчанию, во freepbx пиры сидят в контексте from-internal, меня это вполне устраивает, я ничего не меняю. Если вы хотите выпускать факсы через какой то отдельный транк, то прописшите это в отдельный контекст, который потом поставьте для iax-пира в настройках.
Отправка факсов совершается командой sendfax. У меня она имеет следующий вид:
sendfax -n -T 2 -N -d [номер назначения] [файл факса]
-n - не генерить титульную страницу
-T 2 - совершить 2 попытки отправить факс, прежде чем посчитать отправку неуспешной(по умолчанию будет совершено 12 попыток)
-N - не посылать на электронную почту уведомление об отправке факса
-d [номер назначения] - номер, на который посылать факс
Если у вас всё настроено правильно, то в консоли астериска вы увидите исходящий звонок от iax-пира на номер назначения. Проверить статус отправки можно командами faxstat -s и faxstat -d

Приём факсов
Для того, чтобы принять факс, необходимо направить вызов на iax-пира, под которым в астериске зареган iaxmodem:
exten => _XXXX.,1,Dial(IAX2/iaxmodem/${EXTEN},30,)
После чего факс будет принят hylafax'ом и будет складирован в папку /var/spool/hylafax/recvq. В данном методе существует одна маленькая неприятность - имя файла в /var/spool/hylafax/recvq никак не будет отражать информацию о том, кто послал данный факс. Но, к счастью, эту проблему довольно просто решить. В hylafax есть встроенный инструмент, под названием FaxDispatch. Данный инструмент позволяет получить информацию о вызове. В частности, получить CLID и DID, которые использваолись в вызове. CALLERID звонящего сохраняется в переменной $CIDNUMBER, номер, на который пришёл вызов - в переменной $CALLID4. Необходимо отредактировать файл /var/spool/hylafax/etc/FaxDispatch (если его не существует, то создайте). У меня он выглядит следующим образом:
FILETYPE=tif
FOLDER="/var/spool/hylafax/recvq/"
FULLPATH="${FOLDER}${FILENAME}.tif"
cp $FULLPATH /tmp/$CIDNUMBER\_$CALLID4.tif
chmod 777 /tmp/$CIDNUMBER\_$CALLID4.tif

Думаю, объяснять особо не нужно. Все тифы копируются в папку tmp, им присваивается имя $CIDNUMBER_$CALLID4. В конфиге астериска у меня прописано:

exten => _[124]XX,1,Set(FAXFROM=${CALLERID(num)})
exten => _[124]XX,n,Set(FAXEXTEN=${EXTEN})
exten => _[124]XX,n,Set(FAXMAIL=${FAX_GET(${EXTEN})})
exten => _[124]XX,n,Goto(fax)
exten => _XX.,n(fax),Dial(IAX2/8001/${EXTEN})
exten => h,1,DumpChan()
exten => h,n,System(/usr/bin/perl /space/scripts/fax_handler.pl ${FAXFROM} ${FAXEXTEN} ${FAXMAIL})

т.е. после того, как был принят факс, запускается перловый скрипт следующего содержания:
#!/usr/bin/perl -w

use strict;
use POSIX;

my $tiff2pdf = '/usr/bin/tiff2pdf';
my $rm = '/bin/rm';
my $mv = '/bin/mv';
my $peer = $ARGV[0];
my $user = $ARGV[1];
my $mail = $ARGV[2];
my ($sec,$min,$hour,$mday,$mon,$year,$wday)=localtime(time());
$mon += 1;
$year += 1900;
$mday = '0' . "$mday" if (length($mday) == 1);
$mon = '0' . "$mon" if (length($mon) == 1);
$sec = '0' . "$sec" if (length($sec) == 1);
$min = '0' . "$min" if (length($min) == 1);
$hour = '0' . "$hour" if (length($hour) == 1);
my $_file = "$peer" . '_' . "$user";
my $file = "$peer" . '_' . "$user" . '_' . "$year" . "$mon" . "$mday" . '_' . "$hour:$min:$sec";
my $date = "$year" . "$mon" . "$mday" . '_' . "$hour" . ':' . "$min" . ':' . "$sec";
chdir '/tmp';
exit unless (-e "$_file.tif");
system("$tiff2pdf -o $file.pdf $_file.tif");
system("$rm -f $_file.tif");
system("/usr/local/bin/sendEmail -f [from_mail] -t $mail -u FAX from $peer to $user -m fax received $date -a /tmp/$file.pdf -s [smtp-сервер] -xu [from_mail] -xp [mail_passwd]");
system("$mv $file.pdf /var/spool/asterisk/fax");

Данному скрипту передаются CLID, DID и мейл, на который нужно отсылать письмо с факсом. Скрипт по CLID и DID ищет в папке /tmp нужный файл, конвертит его в pdf пуляет на почту.

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

http://www.the-asterisk-book.com/unstable/faxserver-mit-iaxmodem-und-hylafax.html
http://lynks.ru/blog/articles/iaxmodem-hylafax-i-ldap

вторник, января 19, 2010

Новый день

К сожалению, из-за смены работы с zabbix'ом пришлось повременить. Сейчас другие заботы, не менее интересные. Всё так же продолжаю заниматься астериском, но уже с сильным уклоном в базы данных, конкретно в postgres.
Руководство на новой работе поставило задачу освоить freebsd, т.к. почти все сервера работают под управлением этой OS, да и сам технический директор с замом работают из под этой оси.
Занялся изучением, поставил себе qemu, хочу туда замостырить фряху. С ужасом и трепетом ожидаю встречи с нею))

среда, августа 19, 2009

Занялся изучением системы zabbix

По работе понадобилась мне данная приблуда для мониторинга серверов, качнул, скомпилил, запустил. Веб-морда красивая, но полезной информации не отображает. Вообщем, с наскоку не получилось, сижу курю мануалы. Жаль, что в универе плохо изучал англицкий язык, знание последнего мне бы сейчас очень пригодилось, т.к. почти вся полезная информация на буржуйском языке. Ну что ж, значит всё как всегда - зарываемся с головой в документацию и пытаемся разобраться что к чему. Как разберусь, накатаю мануал для таких же как я, новичков)

среда, июля 22, 2009

не обновлять пакет в aptitude

Это скорее, небольшая памятка для себя, чтобы не забыть. Итак, заходим в aptitude, выбираем пакет, который не нужно обновлять(в моём случае - это ядро, т.к. стоит самосборное), далее нажимаем кнопочку F и всё, в следующий раз, при safe-upgrade, aptitude "не увидит" обновлений для данного пакета.

вторник, апреля 28, 2009

HP LaserJet 1018 + Debian Etch в качестве сетевого принт сервера

На днях озаботился я на работе установкой принтера HP LaserJet 1018 в качестве сетевого принтера. Т.к. само устройство в силу своей бюджетности не имеет сетевого порта, то понадобился принт-сервер. Под эту задачу был выбран мой любимый Debian.
Итак, что мы имеем? А имеем мы древний компутер на целероне 1.7 МГц + 40 Гб HDD + 256 RAM. Как раз то, что нам нужно.
Данное руководство писалось путём проб и ошибок, которые были допущены мной во время казалось бы не такой сложной процедуры, как установка компьютера в качестве принт-сервера. Не уверен, что всё делал верно, но в итоге всё работает и работает стабильно. Буду рад, если данное руководство кому-нибудь поможет.

Итак, приступим.
В первую очередь качаем необходимые пакеты:
cd /usr/src
wget -O foo2zjs.tar.gz http://foo2zjs.rkkda.com/foo2zjs.tar.gz
wget http://mirror.cs.wisc.edu/pub/mirrors/ghost/GPL/gs862/ghostscript-8.62.tar.bz2
wget http://ftp.easysw.com/pub/cups/1.3.7/cups-1.3.7-source.tar.gz
- более поздние версии качать не рекомендую, т.к. с ними возникают проблемы.
Далее устанавливаем необходимые бинарники из репозитария:
aptitude update
aptitude install g++ openssl libssl0.9.8 libssl-dev ssl-cert foomatic-db foomatic-db-engine foomatic-filters libtiff4-dev libttf2 ttf-dejavu


Компилируем пакеты ghostscript и cups(Там всё стандартно в README и INTALL описано подробно). После этого ставим foo2zjs:
tar zxf foo2zjs.tar.gz
cd foo2zjs
make
./getweb 1018
make install && make install-hotplug && make cups

После этого делаем первый финт ушами:
cat /usr/share/foo2zjs/firmware/sihp1018.dl > /dev/usb/lp0

Далее правим конфиг cupsd.conf

print-server:~# nano -w /etc/cups/cupsd.conf

Listen localhost:631
Listen /var/run/cups/cups.sock
Listen [ip-адрес данного компьютера]

# Show shared printers on the local network.
Browsing On
BrowseOrder allow,deny
BrowseAllow all

Далее в секциях Location /, Location /admin и Location /admin/conf добавляем строчку Allow all. Можете в принципе и не открывать на полный доступ, дело ваше. Мой компьютер стоит в локальной сети, лишний на него не зайдёт.

делаем рестарт сервиса:
/etc/init.d/cups restart

После чего заходим по http на ip-адрес вашего принт-сервера по порту 631
http://[ip-адрес]:631

Должно появиться стандартное окно Cups, в нём выбираем "add printer" и далее следуем инструкциям. Во время данной процедуры капс запросит вас указать из списка драйвер для принтера. И вот тут вылазит второй финт. Почему то в данном списке моего принтера не было и я сделал проще - качнул пакет foo2zjs.tar.gz на свой виндовый комп, разархивировал его и из папки foo2zjs.tar\foo2zjs\foo2zjs\PPD\ вручную выбрал драйвер для моего принтера. Принтер установился без проблем.
После того, как добавили принтер, идём в закладку "Printers" и наблюдаем там наш принтер. Нажимаем "Print test page" и любуемся тестовой страницей. Если вдруг капс ругнётся на foomatic rip, то нужно найти данный файл(у меня он был в папке /usr/bin/) и скопировать в /cups/filter/ :
cp /usr/bin/foomatic-rip /usr/lib/cups/filter/

После этого всё должно работать.
Далее на виндовом компе настраиваем подключение к принтеру. Качаем с сайта hp драйвер: ftp://ftp.hp.com/pub/softlib/software10/COL22196/bi-58438-2/lj1018-HB-pd-win32-ru.exe , устанавливаем его и в папке принтеры и факсы добавляем принтер. Мой принтер выглядит следующим образом:
http://10.15.1.198:631/printers/HP_LaserJet_1018
у вас будет что то похожее. После этого можно печатать. Наш принт-сервер работает уже полторы недели и как говорится, не жужжит))

суббота, марта 28, 2009

Debian Lenny

Недавно установил себе сей дистрибутив. Пришлось сразу повозиться с сетевушкой и звуковой картой, но в итоге всё заработало как надо. Поставил систему, собрал ядро. Скорость работы на глаз выше чем в Windows XP раза в полтора. Всё работает как надо, даже странно. Помниться, в Этч наблюдались перебои со стабильность систему(хотя, скорее всего, дело было в руках). Поставил виртуальную машину Qemu, планирую заняться изучением Kamailio(бывший Openser), т.к. по работе в скором времени может пригодится. Ну и вообще погонять различные сервисы ради интереса.

Asterisk + SCCP

Итак, техническая тематика. Сегодня я хочу написать про Asterisk в связке с протоколом SCCP. Настраивая телефон под данный протокол, я нашёл много полезной информации, но порой большая её часть сводится к первоначальной установке и настройке протокола и Asterisk, я же постараюсь обобщить полученные знания и поделиться опытом, полученным мною при изысканиях.
Итак, что мы имеем? В наличии аппарат Cisco 7960 + консоль к нему 7914, система Centos - 4.5, Asterisk - 1.2.26.1 из репозитария (Trixbox) , версия прошивки SCCP для телефона - P00308000800, версия протокола для Asterisk - 20071213.
Для начала перепрошиваем телефон на SCCP, для этого в вашей сети должен быть поднят tftp-сервер. Забрасываете на него прошивку для телефона и создаёте там же файлы
xmlDefault.CNF.XML SEP[mac-адрес].cnf.xml .
Мой SEP[mac-адрес].cnf.xml :



и xmlDefault.CNF.XML:


Этих файлов должно хватить для того, чтобы телефон поднялся и начал работать.
После этого, нужно установить поддержку протокола SCCP на Asterisk. Берём последний chan-sccp с sourceforge.net:
cd /usr/src
wget http://downloads.sourceforge.net/chan-sccp-b/chan_sccp_20090110.tar.gz?use_mirror=heanet

Доставляем в систему пакеты asterisk-devel и spandsp-devel:
yum install asterisk-devel spandsp-devel

Устанавливаем chan-sccp в систему. Описывать сам процесс не буду, сложного там ничего нету.
После того, как установили модуль, идём в директорию /etc/asterisk, создаём там конфиг sccp.conf примерно следующего содержания:

[general]
keepalive = 10 ;IMPORTANT: 5secs. lead to trouble with 7960
context = custom-test
dateFormat = D.M.YA ; M-D-Y in any order (5 chars max)
bindaddr = 10.15.1.150 ; replace with the ip address of the asterisk server
port = 2000 ; listen on port 2000 (Skinny, default)
debug = 4
accountcode=skinny ; accountcode to ease billing
callwaiting_tone = 0x2d ; sets to 0 to disable the callwaiting tone
language=ru ; Default language setting this setting also sets the voicemailbox language
echocancel = on ; sets the phone echocancel for all devices
silencesuppression = off ; sets the silence suppression for all devices
callgroup= 1
pickupgroup= 1
cfwdall = off ; activate the callforward ALL stuff and softkeys
cfwdbusy = off ; activate the callforward BUSY stuff and softkeys
private = on ; permit the private function softkey
dnd = reject ; turn on the dnd softkey for all devices. Valid values are "off", "on" (busy s$
mwioncall = off
mwilamp = off
firstdigittimeout = 8 ; dialing timeout for the 1st digit
digittimeout = 5 ; more digits
digittimeoutchat = #
disallow = all
allow = alaw
allow = ulaw


[devices]
type = 7960
description = test
tzoffset = 0
autologin = 220
imageversion=P00308010100
device => SEP000F8FFBA358

[lines]
id = 220 ; future use
pin = 1234 ; future use
label = 220 ; button line label (7960, 7970, 7940, 7920)
description = A. Ruzhnikov ; top diplay description
context = custom-test
callwaiting = 1
incominglimit = 2 ; more than 1 incoming call = call waiting
mailbox = 220 ; voicemail.conf (syntax: vmbox@context:folder)
vmnum = *97 ; speeddial for voicemail administration, just a number to dial
cid_name = Aleksandr Ruzhnikov ; caller id name
cid_num = 220
line => 220

После этого в modules.conf добавляем

noload => chan_skinny.so

Перезагружаем астериск и радуемся своим успехам))

понедельник, марта 10, 2008

первый пост

Вообще, я с опаской отношусь к соц. сетям, чувство параноика во мне сильно. Но всё же решил завести данный блог, в который собираюсь записывать чисто технические моменты моей жизни и работы, а так как моя работа тесно связана с Linux, Asterisk и всем опенсорсным и телефонным, то заметок, думаю, наберётся немало