вторник, 3 августа 2010 г.

Getopt и почему я с ним не подружился

Как вы уже поняли сегодняшнее повествование будет о моих неприятностях с getopt.

Случилась со мной необходимость скрипт написать который принмает на вход параметры в виде:

./script -a aaa bbb ccc -b aaa bbb ccc -c ... и т.п.

естественно количество этих самых "aaa bbb ccc" величина неизвествная


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

Решил тогда я написать свою реализацию оного дела ибо скрипт нужен а сколько я еще потрачу на поиски способа уговорить getopt сделать то что мне надо - неизвестно.

Приветствуйте велосипед. только баш.. ну и немного седа.

function parseprm()
{
result=$1
shift
pn=$1
shift
ap=$*

while [ $(expr index "$ap" "-") != "0" ]
do
flet=${ap:$(expr index "$ap" "-"):1}
if [ "$flet" = "$pn" ]
then
ap=${ap:$(expr index "$ap" "-")}
if [ $(expr index "$ap" "-") = "0" ]
then
result=$(echo ${ap:1} | sed 's/^ *//;s/ *$//')
break
else
needlen=$(expr index "$ap" "-")
result=$(echo ${ap:1:$(expr $needlen - 2)} | sed 's/^ *//;s/ *$//')
break
fi
else
ap=${ap:$(expr index "$ap" "-")}
fi
done

echo $result
return 0
}

вызывать так
echo $(parseprm null b hhh jjj -a yyy fddfd -b fgg -c jjsl jjf)

где 'null' это параметр по умолчанию т.е. вернется если
нужной опции найти не получится

'b' - ключ без минуса для которого нужно получить параметры
ну и остальное непосредственно строка для разбора

кстати если ключ есть а параметров для него нет
то вернется пустое значение

З.Ы. тут код немножко уезжает за страничку.. править не буду
Upd: Исправил ошибку в седе для откусывания конечностей

понедельник, 19 июля 2010 г.

Упорядочивание хаоса

Речь пойдет не о сотворении мира а о... кодировках. Точнее о том что с ними могут сделать программисты весьма именитых IT компаний.

Ситуация сложилась презабавная. При копировании строки, содержащейся в некоем элементе GUI некой программы, в.. да куда угодно, получается немыслимая абракадабра.

Пример
îòïðàâëÿåòñÿ

и это кирилица..

Прямым перебором наиболее вероятных кодировок обуздать эту ахинею не смогли не браузеры ни связка человек+iconv

Встал вопрос чтоже это было изначально. Ну и как водится после непродолжительного гугления была нарыта пара рецептов.
1. http://www.artlebedev.ru/tools/decoder/
2. enca

первый заявил:

Как нам пришлось помучиться

CP1252 → CP1251

второй сказал:
# echo 'îòïðàâëÿåòñÿ' | enca
Universal transformation format 8 bits; UTF-8
Doubly-encoded to UTF-8 from ISO-8859-5

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

а дело в следующем. îòïðàâëÿåòñÿ - это уже юникод соответственно если применить преобразование вида
echo 'îòïðàâëÿåòñÿ' | iconv -fUTF8 -tCP1252 | iconv -fCP1251 -tUTF8
то получим нормальную человеческую азбуку.
т.е. похоже декодер лебедева имел ввиду что данные имеющие кодировку CP1251 отобразили как CP1252.

Рассуждения enca по этому поводу я вообще не понял. И двойная трансформация из UTF-8 в ISO-8859-5 не проходит. Однако без ее подсказки о том что это уже UTF-8 я б не догадался до такого извращенного метода трансформации.

пятница, 2 июля 2010 г.

Мосты демонов

Долгое время у меня были проблемы с пробиванием ssh туннелей, никак не мог уяснить кто на ком стоял.

Но вроде счас уяснил и потому расскажу на пальцах как бы это было понятно для меня сразу. Если кому пригодится - буду рад.

Сразу оговорюсь что этот пост не ставит собой цель научить строить туннели как таковые.
Цель - по простому объяснить логику ssh демона в плане построения туннелей.

Итак приступим.

Естественно рассматривать будем на примере



Наша рабочая станция - хост1, нам надо добраться до какой либо службы на хост4 но непосредственно нам доступна только машина хост2.

Команда для подобного туннеля выглядит так
ssh -f -N -L локалхост:порт1:хост4:порт4 логин@хост3

Суть ее следующая
Запросы приходящие на "локалхост:порт1" отправлять на "хост4:порт4" используя промежуточный хост "логин@хост3", полученные в ответ данные вернуть на "локалхост:порт1".

т.е. ssh демон на той машине на которой будет выполнена команда задружится с демоном на "хост3" и будет через него передавать данные службе находящейся на "хост4" и отображать их на своем порту "порт1".
Т.е. для наших целей мы должны выполнить команду на "хост2".

И тогда со своего "хост1" мы сможем обратиться к "хост2" как к аватаре нужной нам службы, естественно напрямую указав порт.

P.S. детальнее см. man

понедельник, 28 июня 2010 г.

Лунный кофе. Отладка.

Суть проблемы.

После встраивания lua в java, у получившейся связки, отсутствует одна важная функция - отладочные сообщения. Они конечно не шибко и нужны если вы сразу пишите код без ошибок, но я не такой.

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

Проблема решается следующим образом:

LuaState.LdoFile возвращает не 0 в случае проблем. И вот тут то и придется поработать. Надо пройтись по стеку lua интерпретатора и выкинуть в stdout все что там есть предварительно преобразовав это все в строки.
примерно так

int stackPtr = 1;
tmp = L.getLuaObject(stackPtr);
while(tmp.isNil() == false)
{
System.out.println(" ["+stackPtr+"] "+tmp.toString());
stackPtr += 1;
tmp = L.getLuaObject(stackPtr);
}

И ура! Есть отладочные сообщения в случае если чего не так.

Но... если вы вызовете(допустив ошибку и имени) метод прокидываемого на уровень скрипта, Java объекта, то опять вам скажут нечто невразумительное

Invalid method call. No such method

и все тут.. ни имени метода ни строки где это произошло.

Красиво побороть эту напасть у меня не вышло. Там видимо надо шибко изгаляться с userdata в которые преобразуются все жабские объекты высовываемые в скрипт. Я не смог нормально раступить как это сделать, не смотря на почти неделю гуглежки. Если кто решил проблему красиво - велакм!

Я поступил проще.

В LuaJavaAPI.java в методе objectIndex
есть строка вида
throw new LuaException("Invalid method call. No such method");
собсно гря она нам и нужна.
меняем ее на
throw new LuaException("Invalid method call. No such method '"+methodName+"'");
и получаем глоток свежего воздуха в виде осмысленной информации о том чегоже мы такого неправильно вызываем.

И да.. не забудьте пересобрать если подключаете к проекту готовый джарник.

пятница, 11 июня 2010 г.

Тонкая однако работа!

Обнаружил преинтереснейшую особенность Oracle.

чтобы выбрать произвольный диапазон строк из таблицы надо сделать чтото в стиле

select *from
(select rownum r, ab.* from
(select * from tbl where rownum < 10)
ab)
where r between 2 and 6

а в постгрессе можно так:

select * from table limit 4 offset 6

вот такой вот ынтырпрайз этот оракл!!!

среда, 17 марта 2010 г.

Свободное солнце и суслик

-ты суслика видишь?
-нет
-и я нет.. но он есть.
(ДМБ)

В ролях:
свободное солнце - OpenSolaris
суслик - SUNWinst

Суть произошедшего в следующем. Надумалось мне овладеть искусством управления контейнерами Solaris. За сим на VirtualBox был водружен OpenSolaris. Водрузился он, что забавно, с третьего раза. Первые разы уверенно скисал при установке.

Итак солярис на месте, талмуд по управлению зонами прочитан. Зона создана. Только вот установка зоны не проходит. Дай грит мне образ системы.

И тут понеслось. Все талмуды утверждают что образ системы для подобной установке совершенно замечательно делается с помощью flarcreate а вот его в системе то и нетуть. Через пару часов гуглежки я таки выяснил что этот самый flarcreate входит в состав пакета SUNWinst. Пакета тоже не сыскал. Что замечательно все вокруг о нем говорят и показывают как пользоваться
flarcreate но откуда взяли SUNWinst - там его нет. Вобщем убился я его искать так и не нашел. Да и не нужен он как оказалось

Все оказалось значительно проще. т.е. этот чудо архиватор пригодится если захотите сделать клон системы а вот если это не критично то достаточно создать нативную зону и иметь подключение к интернету и все заработает. Все нужные пакеты вытянутся из сети, у меня получилось примерно 70Мб.

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

Вообще с солярными контейнерами оказалось все красиво и нарядно!

Ток вот VirtualBox огорчил, почемуто только 1о ядро отдал на растерзание дитю солнца. Маловато будет.

пятница, 5 марта 2010 г.

Лунный кофе. часть 3я.

И снова заноза.

Со сложными возвращаемыми значениями из java тоже не все так просто как хотелось бы. Например метод возвращает HashMap. Т.е. вернуть то он его вернет.. но вот работать с ним придется как в java.

Ниже пример трансформации в Lua таблицу. jMap соответственно HashMap возвращенный из java модуля.


lMap = {}
kSet = jMap:keySet()
iSet = kSet:iterator()

while iSet:hasNext() do
tmp = iSet:next()
lMap[tmp] = jMap:get(tmp)
end

вот как то так.

четверг, 4 марта 2010 г.

Лунный кофе. часть 2ая.

Не прошло и недели как наткнулся на проблему и долго искал решение. Часть нашел на форумах? правда довольно старых так что пришлось синтезировать то что там писали с офф докой.

Собсно гря суть проблемы.
Из java модуля прокидывается в Lua инстанс класса имеющий функцию принимающую в качестве параметров массив чего либо. Проблема заключается в том что модель построения коллекций Lua такова что массивы там - такиеже ассоциативные массивы(очень похоже на gawk).

получившееся решение не блещет красотой но работает

uArray = luajava.bindClass("java.lang.reflect.Array")
uObject = luajava.newInstance("java.lang.Object"):getClass()
ux = uArray:newInstance(uObject, #lst)

for k,v in pairs(lst) do
uArray:set(ux, k - 1, v)
end

где lst и есть Lua массив.
После этого ux передается в метод java класса и все работает.

вторник, 2 марта 2010 г.

Лунный кофе

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

Итак это будет Lua. Потому что очень маленький и просто встраивается.
Поскольку проект написан на java то и потребуется luajava.
но в репах его нет. и рпмки я не нашел.
Тут я решил тряхнуть слакварным прошлым и собрать все что надо
ручками.

сам luajava лежит здесь http://www.keplerproject.org/luajava/
там же есть мануалы по встраиванию в джава и как все это собрать. Но у меня х86_64 и потому будут небольшие отличия.

В системе уже установлен lib64lua5.1 и помечен как неудаляемый(удивлен).

В дополнение к тем пакетам что указаны в офф доке необходимы
lib64lua-static-devel
lib64lua-devel

Cобирать надо так.
make LIB_LUA=/usr/lib64/liblua.a

В противном случе make пытается привинтить 32х разрядную библиотеку
которая отсутствует, естественно.

Путь тот куда поставился пакет lib64lua-static-devel

у меня получилось примерно следующее
luajava-1.1/# make LIB_LUA=/usr/lib64/liblua.a
/opt/bea/jdk150_12/bin/javadoc -public -classpath src/java/ -quiet -d "doc/us/API" src/java/org/keplerproject/luajava/JavaFunction.java src/java/org/keplerproject/luajava/LuaException.java src/java/org/keplerproject/luajava/LuaInvocationHandler.java src/java/org/keplerproject/luajava/LuaObject.java src/java/org/keplerproject/luajava/LuaState.java src/java/org/keplerproject/luajava/LuaStateFactory.java src/java/org/keplerproject/luajava/Console.java
export MACOSX_DEPLOYMENT_TARGET=10.3; gcc -shared -o libluajava-1.1.so src/c/luajava.o /usr/lib64/liblua.a
------------------
Build Complete
------------------

После чего как и обещает офф дока джарник и библиотека появились

Поскольку я пользуюсь для сборки мавеном то прописываю в pom.xml
следующую зависимость

...
<dependency>
<groupId>luajava</groupId>
<artifactId>luajava-local</artifactId>
<version>local</version>
</dependency>
...

И импортирую получившийся ранее джарник в локальный репозитарий мавена.
mvn install:install-file -DgroupId=luajava -DartifactId=luajava-local
-Dversion=local -Dpackaging=jar -Dfile=./luajava-1.1.jar

После всех этих манипуляций проект начинает нормально компилятся

Дальнейшие действия по встраиванию описаны в документации

Дополнив проект небольшим количеством кода запускаю результат.

LD_LIBRARY_PATH=./ ~/bin/jdk1.6.0_17/bin/java -jar
target/func-test.jar test.lua

библиотека соответственно лежит тутже

все работает.. красота!
Осталость собрать библиотеку для Solaris.

пятница, 19 февраля 2010 г.

От это номер!

не могу не обратить внимание на это событие

Интересно чтоже будет дальше?
Микрософт начнет приплачивать за пользование их софтом?