понедельник, сентября 29, 2008

Настройка дополнительных клавиш под Linux

Решил задействовать дополнительные клавиши моей относительно недавнокупленной Logitech Wave Keyboard. С удивлением увидел что утилиты под иксы которая бы подхватила мою клаву прямо "из коробки" нету(напомню - у меня fedora), более того настроить дополнительные клавиши тоже нечем - они игнорятся теми настройщиками какие есть. Править конфиги руками - лениво мне, всё же не 90-е уже. И тут я нашёл то что нужно в репозитории от Tigro (если кто не знает: http://tigro.info ) - keytouch и keytouch-editor.

keytouch правда тоже мою клаву не знал, но keytouch-editor осилил мою клаву, правда комбинации типа Fn-F7 приходится нажимать хитро сначала жмём Fn, потом мышкой кнопку New а потом уже F7. Иначе в сканкод у вас запишется код клавиши Fn. После работы в keytouch-editor результаты сохранил в файл который потом подгрузил в keytouch. Жить с настроенными дополнительными клавишами стало веселее и более эффективно.

вторник, сентября 16, 2008

Работа с удалённой ФС через ssh

Довольно типичная задача когда необходимо быстренько что-то залить на сервер или перекинуть с сервера на сервер, причём ftp на серверах нет и не будет(по разным причинам). Когда это "что-то" - мои исходники/скрипты и т.п., то я использую svn потому что такие вещи у меня всегда в репозитории. Но что делать когда это например гигантский дамп БД, куча логов и тп? Тогда я обычно использовал scp - отлично копирует, но по юзабилити конечно консольно минимилистична. В принципе с помощью scp можно сделать всё что нужно. Но не очень удобно в некоторых случаях.

А удобнее использовать fuse и sshfs (в федоре пакеты fuse и fuse-sshfs). Тогда для того чтобы подмонтировать удалённую ФС необходимо сделать что-то типа такого:
sshfs root@server.com:/path/on/server /path/on/local

Тогда в /path/on/local у вас будет доступна /path/on/server находящаяся на сервере server.com. Отмонтировать можно например так:
fusermount -u /path/on/local

Вобщем в некоторых случаях sshfs экономит кучу времени.

суббота, августа 23, 2008

Организация бэкапов в linux

Долгое время я вполне обходился рукописным велосипедом для создания бэкапов. Ну т.е. использовал tar с небольшими скриптами.

Но недавно наткнулся на достаточно удобную утилиту написанную на perl - rsnapshot. Она использует rsync и hard links для создания серии бэкапов с заданными промежутками (у меня например создаются каждые 4 часа, каждый день и каждую неделю). При этом можно не просто указать что бекапить но и задать скрипты запускающиеся до/после очередного бекапа. Также есть много полезных функций например есть diff (например rsnapshot diff daily.0 daily.1 сравнит последний и предпоследний ежедневные бекапы), rsnapshot du покажет сколько отожрано места под ваши бекапы (отжирает надо сказать не так уж и много - читайте подробнее по ссылкам в заметке). Вобщем изучение man'а занимает минуты, всё просто и удобно - советую.

Перечислю вкратце плюсы которые я получил. Даже без сжатия бэкапы занимают мало места, делаются быстро. Так как бэкапы не сжаты то мгновенно можно посмотреть всё что нужно (например меняли конфигурацию утилитой и что-то поломалось - хотите посмотреть что поменялось по сравнению скажем со вчерашним конфигом), а не ждать пока распакуется многогиговый зазипованный tar файл. Можно не страдать паранойей и не коммитить в svn каждый чих - хотя конечно это спорно и не для всех подходит. Но для проектов которые вы ведёте с одного компьютера вполне применимо.

Ссылки по теме:
  1. http://www.mikerubel.org/computers/rsync_snapshots/ - желающим соорудить свой велосипед во чтобы то ни стало :)
  2. http://gentoo-wiki.com/HOWTO_Backup_to_DVD - о тонкостях бэкапа на DVD
  3. http://www.linux-backup.net/App/ - куча ссылок по теме, но много устаревших

P.S. да и делайте бэкап не на тот же диск на котором данные которые вы бэкапите. Помните закон Мерфи - бэкап нужен тогда когда его нет.

воскресенье, мая 18, 2008

Сходил на YAPC::Russia 2008

Сходил на May Perl, впечатления смешанные.

Для начала впечатления от докладов, которые я посетил.

1 день:
IO::Lambda - в принципе для меня это было что-то что я не трогал руками, но имею в планах попробовать - было интересно. Конечно то что модулю всего полгода несколько не радует, но с другой стороны свежие модули оперативней патчат по моим наблюдением, так что посмотрим.

Профилирование perl-кода - в принципе несмотря на то что большая часть информации для меня не была новой, но например kcachegrind надо будет попробовать (cправедливости ради отмечу что слышал и раньше про неё, но по-моему не использовал).

May POE - ну доклад в принципе грамотный, но мне не особо интересный, так как новой информации там для меня было (да и в целом доклад в основном обзорный был).

Потом я пошёл на мастеркласс POE - но там были проблемы с инетом, поэтому всё пошло как-то сумбурно. В целом наверное зря я на него пошёл - мастеркласс мне был не нужен, я собственно хотел задать один вопрос (задал только во второй день поймав Серёжкина с утра, но об этом ниже). Вобщем поскучал я тут, в отличие от тех кого поражала/развлекала скорость эффективного кнопкодавления в *nix консоли и emacs'е - я 90% времени живу в никсах, поэтому меня это не развлекло. Вобщем со стороны конечно виднее - но можно было и без инета придумать чего-нибудь (как вариант запустить apache/nginx и его дрючить POE или носить с собой usb-bluetooth и мобилу на случай отсутствия инета(хотя такой тонкий канал поможет не всегда)).

"Аргументы в пользу XSLT" - на мой взгляд инородный доклад. Лично мне абсолютно неинтересен был - аргументы и за и против XSLT давно известны всем интересующимся, а про какое-то приложение к perl'у не было вообще ничего сказано.

Построение совместимых Perl/mod_perl систем с веб-интерфейсом - чего-то я вообще не помню этого доклада. Либо его отменили, либо не зацепило совсем(судя по названию это очень может быть).


Perl и Web 2.0 - несмотря на то что ничего особо нового для меня не было сказано, было весело и запомнилось. Не зря докладчику дали приз. :)

2-й день:
Блицы вобщем понравились все. Единственное что про обфускатор Stunnix мне было неинтересно(всё очевидно и уж больно самопиарно, хотя может кому полезно будет), ну а "CGI.pm - зло?!" не очень вписывается в формат блиц-доклада на мой взгляд, т.к. вопросы из зала наверняка бы были. :) Ну и у Серёжкина блиц получился не до конца


Perl+виртуализация - меня не зацепило, но возможно я просто не проникся до конца.

UTF Perl Practice - в принципе полезный доклад для тех кто не хочет сам пройтись по граблям. Жаль что его не было лет 5 назад когда я на эти грабли наступал изо всех сил. :)


CMS для крупного портала на примере TRAVEL.RU - ну реально работающие решения всегда интересны. Докладчик грамотно отбивался от каверзных и не очень вопросов - видно что не в первый раз. :)

ООП. Parrot. - Ну тут для меня тема была относительно новая, да и у Серёжкина на этот раз были заранее приготовленные слайды так что доклад был интересен и безэксесен :).

YAPC::Russia::Golf - вобщем задачи были не из разряда моих любимых, да и в субботу у меня было много дел после которых в воскресенье болела голова, поэтому я забил на них. :) Но решение-победитель про делимость на 11 удивило, так как в перерыве начали прикидывать как можно сделать, но ничего похожего даже близко не придумывалось.

Теперь не про доклады, а про разное:

Во время обеда оказался за одним столом с другими перловиками и выяснил что POE полетел не так как надо не только у меня. Т.е. не у меня одного он тёк по копейке в минуту, и не меня одного его скорость не впечатлила. Вобщем после этого я передумал по этому поводу пытать Серёжкина - может действительно для его задач и скорость достаточная, и утечки не критичны (там вобщем действительно текло помаленьку, ну и как кто-то сказал ничто не мешает убить и перезапустить скажем раз в сутки).

Но на второй день случайно поймав Серёжкина, всё же спросил его про POE. Он сказал что у него оно работает и не течёт, но версия 1.0002. Я же пробовал давно и наверняка более младшую версию. Вобщем придётся видимо опять уколоться и пожрать кактус.


Про организацию:
Футболки выдали, кофебрейки были с едой и питьём - вроде всем хватило. Вобщем в этой части всё нормально.

Из минусов - накладки в докладах одного из организаторов (это я про Серёжкина), это как-то не очень радовало. Хотя я иногда малотерпим к чужой неорганизованности, поэтому может излишне предвзят. Ну и кроме того к чему-то придраться надо, а тут вроде как и по делу... :)

Добавление:
Забыл про два доклада вошедшие вне программы:
ПеАр LinuxFormat - на удивление прошёл на удивление легко.
ORM - местами было интересно, хотя я пока для своих задач не вижу смысла в нём особого.

Добавление 2:
Забыл написать что в целом неплохо, но могло быть лучше. :)

Update 3: решил дать ссылку на страницу где есть ссылки на презентации а не втыкать их сюда по одной :) : http://event.perlrussia.ru/yr2008/talks

В рассылке jerom выложил новое мегарешение гольфа про деление на 11 (автор некто mtve):
#!perl -lp
$_=s/..?\b/"@:[0..$&]"/e?redo:/^( {11})*$/?yes:'no'
Вобщем я поражён, пока больше и сказать нечего. :)

Update 4: видео с конференции здесь: http://event.perlrussia.ru/yr2008/media/video.html

среда, мая 07, 2008

vim как удобный diff (часть 2)

В предыдущем посте vim как удобный diff я уже описал как использовать vim в качестве diff. Но погуглив нашёл что оказывается есть дополнительная настройка которая делает использование vim для этой задачи ещё удобнее. Настройка называется diffopt и по умолчанию установлена в filler:
:set diffopt=filler
Это заставляет оба столбца скролится синхронно. Но кроме этого можно задать игнорирование начальных и конечных пробелов, и кол-во пробелов подряд:
:set diffopt+=iwhite
Ну и конечно можно задать игнорирование регистра при сравнении:
:set diffopt+=icase
Также можно задать кол-во строк между "схлопнутыми одинаковыми фрагментами" и отличающимися фрагментами (коряво описал - но прямее не получается чего-то), по умолчанию выставлено в 6:
:set diffopt+=context:2
Пример того что получается при выставленном icase и context:2 приведён ниже(я добавил в f1 и f2 дополнительных 8 строк чтобы fold'инг был виден):

вторник, мая 06, 2008

vim как удобный diff

Довольно обычная задача - сравнить два файла построчно. Можно конечно использовать diff (под виндой есть наверное что-то похожее, ну аналог точно есть - сам когда-то давно использовал), но вывод diff не очень красив, а для усталого ума ещё и не достаточно очевиден...

Пусть у нас есть два файла f1 и f2.
Файл f1 состоит из 5 следующих строк:
row1
row2
row3
row4
row5

Файл f2 получен из f1 закоментированием одной строки и добавлением двух новых:
row1
row2
#row3
newRow1
row4
newRow2
row5

Выполнение diff нам даёт следующий результат:
[***]# diff f1 f2
3c3,4
< row3
---
> #row3
> newRow1
4a6
> newRow2

В принципе понятно но не сказать что прямо сразу. Можно сделать чуть получше:
[***]# diff -u f1 f2
--- f1 2008-05-06 03:24:16.000000000 +0400
+++ f2 2008-05-06 03:24:41.000000000 +0400
@@ -1,5 +1,7 @@
row1
row2
-row3
+#row3
+newRow1
row4
+newRow2
row5
Но на больших файлах не очень это удобно смотреть будет, ну и если я сравниваю с целью поправить что-то то хотелось бы прямо на месте это сделать. И это можно сделать командой `vim -d f1 f2` что синонимично `vimdiff f1 f2`. После запуска этой команды получим следующую картину:


На мой взгляд весьма наглядно и удобно. Ну по крайней мере для тех кто умеет пользоваться vim. Тем кто не умеет - советую научится, так как vim обычно есть везде на *nix, там где нету - можно быстро поставить (даже под винды).

P.S. Если вдруг когда-нибудь сюда набегут emacs'овцы - на emacs'е я сидел, правда довольно давно. Со временем стал считать что он избыточен для одних задач и недостаточен/неудобен для других (это вовсе не значит что vim для этих задач достаточен), так же избегаю лишних наворотов в vim'е. Но своё мнение другим не навязываю. :)

понедельник, апреля 28, 2008

Покажи мне свою history и я скажу кто ты есть...

Увидел на одном зарубежном блоге как собрать статистику по history коммандной строки в *nix, увеличил кол-во выводимых позиций до 50 и получил следующую картину:

history 1000 | awk '{a[$2]++}END{for(i in a){print a[i] " " i}}' | sort -rn | head -n 50

134 vim
123 svn
108 make
91 ssh
48 dig
34 mc
33 perl
29 rpm
24 yum
24 wget
23 ps
23 ls
22 ./uri_test.pl
21 startx
21 service
18 mysql
15 shutdown
12 touch
12 man
11 kill


Всё что меньше 10 я отрезал - там вобщем много всего и неинтересно. В моём случае стата конечно не очень репрезентативна. dig - это временное явление, так как я настраивал dns кэш просто. Ну и make это не потому что я что-то руками собираю или на c/c++ мастерю - а в основном из-за сборки/инсталла perl-овых модулей (ну малая доля вызовов make пришлась на небольшой с++ проект). Но вобщем и целом видно чем человек занимается.

пятница, апреля 11, 2008

Оригинальный аргумент в пользу того что PHP зло

Недавно нашёл доказательство мразостности PHP - люди посчитали количество goto в сорцах разных языков тут: http://blog.ptpm.ru/index.php/2008/03/24/mrazotnyjj-pkhp/. :)

Perl получился менее мразостным чем PHP (что и так очевидно) и чем Python.

На самом деле я хотел попиарить тут проект http://defun.ru/ который что-то типа аггрегатора новостей /статей про функциональные языки и не только. Вобщем на данный момент есть что почитать интересного.

P.S. Просьба к части про мразостность языков отнестись с долей юмора.

среда, апреля 02, 2008

Неправильный POST через LWP

Писал я тут небольшое приложение и написал к нему тест на perl - с помощью LWP посылал POST запрос ну и соответственно проверял реакцию. Реакция оказалась неправильной, но при этом если я руками через firefox слал то же самое то всё замечательно работало. Побайтно сравнив посылаемое в обоих случаях - обнаружил что perl не эскейпит символ "!", т.е. посылает как есть, а firefox как %21. Полез искать почему так - нашёл что в итоге вызывается query_form (в URI::_query) который соответственно вызывает метод query такой:

sub query
{
my $self = shift;
$$self =~ m,^([^?\#]*)(?:\?([^\#]*))?(.*)$,s or die;

if (@_) {
my $q = shift;
$$self = $1;
if (defined $q) {
$q =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
$$self .= "?$q";
}
$$self .= $3;
}
$2;
}


Т.е. эскейпится всё кроме символов в $URI::uric. Полез смотреть что там прописано:

$reserved = q(;/?:@&=+$,[]);
$mark = q(-_.!~*'()); #'; emacs
$unreserved = "A-Za-z0-9\Q$mark\E";
$uric = quotemeta($reserved) . $unreserved . "%";


Т.к. "!" в $mark то он тоже не преобразуется. Полез смотреть стандарты в rfc1866 сказано следующее:
The form field names and values are escaped: space
characters are replaced by `+', and then reserved characters
are escaped as per [URL]; that is, non-alphanumeric
characters are replaced by `%HH', a percent sign and two
hexadecimal digits representing the ASCII code of the
character. Line breaks, as in multi-line text field values,
are represented as CR LF pairs, i.e. `%0D%0A'.


Тут конечно можно задуматся входит "!" в alphanumeric или нет, но rfc2396 рассеивает все сомнения:
alpha = lowalpha | upalpha

lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" |
"j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" |
"s" | "t" | "u" | "v" | "w" | "x" | "y" | "z"

upalpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" |
"J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" |
"S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z"

digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" |
"8" | "9"

alphanum = alpha | digit


Т.е. firefox прав, а lwp нет. В принципе lwp вообще непонятно зачем form_query в POST вызывает - оно не для этого. Ну ладно - это всё лирика...

Поправить дело можно относительно легко - исправить $URI::uric на то что нужно перед POST, а потом обратно. Заменить можно например так: $URI::uric = quotemeta("=&+")."A-Za-z0-9"; . Но возможно(скорей всего) я тут что-то не учёл - просто для моего теста это сработало, а всесторонне исследовать - времени нет.

Всё-таки LWP написан очень плохо - в который раз убеждаюсь. Зачитать про другой баг LWP.

четверг, февраля 28, 2008

GWT RPC

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

Для начала вкратце о том зачем оно(GWT RPC) нужно.
Все наверное слышали про AJAX (те кто не слышал могут зачитать здесь или на русском здесь). В принципе способов реализации много, но обычно(ну или часто, а не обычно - я не бог весть какой AJAX-гуру сейчас, но когда-то много чего пробовал и в итоге приходил к передаче форматированных данных, а не например html для вставки - что само по себе плохо так как стандарт на это вроде смотрит косо. Да и вообще зачем на сайте генерить то что можно переложить на клиентскую часть? Отдал данные - пусть яваскрипт работает и вставляет куда нужно что надо. При этом как правило увеличивается скорость работы, т.к. трафик получается без оверхеда - только данные без оформления гоняются.) данные передают в формате XML или JSON. Т.е. если у вас на сайте есть например объект класса BigInfo, то вы должны его преобразовать в XML или JSON и передать клиенту, а на клиенте должны соответственно обработать полученный кусок данных (часто это значит преобразовать уже в объект класса JS и сделать с ним чего-то).

Вроде всё просто но минусы тоже очевидны:
  • трудоёмкое и нудное отслеживание корректности получаемых данных(речь естественно не о простых случаях);
  • асинхронность разработки усложняет отладку и повышает вероятность ошибки(поменяв формат в серверной части и неправильно поменяв клиентскую можно получить волшебные неуловимые баги).
В принципе можно конечно написать свою волшебную библиотечку которая из класса написанного на серверном языке с некоторыми закоменченными декларациями будет генерить этот же класс но уже с методом сериализующим его например в JSON и этот же класс но уже на яваскрипте с методом десериализации из JSON. В принципе в этом есть смысл если приложение большое...

Так вот GWT RPC нужно чтобы избавить вас от всех этих проблем. Ну избавить настолько насколько это возможно. Естественно бесплатно ничего не бывает - поэтому выбора серверного языка вы лишаетесь, им автоматически становится Java. Итак вкратце как этот работает...

Для тех кто не знаком с GWT сообщу что сам GWT (безо всяких RPC) уже по сути и есть та волшебная библиотечка которая преобразует код написанный на Java в код написанный на JavaScript. Т.е. по сути нам осталось добиться того, чтобы мы могли в GWT написать серверную часть используя общие классы с клиентской частью.

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

Собственно интерфейс нашего сервиса:
public interface CustomService extends RemoteService {
public String myMethod(String s);
}
Асинхронная версия нашего сервиса, получается путём добавления к имени предыдущего интерфейса "Async", заменой возвращаемого значения на void и добавления в параметры метода аргумента типа AsyncCallback:
interface CustomServiceAsync {
public void myMethod(String s, AsyncCallback callback);
}
Ну и наконец класс который будет исполняться на серверной части, к названию основного интерфейса прибавляем "Impl" и наследуемся от RemoteServiceServlet:
public class CustomServiceImpl extends RemoteServiceServlet implements CustomService {

public String myMethod(String s) {
return s+" oO";
}
}
По сути CustomServiceImpl это сервлет умеющий делать сериализацию(т.к. наследуется от RemoteServiceServlet а не от HttpServlet).

Чтобы всё это заработало надо конечно настроить mapping для сервлета, сделать вызов с помощью асинхронного интерфейса, обработать результат в созданном callback'е. Mapping прописывается в web.xml (для Eclipse и NetBeans вроде бы по разному - так что смотрите как вам нужно)... Допустим мы замапили сервлет на url "customURL". Вызов делается примерно так:

public void testMyMethod() {
CustomServiceAsync custService = (CustomServiceAsync) GWT.create(CustomService.class);

// указываем урл по которому отзывается наш "сервлет"
ServiceDefTarget endpoint = (ServiceDefTarget) custService;
String moduleRelativeURL = GWT.getModuleBaseURL() + "customURL";
endpoint.setServiceEntryPoint(moduleRelativeURL);

// создаём callback
AsyncCallback callback = new AsyncCallback() {
public void onSuccess(Object result) {
// радуемся
}

public void onFailure(Throwable caught) {
// страдаем
}
};

// Делаем вызов нашего сервиса. Вызов будет асинхронный - программа продолжится сразу,
// а когда придёт ответ вызовется callback
custService.myMethod(someString, callback);
}
Вобщем понятно - мы получим результат в onSuccess, далее надо его преобразовать к нужному типу и обработать. Но этот пример по сути даёт только одно преимущество по сравнению со стандартным AJAX-подходом - мы может отлаживать серверную часть без отрыва от клиентской. Но тут не отображена проблема передачи не примитивов а например коллекций или объектов наших классов.

Что если мы захотим такой интерфейс, myMethod вернёт нам список строк например:
public interface CustomService extends RemoteService {
public List myMethod(String s);
}
(для тех кто не в курсе - на данный момент под GWT можно писать только в режиме совместимости с явой 1.4, поэтому List не типизирован)

Это работать не будет - потому что угадывать что за объекты лежат в List GWT не умеет, и соответственно сериализовать/десериализовать не сможет. Но для типизирования коллекций в GWT сделали специальную javadoc-аннотацию, если вы хотите получить список строк то надо переписать интерфейс так:
public interface CustomService extends RemoteService {
/**
* @gwt.typeArgs <java.lang.String>
*/
public List myMethod(String s);
}
Тут мы указываем что будет возвращён список строк а не чего-то ещё. Если надо типизировать аргумент, то пишем так:
public interface CustomService extends RemoteService {
/**
* @gwt.typeArgs listArg <java.lang.String>
* @gwt.typeArgs <java.lang.String>
*/
public List myMethod(String s,List listArg);
}
Так мы указали что listArg это список Integer, а возвращается список строк.

Итак выяснили что примитивные типы(ну и обёртки над ними) и коллекции примитивных типов сериализуемы и передавать/получать их через GWT RPC можно. Чуть сложнее дело с пользовательскими классами. Для того чтобы класс можно было сериализовать автоматически необходимо выполнение следующих условий:
  1. класс должен реализовывать интерфейс com.google.gwt.user.client.rpc.IsSerializable либо сам, либо иметь базовый класс который этот интерфейс реализовал;
  2. все поля(кроме final и transient) должны быть сериализуемы;
  3. класс должен иметь публичный конструктор по умолчанию
Если ваш класс не удовлетворяет какому-либо из этих условий, либо не устраивает стандартный сериализатор (например по производительности), то вы можете написать свой сериализатор.

Для того чтобы создать свой сериализатор для класса MyClass надо создать класс MyClass_CustomFieldSerializer (именно такое построение имени важно) такого вида:

import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.client.rpc.SerializationStreamReader;
import com.google.gwt.user.client.rpc.SerializationStreamWriter;

public class MyClass_CustomFieldSerializer
{
public static ServerStatusData instantiate(
SerializationStreamReader reader)
throws SerializationException
{
}

public static void serialize(
SerializationStreamWriter writer,MyClass instance)
throws SerializationException
{
}

public static void deserialize(
SerializationStreamReader reader,MyClass instance)
throws SerializationException
{
}
}
Метод instantiate() опциональный и нужен для того чтобы породить объект класса который не имеет публичного конструктора по умолчанию.

Метод serialize() позволяет записывать в поток данные которые вы хотите сериализовать. У SerializationStreamWriter(объект которого передаётся в аргументах вызова serialize()) есть методы writeBoolean, writeInt, writeObject и т.д. для этого.

Метод deserialize() соответственно позволяет считать из потока сериализованные данные и как-то привязать их к объекту. Считывать надо в том же порядке в котором вы писали в методе serialize(). У SerializationStreamReader есть методы readBoolean, readInt, readObject и т.д.

В итоге на относительно сложных проектах это всё очень удобно писать, дебагить и поддерживать.

Ссылки по теме:
GWT RPC
GWT

P.S. Правда эклипс не прижился почему-то с GWT RPC - постоянно впадал в транс при большой корректировке интерфейсов, проблемы с серверной частью у него были. Перешёл на NetBeans и пока не пожалел - костыль который я описывал здесь теперь без надобности.

суббота, февраля 23, 2008

Выкат GWT-RPC приложения на Tomcat из-под Eclipse

Решил написать краткую инструкцию по выкату GWT-RPC приложения под Томкат. Стандартный способ который даже вроде бы упоминается в доках, гласит примерно следующее - скомпиляйте клиентскую часть в яваскрипт, отдельно скомпиляйте серверную часть и выкатите куда вам надо.

Всё правильно конечно, но это можно делать с разной эффективностью. Особенно компилять серверную часть(те кто юзал GWT давно должны помнить хаки к которым приходилось прибегать)... На самом деле есть вполне конкретные удобные варианты быстрого deploy'я приложения GWT-RPC на Tomcat. Один из них заточенный под Eclipse я и распишу. Соль этого варианта - быстро сделать WAR-файл и выкатывать уже его.

Итак то что нужно сделать для начала(только один раз):
  • открыть {PF}\www\com.domain.{Project}
  • создать новую директорию WEB-INF
  • открыть {PF}\www\com.domain.{Project}\WEB-INF
  • создать файл web.xml и прописать туда что нужно
  • создать новую директорию lib
  • открыть {PF}\www\com.domain.{Project}\WEB-INF\lib
  • скопировать gwt-servlet.jar из дистрибутива GWT в {PF}\www\com.domain.{Project}\WEB-INF\lib
Это надо делать каждый раз для получения WAR-файла:
  • запустить скрипт {PF}\{Project}-compile
  • в Eclipse выбрать папку src
  • нажать Export (в выпадающем меню или в меню "File")
  • выбрать экспорт в "JAR file"
  • отметьте "Export generated class files and resources"
  • отметьте "Export java source files and resources"
  • установите export destination в {PF}\www\com.domain.{Project}\WEB-INF\lib\{Project}.jar
  • отметьте "Compress the contents of the JAR file"
  • дважды нажмите Next
  • выберите "Generate the manifest file" (если не выбран)
  • не отмечайте "Save the manifest in the workspace"
  • "Seal the contents" - должно быть выбрано "Seal some packages" ... "Nothing sealed"
  • оставьте поле "Main class" пустым
  • жмём "Finish"
  • открываем {PF}\www\com.domain.{Project}
  • упаковываем все файлы и директории в zip-файл с именем {Project}.war
  • кидаем {Project}.war томкату внутрь (зависит от того куда именно вы хотите выкатить проект)
Обозначения:
{PF} - путь к проекту (например /home/gwt_project1)
{Project} - название проекта (например Calendar)

Вобщем лично мне такой подход сильно экономит время. Те кто использают не Eclipse - могут модифицировать всё тут описанное в скрипт для ant ну или ещё во что-то, никакой особой магии тут не используется...

В принципе идея взята отсюда но там автор (видимо после множества редакций) перевирает с путями местами.

пятница, февраля 22, 2008

Про ломку капч

Давно я не писал про спам и спамботов. А тут и повод есть.

Mail.ru ввела новую капчу на реге. Сначала она выглядела весьма психоделично:
Потом сменили на менее мозголомающий вариант:

При кажом нажатии на цифру кнопки перемешиваются заново.

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

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

В принципе из интервью вебпланете видно что Ильичев (директор по проектам mail.ru) вполне в теме вопроса и нету у него ощущения что он отлил серебрянную пулю против спамеров. Просто он обеспечил себе перевес в борьбе. И путь к победе он видит верно: "Наша задача - не сделать лже-регистрации невозможными в принципе (это утопия), а сделать их как можно более дорогостоящими. Чтобы бизнес спамеров с использованием нашей системы стал неэффективным.". Вобщем рад что первыми ощутимо двинулись в правильном направлении мои соотечественники (хотя самое правильное направление конечно у Gmail - не помню когда я там спам в инбоксе видел последний раз).

В принципе давно надо было mail.ru взятся за эту проблему - у меня есть ящик на mail.ru и количество спама которое на него приходит с ящиков на том же mail.ru огромно. Конечно много сразу ложится в spambox ещё на сервере, что-то ещё фильтрами клиента укладывается, но всё же прорывалось иногда письмо-другое.

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

Ссылки по теме(все публикации свежие - этого года):
взлом капчи Gmail
взлом капчи Microsoft
взлом капчи Yahoo

воскресенье, февраля 10, 2008

Что делает gcc/особенности OpenSSL

Решил в виде исключения разродится миниобзором чужого сайта.

Просматривал тут сайт Сысоева (который автор nginx) и наткнулся на древнюю ссылку на англоязычную статью What gcc really does. Оказывается сам gcc в основном занимается тем что вызывает другие программы. Флажок -save-temps весьма интересный - даёт возможность посмотреть что получается на промежуточных стадиях. Надо бы копнуть поглубже потому что с наскоку не всё понятно. Понятно что .i файл получился после препроцессинга, но интересно что за хитрые строчки типа # 325 "/usr/include/sys/cdefs.h" 2 3 4 там натыканы(ну по этому поводу несколько догадок напрашивается, но хотелось бы убедится).

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

Вообще на сайте Сысоева есть не менее интересные заметки и ссылки (например "The C10K problem") - просто они не были для меня новы. Вобщем советую зачитать сайт sysoev.ru - обновляется он редко, так что много времени не уйдёт.

пятница, февраля 08, 2008

Получить список используемых модулей в проекте perl

Вычитал на Mechanix что для того чтобы узнать какие модули используются perl-проектом, достаточно запустить в директории с ним вот такое:
ack -h '^use\s+(\w+(?:::\w+)*).*' --output=\$1 | sort -u

Ну как вобщем я увидел сразу - этого не достаточно. Потому что не учитываются например базовые классы, которые я использую с помощью use base qw(ModuleName), и почему-то не учитываются варианты когда use написан не вначале строки а с отступом поэтому я быстренько(не мудрствуя особо) дополнил эту команду до такой:
ack -h '^\s*use\s+base\s+(?:qw\()*\s*(\w+(?:::\w+)*)|^\s*use\s+(\w+(?:::\w+)*).*' --output=\$+ | sort -u


Тут конечно тоже не всё учтено, но уже лучше по крайней мере. В этом варианте не учитываются классы из @ISA, не учитывается множественное наследование через base - так что это не универсальный вариант. Но кому надо - сам допишет что ему нужно.

P.S. Для тех кто не в курсе что такое ack: http://petdance.com/ack/

суббота, февраля 02, 2008

Perl cheat sheets

Думаю у тех кто использует много языков периодически возникают проблемы с вспоминанием простых казалось бы вещей при переходе на язык который не использовал довольно долго. Вернее даже вроде бы вспомнил но сомневаешься, а хочется проверить быстренько скажем за несколько секунд ну или десятков секунд (я например периодически забываю $+). Для таких случаев я обычно использовал распечатку ключевых моментов языка в виде таблицы(на 1-2 страницы максимум), но со временем потерял и сами таблички и цифровой их оригинал. Поиском нашёл что оказывается что-то такое уже есть.

Ключевые моменты perl (для новичков незаменима, для не новичков - такое забывать стыдно :) ):
http://juerd.nl/site.plp/perlcheat

Предопределённые переменные perl:
http://perldoc.perl.org/perlvar.html,
то же самое но переформатированное более удобно:
http://docs.google.com/Doc?id=dn6sgh3_6fbdspbcg.

Расширенный краткий обзор perl(ссылка на pdf внизу страницы):
http://johnbokma.com/perl/perl-quick-reference-card.html

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

воскресенье, января 20, 2008

LWP через SOCKS

Для того чтобы использовать LWP через SOCKS можно воспользоваться замечательным модулем LWP::Protocol::http::SocksChain. В принципе там пример есть, но вкратце вам просто надо указать LWP чтобы он работал через этот класс и задать параметры для сокетов, вот например что нужно добавить для работы через SOCKS4 1.1.1.1:80 :
LWP::Protocol::implementor(http => 'LWP::Protocol::http::SocksChain' );
@LWP::Protocol::http::SocksChain::EXTRA_SOCK_OPTS = (
Chain_Len => 1,
Debug => 0,
Random_Chain => 1,
Chain_File_Data => ['1.1.1.1:80:::4'],
Auto_Save => 0,
Restore_Type => 1
);



На больших объёмах я его не гонял(не использую LWP на них), но в принципе работоспособный вариант...

P.S. Как видно из названия модуля он позволяет работать через цепочки SOCKS.

пятница, января 18, 2008

Как посчитать кол-во строк соответствующих регекспу в файле

Исходные данные - в файле pr_2 есть строки содержащие в себе подстроки вида Data result: X где X неотрицательное целое число меньше 100(не суть). Надо найти сколько строк для каждого такого X.

Решение одной строкой:
cat pr_2|grep -o -E "Data result: [0123456789]+"|sort -|uniq -c
ну или так(синонимично):
cat pr_2|grep -o -E "Data result: [[:digit:]]+"|sort -|uniq -c

На выходе примерно такое:
8585 Data result: 0
16 Data result: 18
1772 Data result: 28
9 Data result: 47

Первое число в строке - это кол-во строк соответствующих регекспу из этой строки в файле pr_2.

среда, января 16, 2008

Работа в linux. Заметки на полях.

Решил вобщем записать то что регулярно использую (это будет возможно полезно остальным), и то что регулярно забываю(это будет полезно мне :) ) при работе(различного рода) в linux... Так что наверное этот пост не для всех. Советы эти малосвязны друг с другом можно сказать это заметки на полях.

Для работы на удалённом хосте используйте screen. Даже если сессия оборвётся вы всегда сможете быстро законектиться и оказаться в точно том же состоянии которое было до разрыва, более того вы можете загрузить любую из сессий screen которые были созданы. Краткий перечень команд:
  • создание сессии screen -S SessionName
  • создание нового "окна" shell Ctrl-a c
  • переход между shell'ами Ctrl-a shell# где shell# это номер shell'а от 0 и выше
  • посмотреть список сессий скрина screen -ls
  • убить активный shell exit
  • выйти из текущего скрина Ctrl-a d
  • загрузить ранее созданную сессию screen -d -R SessionName
Вобщем наверное сходу не всем понятно зачем это надо и как работает, но попробуйте и не пожалеете.

-----

Если вам надо скопировать например первые 100 строк одного файла в другой(бывает часто нужно с тестовыми данными) то вы можете сделать это так:
sed -n '1,100p' file1 > file2

-----

Для поиска утечек памяти и например багов в многопоточных приложениях используйте valgrind. Ключи запуска перечислять не буду - смотри сайт и valgrind --help.

-----

Для отладки программы когда нужно посмотреть системные вызовы, сигналы и т.п. я советую использовать strace. Для подробностей читайте мануал, лучше чем там не написать. :)