Posts Tagged ‘bsd’

Мониторинг качеството на нета

Wednesday, March 11th, 2009

Терминът “качество на нета” по-скоро е взет от някой тинейджърски журнал, но уцелва точно нуждите на крайния клиент. Аз като клиент на моя ISP се нуждая от две неща - ниска (по възможност - никаква) загуба на пакети и ниско (по възможност - никакво) забавяне на пакетите. Това трябва да ми се поднесе разбираемо, с картинка.
Нужен софтуер:

  • RRDtool - има страхотни възможности за представяне на числова информация. За примерни графики вижте галерията им.
  • ping - резултата от изпълнението на ping съдържа всичко необходимо за изграждане на статистиката ни - Round trip time и Packet loss
  • Perl - или друг удобен ви език. Трябва ви за парсване на изхода от ping
  • crontab - искаме статистиката да се събира през определен интервал от време

Системата може да бъде разделена на две части: част за събиране на статистика и част за графично представяне на данните.
Събиране на статистика
На всеки 5 минути ще се пуска ping до няколко избрани хоста в различни зони на пиъринга. Естествено върнатите резултати ще са субективни, защото зависят от параметрите на отсрещната точка. Все пак цялото задание “качество на нета” е субективно, така че да продължаваме :) Избрал съм единия хост да бъде шлюза на доставчика ми, втория хост да бъде dir.bg (тест на bg пиъринга) и третия хост да бъде ivanatora.info (за тест на международната свързаност).
Логът се изгражда от следния скрипт:
/home/ivanatora/perl_razni/ping_stats.pl


#!/usr/bin/perl
$target = $ARGV[0]; # тук ще идва адреса на целта
$db = $ARGV[1]; # тук ще идва в коя база ще се записва
$dump = "/home/ivanatora/stats_ping/$target.log"; # лога с крайните резултати
$rrd_path = "/home/ivanatora/rrd/temps/pings"; # директорията с RRD базите
open (FH, ">>", $dump) or die "$!";
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$mon++;
$year += 1900;
$time = sprintf("%02d/%02d/%4d %02d:%02d:%02d", $mday, $mon, $year, $hour, $min, $sec);
$output = `/bin/ping -q -c100 -w100 $target`; # пуска ping със 100 пакета и чака максимално 100 секунди за изпълнението на командата

if ($output =~ /(d+?)% packet loss/){
        $loss = $1;
        $percent = sprintf("%3d", $1);
}
if ($output =~ /rtt min/avg/max/mdev = .+?/(.+?)//){
        $avg = $1;
        print FH "$time : $percent% loss to $target Average: $1 msn";
        # update RRD
        $ts = time;
        $mod = $ts % 300;
        $ts -= $mod;
        $avg =~ /^(.+?)./;
        $rtt = $1;
        `/home/ivanatora/rrd/bin/rrdtool update $rrd_path/$db.rrd $ts:$loss:$rtt`; # командата за ъпдейт на базата; TODO: да направя пътя до изпълнимия файл на rrdtool в променлива
}
close (FH);

Малко изпреварвам времето, защото още не сме създали RRD базите. Каква е идеята на RRD? Round Robin Database е способ за запазване на постоянно изменяща се информация във времето, като всяка промяна се регистрира в цикличен буфер. Ако имаме един буфер със 12 слота и ъпдейтваме базата през 5 минути, във всеки момент ще имаме данните от предния час. Какво става с по-старите данни - губят ли се? Да. Ако ни трябват ще направим още един буфер, който ще се ъпдейтва на всяко цялостно извъртане на часовия буфер - ще взима средната стойност на всички измервания и ще го записва в един негов слот. Така ако този буфер има 24 слота ще имаме статистика на средната часова стойност на измерванията. Може да имате колкото си искате вторични буфери и всички се съхраняват в една и съща база и се ъпдейтват автоматично. Освен това в един буфер може да пазите стойностите на няколко променливи. Предимствата на RRD е че всяка промяна се регистрира, като размера на базата не нараства линейно във времето.
До тук вероятно имаме лог с нещо такова:
/home/ivanatora/stats_ping/dir.bg.log

11/03/2009 00:05:01 :   0% loss to dir.bg Average: 7.271 ms
11/03/2009 00:10:01 :   0% loss to dir.bg Average: 9.091 ms
11/03/2009 00:15:01 :   0% loss to dir.bg Average: 7.466 ms
11/03/2009 00:20:01 :   1% loss to dir.bg Average: 7.152 ms
11/03/2009 00:25:01 :   0% loss to dir.bg Average: 8.273 ms
11/03/2009 00:30:01 :   0% loss to dir.bg Average: 6.863 ms
11/03/2009 00:35:01 :   0% loss to dir.bg Average: 11.690 ms

Този лог може да използваме за каквото си искаме, а може и въобще да не го правим. Горния скрипт работи ъпдейтва директно rrdtool, така че ако не искате излишни логове да се пазят на машината ви насочете $dump = “/dev/null”; :)

Създаване на RRD бази.
За всеки изследван хост ще направим по една база. В тази база ще се съхраняват стойностите за Round Trip Time и Packet Loss.
Правим си следното bash скриптче (освен ако не ви мързи да го пишете на ръка за всяка база - може да имате и повече от три бази):

#!/bin/bash
NOW=`date +%s`
rrdtool create $1.rrd --start $NOW --step 300 
DS:PacketLoss:GAUGE:300:0:100 
DS:RTT:GAUGE:300:0:10000 
RRA:LAST:0.5:1:288 
RRA:AVERAGE:0.5:6:336 
RRA:AVERAGE:0.5:24:360 
RRA:AVERAGE:0.5:288:365

Подробностите за синтаксиса можете да намерите в документацията на RRDtool. На кратко - създаваме база с 2 източника на данни (променливи, които ще следим): PacketLoss и RTT. Задават се интервалите на ъпдейт на всеки източник,минимални и максимални допустими стойности. След това се правят 4 Round Robin Archives (буферите, за които говорихме по-рано).
Създаваме трите бази:

[ivanatora@~/rrd/temps/pings]$ sh create_script.sh bg
[ivanatora@~/rrd/temps/pings]$ sh create_script.sh gw
[ivanatora@~/rrd/temps/pings]$ sh create_script.sh int

Слагаме cronjob за изпълнение на ъпдейтващия скрипт на 5 минути:

*/5 * * * * perl /home/ivanatora/perl_razni/ping_stats.pl 87.120.194.1 gw
*/5 * * * * perl /home/ivanatora/perl_razni/ping_stats.pl dir.bg bg
*/5 * * * * perl /home/ivanatora/perl_razni/ping_stats.pl ivanatora.info int

Както видяхме скрипта приема два аргумента: адрес за ping и име на базата, която ъпдейтва.
Рисуване на графиките
Ще имаме отделна графика за всяка следена величина. Може да комбинираме няколко от графиките на една, но само ако очаквате там приблизително еднакви резултати. Големите отклонения на величините карат rrdtool да измества разделителната способност на графиката и една от графиките в общата картинка не се вижда добре. Ще имаме два скрипта за чертане на графики - един за Round Trip Time и един за Packet Loss.
/home/ivanatora/rrd/temps/pings/loss_graph.sh

#!/bin/bash
PATH=$PATH:/home/ivanatora/rrd/bin
DIR=/home/ivanatora/rrd/temps/pings/
rrdtool graph $DIR/img/loss-$1.png 
--title="<$1> Packet loss" 
--color CANVAS#000000 
--color BACK#000000 
--color GRID#006600 
--color MGRID#003300 
--color AXIS#00ff00 
--color FONT#00ff00 
--color SHADEA#000000 
--color SHADEB#000000 
--slope-mode 
--upper-limit 100 
--rigid 
--width 480 
--height 300 
--font DEFAULT:10:Arial 
DEF:loss=$DIR/$1.rrd:PacketLoss:LAST 
DEF:rtt=$DIR/$1.rrd:RTT:LAST 
AREA:loss#00FF00:"Packet loss (%)" 

/home/ivanatora/rrd/temps/pings/rtt_graph.sh

#!/bin/bash
PATH=$PATH:/home/ivanatora/rrd/bin
DIR=/home/ivanatora/rrd/temps/pings/
rrdtool graph $DIR/img/rtt-$1.png 
--title="<$1> Round trip time" 
--color CANVAS#000000 
--color BACK#000000 
--color GRID#006600 
--color MGRID#003300 
--color AXIS#00ff00 
--color FONT#00ff00 
--color SHADEA#000000 
--color SHADEB#000000 
--slope-mode 
--width 480 
--height 300 
--font DEFAULT:10:Arial 
DEF:loss=$DIR/$1.rrd:PacketLoss:LAST 
DEF:rtt=$DIR/$1.rrd:RTT:LAST 
AREA:rtt#00FF00:"Round trip time (ms)" 

Тук можем да си поиграем с цветовете и крайния резултат да е доста eye-candy. Важните редове са DEF - където се извличат стойностите на променливите от базата и AREA - самото изчертаване. За повече подробности - документацията на RRDtool.
След това правим един скрипт, който да задейства изчертаване на всички графики:
/home/ivanatora/rrd/temps/pings/graph_all.sh

#!/bin/bash
DIR=/home/ivanatora/rrd/temps/pings/
$DIR/loss_graph.sh int
$DIR/loss_graph.sh bg
$DIR/loss_graph.sh gw
$DIR/rtt_graph.sh int
$DIR/rtt_graph.sh bg
$DIR/rtt_graph.sh gw

И поставяме съответната задача в crontab:

*/5 * * * * sh /home/ivanatora/rrd/temps/pings/graph_all.sh

В резултат всичките изображения се намират в директорията pings/img/. Остава да направим красива HTML страничка, която да събира всичко в едно.
Резултата можете да го видите тук.

Какво е HFSC и има ли почва у нас

Thursday, January 29th, 2009

Снощи нямах какво да правя, та взех и преведох текст от разни места и го събрах в едно материалче което разглежда принципа на действие на HFSC. Има примери как се прави това в Linux и *BSD.

Статията може да е скучна за доста хора, така че който го интересува да чете навътре :)

(more…)

Изгасяне на монитора след вечерния филм

Tuesday, January 20th, 2009

Пускате си да гледате филмче, завивате се на топло, гасите си лампите… идилия :) Само че филма свършва, mplayer приключва и десктопа ви с всичките си милион и триста хиляди светещи пиксела се забива под клепачите ви. Сега трябва да ставате от топлото легло, да се разхождате до PC-то и да гасите монитора. За мързеливите има следния трик:

mplayer <опции>; xset dmps force off

След приключване на процеса на mplayer се изпълнява и втората команда, която управлява Power managment на монитора ви (standby, suspend, on, off) го изключва.

Бутона DEL и стоте му превъплъщения

Monday, November 3rd, 2008

Във FreeBSD-то имах един проблем, който ми тровеше нервите - бутона DEL или не работеше или имаше собствено мнение какво трябва да прави. Това му поведение се държеше както в шела (csh), така и във Vim.
Какво точно ставаше:

  • DEL се държи като BACKSPACE - трие знака от ляво на курсора
  • при натискане на DEL се изписва ?^ или ?H или нещо подобно
  • при натискане на DEL просто не се случва нищо

Изметох Гугъл за отговори какво става с мен и накрая се оказа че имам полтъргайст в контролера на клавиатурата.
Майтап :) Ама се оказа че проблема с клавишите DEL и BACKSPACE е толкова заплетен, че чак ми стана чудно как в Windows и Linux до сега не съм имал проблеми. Ето ви един примерен документ да прочетете за какво става въпрос.
Е, оказа се че тъпия проблем има тъпо решение. Във Vim командата

:fixdel

оправя всичко и съответно може да бъде добавена в ~/.vimrc
За csh има подобна магия и това е:

if ($term == “xterm” || $term == “vt100″ || $term == “rxvt” \
|| $term == “vt102″ || $term !~ “con*”) then
# bind keypad keys for console, vt100, vt102, xterm
bindkey “\e[1~” beginning-of-line # Home
bindkey “\e[7~” beginning-of-line # Home rxvt
bindkey “\e[2~” overwrite-mode # Ins
bindkey “\e[3~” delete-char # Delete
bindkey “\e[4~” end-of-line # End
bindkey “\e[8~” end-of-line # End rxvt
endif
bindkey ^? delete-char # for console
bindkey ^[[3~ delete-char # for xterm

Идеята на последните два реда обезмисля целия if-endif блок преди това. При мен работи само така - и с двете неща накуп :)

Енкодване на клипове за k800 с mencoder и ffmpeg

Monday, September 1st, 2008

От месеци се мъчех да си смачкам някое друго видео, което да мога да си го гледам на телефона. GSM е Sony Ericsson k800. По спецификации поддържа:
- видео 3GPP (H263, H264), MP4, Real8
- аудио MP4 (AAC, AAC+, E-AAC+), MP3, M4A, WMA, 3GP, AMR, WAV, G-MIDI 1, Real 8
- максимална разделителна способност 320х240
- максимален битрейт - 400 kb/s - като това е общо видео битрейт + аудио битрейт
До сега имам поне към 500 неуспешни опита да енкодна видео с mencoder и то да тръгне на телефона. Във файловия мениджър се появява една иконка с пакетче и контекстен бутон Send (като на всички непознати файлове) и толкоз. Никакъв опит за по-съществен дебъг. Какво не му харесва? Тук вече става въпрос за много сложна комбинация от видео енкодер, аудио енкодер, видео формат, видео контейнер, аудио кодек, битрейти…
Ето някой от неуспешните опити с mencoder:

mencoder input.avi -ovc lavc -lavcopts acodec=ac3:abitrate=64:vcodec=mpeg4:vbitrate=300 -oac mp3lame -lameopts br=64 -vf scale=320:240 -of lavf -lavfopts format=mp4 -o output.mp4

Сега като го гледам този, не ми е чудно че не тръгва. Опитвам се да ползвам за аудио кодек АС3, а телефона май не го поддържа

mencoder input.avi -ovc x264 -x264encopts bitrate=350 -oac mp3lame -lameopts br=64 -vf scale=320:240 -o output.mp4

Едно време си мислех че x264 == MPEG-4, сега си мисля че не е точно така. Вече почнах да се обърквам кое е енкодер, кое е кодек и кое е контейнер…
Та това са само последните два от няколкостотин опита и килограми изхабени нерви по mencoder. Не искам да кажа че mencoder си върши работата зле - виновно е задклавиатурното устройство :) В други случаи mencoder върши чудесна работа, примерно това рипване на DVD:

mencoder dvd://3 -dvd-device /mnt/cdrom/ -ovc lavc -lavcopts vcodec=mpeg4:vhq:vbitrate=”800″ -oac mp3lame -lameopts br=128 -o dvd.avi

По едно време ми писна и се залових за алтернативния софтуер - ffmpeg. Не ми хареса man страницата му, където са описани по-малко от половината опции. Въпреки това, работата горе долу стана.
Първо пробвах да преобразувам клипчето в 3GP, но се оказа че формата има комплект валидни разделителни способности, най-високата от които да ми върши работа беше 176х144. Не мерси.
Съсредоточих се върху MP4:

ffmpeg -i input.avi -ar 8000 -ac 1 -acodec libfaac -vcodec mpeg4 -s 320×240 -r 24 -b 300000 -ab 48000 -t 30 output.mp4

Видеото излезе с подходящия thumbnail в мениджъра на телефона, даже и тръгна. Единствения кусур беше звука, който беше с отвратително качество.
Ето подобрение:

ffmpeg -i input.avi -ar 44100 -ac 1 -acodec libfaac -vcodec mpeg4 -s 320×240 -r 24 -b 250000 -ab 64000 output.mp4

Аудио енкодера не ми даде да вдигна аудио битрейта докато не вдигнах и sampling rate-а. Намалих и видео битрейта, понеже на някои места видеото забавяше и се получаваше framedrop ефект. Накрая всичко тръгна на сто процента :)