суббота, 30 июня 2012 г.

Pretty Nice git log output

Наконец то дошли руки по нормальному настроить себе вывод git log.
Выставляем следующие строчки в ваш .git/config
 [format]  
   pretty = %C(yellow)%h%Cred%d%Creset - %C(cyan)%an %Creset: %s %Cgreen(%cr)  
И получается очень удобный и информативный вывод логов =)
Быстро посмотреть что получится можно вот такой командой:
 git log --pretty=format:'%C(yellow)%h%Cred%d%Creset - %C(cyan)%an %Creset: %s %Cgreen(%cr)'  

Читать далее

воскресенье, 7 ноября 2010 г.

SSH Agent Forwarding

Возникла у меня на днях такая задачака:
Есть машина(m1) с парой ключей(private and public), я захожу через ssh на другую машину(m2), на которой лежит только публичный ключ, затем с машины(m2) хочу сделать clone git репозитория(на git'овом сервере тоже лежит публичный ключ), но git отвечает: Permission denied (publickey) т.к. моего private ключа на машине(m2) нет.


Решение проблемы:
  1. Запускаем ssh-agent на машине(m1):
    eval `ssh-agent`
    Его нужно запустить только если он ещё не запущен
  2. Добавляем ключ агенту:
    ssh-add
    По умолчанию добавится id_rsa ключ
  3. Проверяем добавился ли ключ:
    ssh-add -l
  4. Подключаемся к хосту через ssh клиенту с опцией -A(либо можно с опцией -o "ForwardAgent yes"):
    ssh -A somebody@somehost
    Либо можно добавить в ssh config:
    Host *
         ForwardAgent yes
  5. Делаем git clone или что мы там хотели и обязательно радуемся, потому-что все работает :)

Полезная ссылочка
An Illustrated Guide to SSH Agent Forwarding

Читать далее

воскресенье, 16 мая 2010 г.

Python client for GoogleTranslate

Есть две хороших и удобных штуки: сервис GoogleTranslate и *nix сonsole. И я решил подружить их =). Вообщем решил написать консольный клиент для GoogleTranslate.

В качестве языка выбрал python. Побродив по просторам всемирной паутины, готовой имплиментации python API для GoogleTranslate не обнаружил. Пришлось разбиратся самому. Вообщем-то ничего сложного:

Обращаемся по URL(пример которого приведен ниже) в ответ получам JSON со статусом ответа, и если все хорошо то там же найдем и перевод:

URL:

http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&langpair=[FROM]%7C[TO]&q=[TEXT]

FROM - из какого языка переводить
%7С - разделитель в виде вертикальной черты(|)
TO - в какой язык переводить
TEXT - текст который нужно перевести


Ответный JSON:

{responseData: {translatedText: [TEXT]}, responseDetails: None, responseStatus: [STATUS]}

translatedText - переведенный текст
responseStatus - статус сообщения

Так как я использую python 2.5, для работы с JSON легким движением руки установил simplejson

  1. sudo apt-get install python-simplejson



После этого написал модуль для работы с GoogleTranslate API:


  1. #!/usr/bin/env python

  2.  

  3. import simplejson

  4. import urllib

  5. import sys

  6.  

  7. GOOGLE_TRANSLATE_AJAX_URL = "http://ajax.googleapis.com/ajax/services/language/translate?"

  8. LANGUAGE_SEPARATOR = "|"

  9. RESPONSE_STATUS = "responseStatus"

  10. RESPONSE_DATA = "responseData"

  11. TRANSLATED_TEXT = "translatedText"

  12.  

  13. def translate(fromLanguage, toLanguage, text):

  14.         """ Translate text using google translate service"""

  15.         # Generate url

  16.         url = GOOGLE_TRANSLATE_AJAX_URL + urllib.urlencode({"v" : "1.0", \

  17.                         "langpair" : fromLanguage + LANGUAGE_SEPARATOR + toLanguage, \

  18.                         "q" : text})

  19.  

  20.         result = simplejson.load(urllib.urlopen(url))

  21.        

  22.         if (result[RESPONSE_STATUS]== 200):

  23.                 return result[RESPONSE_DATA][TRANSLATED_TEXT]



Вот такой простенький модуль получился =).

Ну а теперь код основного скрипта:

  1. #!/usr/bin/env python

  2.  

  3. from googledict import translate

  4. import sys

  5.  

  6. def main(args):

  7.        

  8.         fromLanguage = args[0][:2]

  9.         toLanguage = args[0][2:]

  10.         text = args[1]

  11.  

  12.         print translate(fromLanguage, toLanguage, text)

  13.  

  14. if __name__ == "__main__":

  15.         main(sys.argv[1:])



Ну вот и подружились =):

>./gt.py enru "Hello world"

Привет мир

Простенький скриптик всего с 2-мя аргументами. Первый аргумент состаит из двух частей, первые 2-е буквы это язык из которого переводим, вторые 2-е в который переводим. Ну а второй аргумент собственно что переводим.

Сорци всего этого добра можно найти Тут
Всем спосибо кто дочитался до этих строк.
Всего доброго...

Читать далее

вторник, 9 февраля 2010 г.

Борьба с hibernate LazyInitializationException

Сделай настолько просто, насколько это возможно, но не проще А. Эйнштейн
Доброе время суток!
По просьбе коллег пишу этот пост.
Суть проблеммы:
Когда мы по запросу подтягиваем hibernate сущность содержащую поля инициализирующиеся как Lazy, и пытаемся отобразить эти поля например на странице, то мы получаем LazyInitializationException.

Причина проблемы:
В момент обращения к сущности на странице, сессия уже закрыта и сущность находится в так называемом detached состоянии (более подробно о состояниях тут), отсюда то нам и не удается запросить у сущности её Lazy поля.
Решение:
Решение этой проблемы напрашивается само, сессию нужно держать открытой до тех пор пока не отдадим страницу.
Так как мы используем spring то и решение этой проблемы, будет расмотрено в рамках spring.
Необходимо добавить в свой web.xml spring'овый фильтр который и будет держать сессию открытой.
Вот как это выглядит:

<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter-class>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>sessionFactory</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>*.htm</url-pattern>
</filter-mapping>

Здесь sessionFactory это имя той hibernate фабрики которую вы инициализировали в своем application context'е.

Ну вот собственно и все, после объявления данного фильтра никаких LazyInitializationException поидее у вас быть не должно =).

По этой же теме hibernate community

До новых встреч!)

Читать далее

вторник, 24 ноября 2009 г.

Информация о Linux машине

Понадобилось мне на днях получить полную информацию о сервере на котором я работал.
Давайте рассмотрим как же это можно сделать.

Информацию о установленном дистрибутиве:
$ cat /etc/*-release

Обладатели Ubuntu увидят нечто подобное следующему:
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=9.10
DISTRIB_CODENAME=karmic
DISTRIB_DESCRIPTION="Ubuntu 9.10"

Информацию о системе можно получить следующей комбинацией команд:
$ cat /proc/version

В Ubuntu:
Linux version 2.6.31-15-generic (buildd@yellow) (gcc version 4.4.1 (Ubuntu 4.4.1-4ubuntu8) ) #50-Ubuntu SMP Tue Nov 10 14:53:52 UTC 2009


Так же можно получить немного информации воспользовавшись
$ uname -a

В Ubuntu:
Linux alekseiko 2.6.31-15-generic #50-Ubuntu SMP Tue Nov 10 14:53:52 UTC 2009 x86_64 GNU/Linux

Информацию по объему памяти можно получить
$ cat /proc/meminfo

Информацию по процессору получаем вот так:
$ cat /proc/cpuinfo

Информацию о кол-ве дискового пространства:
$ df -h

Этот список буду продолжать, чтобы самому можно было заглянуть и освежить в памяти то что позабылось :)




Читать далее

четверг, 24 сентября 2009 г.

JSP для определения JAR'ника на сервере по имени класса.

Мал золотник да дорог.
Народная пословица(с)
    Я работаю над очень большим J2EE приложением и частенько сталкиваюсь с проблеммой(и не только я сталкиваюсь но и мои коллеги) определения из какого jar'ника загружен тот или иной класс и где этот jar'ник на сервере лежит.

    Для таких целей я написал давольно таки простенькую, но очень полезную jsp :-) которая принемает на вход имя класса и возвращает, где лижет тот jar'ник из которого загружен необходимый класс. Сама jsp удобна тем что подкладывать её можно на рабочий сервер без перезагрузки. Вообщем получилась некая мини тулза.
    Код её можно посматреть/скопировать здесь getJar.jsp

    Ну это вообщем все что я хотел поведать сегодня. Всем всего хорошего :-)

Читать далее

воскресенье, 19 июля 2009 г.

Работа с memcachedb в JAVA.

Нет причин тормазить свое развитие.
Георгий Александров.
Здравствуйте друзья!!!
В этом посте я бы хотел вам рассказать про возможности использования memcachedb на java.

О memcachedb
Давайте начнем наш разговор с того, что разберемся, что же это за зверь такой memcachedb. В двух словах это такой вид субд, обращение к которой происходит через протокол memcached (интересная презентация на эту тему), а бэкэндом является BerkeleyDB. Более подробно можно прочитать здесь.

Установка и запуск
Ну что ж приступим к установке у себя на компьютере этой прелести. Сразу хочу оговориться, что устанавливать мы будем на Ubuntu, но на других платформах я думаю, никаких сложностей с установкой у вас не возникнет.
Для начала нам нужно установить libevent.
sudo apt-get install libevent1 libevent-dev
Теперь нам необходимо поставить BerkeleyDB. Исходники скачать можно здесь.
tar -xvf db-4.7.25.tar.gz
cd db-4.7.25/build_unix
../dist/configure
make
sudo make install
А вот теперь можно качнуть и поставить memcachedb. Исходники скачать можно здесь.
tar -xvf memcachedb-1.2.0.tar.gz
cd memcachedb-1.2.0
./configure
make
sudo make install
Ну вот мы все установили и теперь можем запустить.
memcachedb -d -v -u root -f some.db -N -H ~/memcachedb
Java клиент
Как я уже говорил ранее, интерфейсом для работы является memcached. Существует несколько клиентов для работы с memcached. Полный список клиентов можно посмотреть здесь. Я выбрал spymemcached, поэтому дальнейшее повествование пойдет о нем.

Demo application
Наконец-то мы все скачали, установили, запустили и подключили. Теперь можем написать небольшое демонстрационное приложение. Наше приложение будет некое подобие тестовой системы. Оно будет задавать пользователю вопрос, ждать пока пользователь ответит на вопрос и сверять правильно ли ответил пользователь на поставленный вопрос. Так как приложение мы пишем для демонстрации работы с memcachedb то, особо сильной логикой перегружать его не будем.
Немного расскажу как у нас будут хранится данные так как memcachedb является бд key=value то мы будем использовать так называемые пространства имен т.е.[namespace]:[key]=[value].
Ну что ж вроде все обговарили, код с комментариями в судию :)
  1. /**
  2. * Copyright (c) 2009 alekseiko alekseiko@gmx.com
  3. */
  4. package memcachedb.example.main;
  5. import java.io.BufferedReader;
  6. import java.io.IOException;
  7. import java.io.InputStreamReader;
  8. import java.net.InetSocketAddress;
  9. import net.spy.memcached.MemcachedClient;
  10. /**
  11. * This is main class for example.
  12. *
  13. * @author alekseiko
  14. *
  15. */
  16. public class Main {
  17. // Customize for memcachedb
  18. private static MemcachedClient client;
  19. private static final String SERVER_NAME = "localhost";
  20. private static final int SERVER_PORT = 21201;
  21. private static final int EXPIRED = 0;
  22. // Memcachedb namespace and key
  23. private static final String TASK_SEQUENCE = "taskSequence";
  24. private static final String TASK_QUESTION = "task_question:";
  25. private static final String TASK_ANSWERS = "task_answers:";
  26. private static final String TASK_TRUE_ANSWER = "task_true_answer:";
  27. // User command
  28. private static final String STOP_COMMAND = "stop";
  29. private static final String NEXT_TASK_COMMAND = "n";
  30. // Splitters
  31. private static final String ANSWER_SPLITTER = ",";
  32. private static final String ANSWER_NUMBER_SPLITTER = ") ";
  33. // Messages
  34. private static final String CONGRATULATION_MESSAGE = "Congratulation! " +
  35. "Enter 'n' for get next question";
  36. private static final String QUESTIONS_IS_COMPLETE_MESSAGE = "Question is" +
  37. " complete.";
  38. private static final String DATA_IS_CORRUPT_MESSAGE = "Data is corrupt.";
  39. private static final String BAD_ANSWER = "Sorry you answer is incorrect. " +
  40. "Try again.";
  41. /**
  42. * General logic for work with memcachedb and user i/o.
  43. *
  44. * @param args
  45. * @throws IOException
  46. */
  47. public static void main(String[] args) throws IOException {
  48. // Connect to memcachedb
  49. client = new MemcachedClient(new InetSocketAddress(SERVER_NAME,
  50. SERVER_PORT));
  51. // Hardcode fill memcachedb of tasks.
  52. fillMemcachedbOfTask();
  53. BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  54. String msg = null;
  55. // Default currentTask=0 because task begin with 1
  56. int currentTaskId = 0;
  57. // Get last sequence value
  58. int maxTaskId = (Integer) client.get(TASK_SEQUENCE);
  59. while(!STOP_COMMAND.equals(msg = br.readLine())) {
  60. if (NEXT_TASK_COMMAND.equals(msg)) {
  61. if (currentTaskId >= maxTaskId) {
  62. System.out.println(QUESTIONS_IS_COMPLETE_MESSAGE);
  63. break;
  64. }
  65. currentTaskId++;
  66. // Get task from memcachedb.
  67. String question = (String) client.get(TASK_QUESTION + currentTaskId);
  68. String answers = (String) client.get(TASK_ANSWERS + currentTaskId);
  69. if (question !=null && answers != null) {
  70. // Out question
  71. System.out.println(question);
  72. // Split answers
  73. String[] answerList = answers.split(ANSWER_SPLITTER);
  74. // Out answers
  75. for (int i = 0;i < answerList.length;i++) {
  76. System.out.println((i+1) + ANSWER_NUMBER_SPLITTER
  77. + answerList[i]);
  78. }
  79. } else {
  80. // Out error message if data in memcachedb is corrupt.
  81. System.out.println(DATA_IS_CORRUPT_MESSAGE);
  82. break;
  83. }
  84. } else {
  85. // Get true answer
  86. String trueAnswer = (String) client.get(TASK_TRUE_ANSWER
  87. + currentTaskId);
  88. if ((trueAnswer != null) && (trueAnswer.equals(msg))) {
  89. // Out congratulation message if answer is true.
  90. System.out.println(CONGRATULATION_MESSAGE);
  91. } else {
  92. // Out bad message if answer is bad.
  93. System.out.println(BAD_ANSWER);
  94. }
  95. }
  96. }
  97. // Shutdown client
  98. client.shutdown();
  99. }
  100. private static void fillMemcachedbOfTask() {
  101. // Hardcode firs task
  102. // Set task question
  103. client.set(TASK_QUESTION + 1, EXPIRED, "What is your name?");
  104. // Set task answers
  105. client.set(TASK_ANSWERS + 1, EXPIRED, "Aleksei,Petia,Katia,Sveta");
  106. // Set true task
  107. client.set(TASK_TRUE_ANSWER + 1, EXPIRED, "Aleksei");
  108. // Hardcode second task
  109. // Set task question
  110. client.set(TASK_QUESTION + 2, EXPIRED, "Do you speak english?");
  111. // Set task answers
  112. client.set(TASK_ANSWERS + 2, EXPIRED, "yes,no");
  113. // Set true task
  114. client.set(TASK_TRUE_ANSWER + 2, EXPIRED, "yes");
  115. // Hardcode task sequence
  116. client.set(TASK_SEQUENCE, EXPIRED, 2);
  117. }
  118. }
Ну вот вроде и все, ничего сложного казалось бы нет. Выше приведенный код демонстрирует основные операции для работы с memcachedb. НО! есть одно НО! это работа с memcachedb в многопоточной среде. Простейшая операция увеличения sequence для получения id новой записи, реализованная следующим образом:
  1. int nextTaskId = (Integer) client.get(TASK_SEQUENCE);
  2. nextTaskId++;
  3. client.set(TASK_SEQUENCE, EXPIRED, nextTaskId);
может привести к коллизии.
Для того чтобы таких ситуаций не возникало существют incr/decr, инкримент и дикримент соответственно. Они увеличивают/уменьшают значение ключа и возвращают результат.
Что ж я вроде сказал все что хотел сказать.
Надеюсь мой небольшой очерк вам поможет...
Всем спасибо!

Интересные ссылки по теме:
Твиттер на основе Memcachedb и PHP
memcached на пальцах

Читать далее