вторник, 24 декабря 2013 г.

Форматы файлов для хранения ключей/сертификатов

И так повторим теорию шифрования открытыми ключами:
Генерируется приватный ключ, который хранится в защищенном месте, на основе его генерируется публичный ключ, который предоставляется тем, кто хочет передавать сообщения автору и быть уверенным в том, что никто не сможет его прочитать кроме автора. Все что закодировано публичным ключем, может быть раскодированно только приватным.
Чтобы пользователь публичного ключа был действительно уверенным, что у него оказался ключ не злоумышленника, придумали сертификаты открытых ключей. Суть в том, что третье лицо "аля власть в сертификации открытыми ключами" CA под каждый публичный ключ вставляет свою цифровую подпись, которая имеет ограниченное время жизни, и его ответсвенность в том, чтобы гарантировать, что тот кто представляется собой в сертификате, действительно яляется собою и публичный ключ, которых хранится в этом сертификате действительно его.
Формат файла для сертификата и процедуру распределения открытых ключей с помошью сертификатов с цифровыми подписями определяется стандартом X.509.
Формат файла сертификата по стандарту 
X.509:
• Номер версии(текущая 3)
• Серийный номер
• Эмитент
• Субъект
• Открытый ключ субъекта (алгоритм, ключ)
• Период действия
• Дополнительные (необязательные) значения
• Алгоритм подписи сертификата
• Значение подписи сертификата

(*.p12) Personal Information Exchange (PKCS #12)
Файл, который является безопасным(кодирование + пароль на розархивирование/чтение) хранилищем(архивом) для приватных ключей, сертификатов,  и цепочек сертификатов.
Это единственный формат, который может быть использован для експортирования сертификата и его приватного ключа в java keystore(jks)/truststore(jts).

(*.p7b) Cryptographic Message Syntax Standard (PKCS #7)
Используется как хранилище для цепочек сертификатов.

(*.cer | *.der) DER-encoded binary X.509
Формат хранилища сертификатов в бинарном виде, который является стандартом для Internet. Он не для приватных ключей, ни для цепочек.
(*.der) Distinguished Encoding Rules


(*.cer | *.pem) Base64-encoded X.509
Используется для тех же целей, что и предыдущий, но способ хранения данных в файле отличается (похоже занимает больше места на диске, потому что не бинарный а текстовый).
(*.pem) Privacy Enhanced Email
Файл в котором хранятся ключи/сертификаты в обычном текстовом формате. Его конек в том, что данные могут оттуда и туда копироваться как в обычный текстовый файл через GUI операционных систем. Только вот нужно следить чтобы в отметках начала и конца(-----BEGIN ENCRYPTED PRIVATE KEY----- и -----END ENCRYPTED PRIVATE KEY-----) не терять "минусы". И если мы это делали в Windows, то в файле нужно будет поудалять возрврат каретки. Тоесть в файл можно позгружать и всю цепочку сертификатов, ключи и приватные и публичные, но обычно так никто не делает, их разбивают на отдельные файлы, особенно приватный ключ находится в отдельном файле.

(*.crt) альтернативное имя расширения *.cer, как для бинарного, так и аски-формата,  этот вариант более характерен для *nix мира, а cer соответсвует Microsoft Convention.

(*.csr) Certificate Signing Request
Файл, в который генерируется на основе [только что созданного] приватного ключа публичный ключ и добавляется информации о авторе этого сертификата. В файле оказывается только что сгенерированный публичный ключ автора и информация о нем. Этот файл отправляется на подпись к certificate-authorities(CA), который своей подписью под сертификатом гарантирует, что автор является действительно тем, кем представляется в сертификате, CA из этого файла генерирует сертификат в формате X.509.


(*.key) PKCS#8
Чеще всего в таком файле хранятся приватные ключи. Но также могут храниться и публичные.  Закодированы они могут быть как в формате pem, так и der.

Существует 4 основых манипуляции над сертификатами:
- Просмотр.
- Преобразование.
- Соединение.
- Извлечение.

Чтобы просмотеть содержимое сертификата будь то der или pem, оба нужно декодировать в человекочитаемый вид.
Прочитать PEM:
openssl x509 -in cert.pem -text -noout
openssl x509 -in cert.cer -text -noout
openssl x509 -in cert.crt -text -noout

Прочитать DER:
openssl x509 -in certificate.der -inform der -text -noout

Чтобы преобразовать один формат в другой мы используем команды.
PEM to DER:
openssl x509 -in cert.crt -outform der -out cert.der
DER to PEM:
openssl x509 -in cert.crt -inform der -outform pem -out cert.pem

Соединение
Сервера например Apache требуют пару приватного и публичного ключа в одном файле. Также в один файл могут положить и ключи и полную цепочку. Самый простой способ создать такой общий файл это сохранить все в формате PEM, а потом просто скопировать контент каждого файла в один.

Извлечение
Нам прислали файл с цепочкой и ключами, но нам нужет только ключ, если обьединили PEMы, то тогда это просто: открыли, нашли по коментариям-отметкам и скопировали только то, что нам нужно.

понедельник, 23 декабря 2013 г.

Как проверить сертификат, который в jks

Нужно его импортировать в формат, в котором его принимает браузер, и отсправить эту генерацию вместе с запросом curl к ресурсу.
Для этого нам нужно:
1) Ипортировать сертификат в формат pkcs12 из jks.
2) Трансформировать pkcs12 в pem
3) Попытаться получить по curl ответ с сервера с полученным сертификатом.

$ keytool -importkeystore -srckeystore foo.jks \
   -destkeystore foo.p12 \
   -srcalias foo \
   -srcstoretype jks \
   -deststoretype pkcs12

$ openssl pkcs12 -in foo.p12 -out foo.pem

$ curl --cert foo.pem:password https://www.example.com/some_protected_page

Чтобы проверить по хешам тот ли у нас ключ, нужно сравнить аутпуты из двох команд:
$ keytool -keystore foo.jks -exportcert -alias foo | \
   openssl x509 -inform der -text

$ openssl x509 -text -in foo.pem


Есть еще вызов, только что это за формат не понятно, нужно разбираться:
$ openssl dsa -text -in foo.pem

Открыть порт в линукс файерволе

$ iptables -A INPUT -p tcp --dport 25 -j ACCEPT
$ iptables -I OUTPUT -p tcp --dport 25 -j ACCEPT
$ service iptables save
$ service iptables restart

четверг, 12 декабря 2013 г.

Основные комманды keytool

У нас есть кисторы - это хранилище с нашими ключами, которые мы предоставляем наружу, и трастсторы - хранилища ключей, которым мы доверяем (удаленные сервера предоставляющие нам такие ключи с максимальной вероятностью те, кем себя представляют).

Проперти JVM, которые используются для информации о ключах:
javax.net.ssl.keyStore
javax.net.ssl.keyStorePassword

javax.net.ssl.trustStore
javax.net.ssl.trustStorePassword

Не факт, но вроде как кисторы с расширением .pem(вроде как кодировка здесь rsa) используются openssl, p12 - всяким другим в том числе и JSSE

Если нам нужно понять тот у нас сертификат или нет мы, можем посмотерть по его алиасу в нашем кисторе с каким хешом он хранится(одинаковый хеш=одинаковые сертификат и ключ)
keytool -list -keystore path/to/my.keystore

Чтобы узнать кчюча время жизни, нам нужно посмотреть на кистор в вербоус моде:
keytool -list -keystore path/to/my.keystore -v

Импортировать ключи&сертификаты, которые соединены в формат PKCS12:
keytool -importkeystore 
        -destkeystore my.keystore -destalias myalias_in_mykeystore
        -srckeystore someout.p12 -srcstoretype PKCS12 -srcalias their_alias

Если пароль ключа из p12 будет отличается от пароля jks( джава кистора ), то такой сертификат не будет работать, поэтому, поэтому пароль нужно сменить при импорте, делается это вот так:

keytool -importkeystore 
        -destkeystore my.keystore -destalias myalias_in_mykeystore
        -srckeystore someout.p12 -srcstoretype PKCS12 -srcalias their_alias
keytool -importkeystore 
        -srckeystore their.p12 -srcalias their_alias 
        -destkeystore my.jks -destalias my_alias -srcstoretype PKCS12 -destkeypass MY_JKS_PASS_FOR_NEW_KEY
Дальще мы введем пароль нашего хранилища и хранилища p12 и готово.

 Преобразовать сертификат и ключ к нему в один файл формата pkcs12:
openssl pkcs12 -export 
               -in certificate.cer -inkey the_key.key 
               -out combined_result.p12 -name my_alias -CAfile this_file_is_never_generate.crt

Удалить сертификат и ключ по алиасу:
keytool -delete -alias delete_me -keystore my.jks


Добавить серификаты удаленного сервера в наш трастстор:
keytool -import -file SOMECER.CER -alias NAME_FOR_OUR_STORE -keystore MYKEYSTORE.JKS –storepass CHANGING_TO_BE_THE_SAME_AS_FOR_KEYSTORE

Иногда бывает нужно переименовать алиас в кисторе:

keytool -changealias -alias OLD_ALIAS -destalias NEW_ALIAS -keystore MYKEYSTORE.jks

понедельник, 2 декабря 2013 г.

Добабить удаленный репозиторий и в одном месте залить туда бранч, в другом - слить

Добавить и залить:
git remote add github https://github.com/user/repo.git
git push -u github my-release

А в другом месте добаить и взять залитое:
git remote add github https://github.com/user/repo.git
git fetch github

git checkout -b my-release github/my-release
Теперь мы отдельно можем работать либо с ORIGIN либо с GITHUB ремоутом.

воскресенье, 1 декабря 2013 г.

Интсрукция настройки репликации на mysql

1) master my.cnf(my.ini )
[mysqld]
log-bin=mysql-bin
server-id=1

innodb_flush_log_at_trx_commit=1
sync_binlog=1

# skip-networking
# bind-address          = 127.0.0.1 # разрешаем конектиться не только с локального хоста

service mysql restart
2) slave my.cnf(my.ini ):
[mysqld]
server-id=2

четверг, 28 ноября 2013 г.

lsof

Утилита, которая показывает поточные открытые файлы. Можно применять фильтры по юзерах и по местах их дислокации

http://handynotes.ru/2010/01/unix-utility-lsof.html

среда, 27 ноября 2013 г.

Логи в MySQL

Есть пять видов логов:
Log TypeInformation Written to Log
Error logProblems encountered starting, running, or stopping mysqld
General query logEstablished client connections and statements received from clients. Тоесть сдесь логируется все что запрашивается у mysqld, все запросы, а не только те, которые изменяют состояние базы, как в Binary log.
Binary logStatements that change data (also used for replication). Риплика тоже может писать эти логи, если она находится в составе сложной цепочки реплик, и является мастером для другой реплики.
Relay logData changes received from a replication master server
Slow query logQueries that took more than long_query_time seconds to exe

Сайт с поддерживаемыми User Defined Function for MySQL

http://www.mysqludf.org/

но лог не получилось например сбилдить, чтобы установить...

вторник, 26 ноября 2013 г.

четверг, 21 ноября 2013 г.

Как из явавского хранилища ключей получить файлы сертификата и ключа для curl

Для начала нам нужно перефести формат ключей из jks в pkcs12. Также если у нас в хранилище несколько ключей нужно указать алис ключа, который и будет сохранен в другом формате
keytool -importkeystore -srckeystore jvmkeystore.jks \
   -destkeystore somesite_key_and_cert.p12 \
   -srcalias keycert_alias_in_keystore \
   -srcstoretype jks \
   -deststoretype pkcs12

Теперь нам нужно получить отдельно файл ключа и файл сертификата чтобы передать их в curl
openssl pkcs12 \
  -in somesite_key_and_cert.p12 \
  -out somesite_key.pem -nocerts
openssl pkcs12 \
  -in somesite_key_and_cert.p12 \
  -out somesite_cert.pem -clcerts -nokeys

Теперь обращаемся по curl к интересуещему нас сайту по SSL(https)
curl -vvv --cert somesite_cert.pem \
  --key somesite_key.pem \
  "https://somesite.com:443/intr/source"



Наверно бывают случаи когда нам нужно, чтобы ключ и сертификат были в отдельних файлах, но если нам это не нужно мы можем сделать все за меньшее количество шагов и введенного текста:
openssl pkcs12 \
  -in somesite_key_and_cert.p12 \
  -out somesite_key_and_cert.pem -clcerts
И обращение:
curl -vvv --cert somesite_cert.pem \
  "https://somesite.com:443/intr/source"

javax.net.ssl

SSL properties are set at the JVM level via system properties. Meaning you can either set them when you run the program (java -D....) Or you can set them in code by doing System.setProperty.
The specific keys you have to set are below:
javax.net.ssl.keyStore- Location of the Java keystore file containing an application process's own certificate and private key. On Windows, the specified pathname must use forward slashes, /, in place of backslashes.
javax.net.ssl.keyStorePassword - Password to access the private key from the keystore file specified by javax.net.ssl.keyStore. This password is used twice: To unlock the keystore file (store password), and To decrypt the private key stored in the keystore (key password).
javax.net.ssl.trustStore - Location of the Java keystore file containing the collection of CA certificates trusted by this application process (trust store). On Windows, the specified pathname must use forward slashes, /, in place of backslashes, \.
If a trust store location is not specified using this property, the SunJSSE implementation searches for and uses a keystore file in the following locations (in order):
  1. $JAVA_HOME/lib/security/jssecacerts
  2. $JAVA_HOME/lib/security/cacerts
javax.net.ssl.trustStorePassword - Password to unlock the keystore file (store password) specified by javax.net.ssl.trustStore.
javax.net.ssl.trustStoreType - (Optional) For Java keystore file format, this property has the value jks (or JKS). You do not normally specify this property, because its default value is already jks. javax.net.debug To switch on logging for the SSL/TLS layer, set this property to ssl.

Склонировать конкретную бранчу

git clone user@git-server:project_name.git -b branch_name /some/folder

как не вводить длинный пароль рута для mysql

 mysqldump -uroot -p`grep -m1 "^password=" /root/.my.cnf | cut -d= -f2`  mydbname > mydump.sql


grep:
-m - сколько первых совпадений выводить

cut:
-d - какую строку/символ считать разграничителем между колонками
-f - какую колонку выводить

вторник, 19 ноября 2013 г.

Создание приложения сразу со всеми зависимостями

Когда мы мавеном создаем и запускаем приложения, то на выходе мы получаем jar только с кодом проекта, но без зависимостей. Зависимости находятся в локальном репозитории, и уже мавен, когда мы запускаем приложение с помощью его, ссылается в класспазе на джарники из локального репозитория.
Если мы хотим поставить джарник, которому нужна будет только jvm для работы ( все зависимости будут поставляться с ним), мы делаем следующее:
1) Настраиваем плагин ассембли.
<project>
    [...]
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
            </plugin>
        </plugins>
    </build>
    [...]
</project>


2) Вызываем и получаем джарник с зависимостями
$ mvn install assembly:assembly

Полезные плагины мавен help и dependency

Плагин help
Вот так можно получить информацию о плагине и как им пользоваться
$ mvn help:describe -Dplugin=exec -Dfull



Плагин dependency
Чтобы узнать что же у нас попадает в класспаз для запуска нашего проекта:
$ mvn dependency:resolve


Если нужно видеть, от чего мы зависим на праямую, а что подтянули прямые зависимости:
$ mvn dependency:tree


Если нужно еще и увидеть какие артефакты были отвергнуты по причине конфликтов или по другим причинам, то нужно запустить мавен с флагом дебага
$ mvn install -X



четверг, 14 ноября 2013 г.

Screen. Что еще такого узнал

-p  -- если несколько табов, то выбрать указанный
-X stuff "some commands" -- чтобы выполнить какие-то комманды сразу


sudo su -c 'screen -r -x bingo-jenkins -p bash -X stuff "cd ~/liferay-plugins; git reset --hard; git pull;git checkout $branchname; git pull;ant stop-portal-force all-new start-portal -Ddeployer.names=Jenkins
"'
Перенос строки обязательно, потому что в терминал вводится текст.

Как активировать CDI в архиве, который предоставляется контейнеру?

1) Необходимо, чтобы контейнер поддерживал CDI.
2) Для этого достаточно добавить beans.xml в META-INF директорию архива, при этом хмл может быть даже пустым.

пятница, 1 ноября 2013 г.

Portlet @ActionMapping

Когда же нужно пользоваться параметром аннотации value, а когда params?

 Этот вариант для фанатов строгого соотвествия спецификации:
@ActionMapping(value = "addDocOrder")
public void addDocOrder(@ModelAttribute("order").......
Your request should URL should be built like:
<portlet:actionURL>
  <portlet:param name="javax.portlet.action" value="addDocOrder"/>
</portlet:actionURL>

Этот для экономных в байтах по сети
@ActionMapping(params = "action=addDocOrder")
public void addDocOrder(@ModelAttribute("order").......
Your request should URL should be built like:
<portlet:actionURL>
  <portlet:param name="action" value="addDocOrder"/>
</portlet:actionURL>

среда, 30 октября 2013 г.

LESS - системная переменная для less

$ export LESS='-i-P%f (%i/%m) Line%lt/%L'
-i - ignore case -P - use promt Все остальное это формат и контент подсказки в нашем случае: [имя поточного файла] ([номер поточного файла]/[количество всего файлов подошедших под маску] Line[номер поточной строки]/[всего строк в поточном файле]

И снова find


Выполнение какой-нибудь команды на каждую строку результата поиска (найденного места(пути к файлу/директории))
find [path/to/dig/into] -exec [command] [command_params] {} \;
{}


Интересные примеры:
# Найти файлы проекта с указанной строкой
find . -exec grep "string_to_find_in_next_path" {} \;

# Вывести список всех директорий проекта
find my_prjdir_in_cur_dir -type d

# Удалить все файлы и директории с именем .svn в директории проекта
find my_prjdir_in_cur_dir "-name" .svn -exec rm -rf "{}" \;

# Найти файлы проекта с указанной строкой и при этом вывести не только строку в файле, но и путь к файлу
find my_prjdir_in_cur_dir  -exec grep --with-filename "string_to_find_in_next_path" {} \;

# Вывести в консоль содержимое файлов; -print это ключ для find
# именно он выведет не только в стандартный аутпут, но и в еррор поток пути к найденным файлам,
# так find выводит в консоль путь к файлу, а cat за каждым путем содержимое файла
find my_prjdir_in_cur_dir -type f -print  -exec cat {} \;


вторник, 29 октября 2013 г.

Правила приорите символов в Scala

Precedence Rules
The precedence of an operator is determined by its first character.
The following table lists the characters in increasing order of priority
precedence:
(all letters)
|
^
&
< >
= !
:
+ -
* / %
(all other special characters)

Поэтому a + b ^? c ?^ d less a ==> b | c

 ((a + b) ^? (c ?^ d)) less ((a ==> b) | c) 

Scala Syntax Summary

Types

Type               =  SimpleType | FunctionType
FunctionType  =  SimpleType ‘= > ’ Type
                       | ‘( ’ [ Types ] ‘) ’ ‘= > ’ Type
SimpleType     =  Ident
Types              =  Type { ‘ , ’ Type }

Расширенная форма записи Бекуса-Наура для представления синтаксиса

Extended Backus-Naur form (EBNF):

| denotes an alternative,
[...] an option (0 or 1),
{...} a repetition (0 or more)

Начало проекта с мавеном

$ mvn archetype:generate
Выбириаем пустой проект, например, который по умолчанию.
Вводим код групы, проекта, выбираем имя проета и версию.

Чтобы запустить, то что у нас получилось
 
$ mvn compile exec:java -Dexec.mainClass="com.pathto.App"
Здесь мы пользуемся услугой плагина Exec(Mojo project) для запуска конкретного класса с методом мейн, кроме того этот плагин умеет передавать аргументы в этот класс через аргемент плагина Exec -Dexec.args.

понедельник, 28 октября 2013 г.

Удаление бинарных логов mysql

В этих логах логируются все запросы в базу.
Кстати они тоже испльзоуются репликами для применения у себя тех же изменений.
Чтобы их коректно удалить нужно в шеле mysql:
purge binary logs before '2013-06-01 00:00:00';


Замена через Vim

Vi: Search and Replace

Change to normal mode with .
Search (Wrapped around at end of file):
  Search STRING forward :   / STRING.
  Search STRING backward:   ? STRING.

  Repeat search:   n
  Repeat search in opposite direction:   (SHIFT-n)

Replace: Same as with sed, Replace OLD with NEW:

 First occurrence on current line:      :s/OLD/NEW
  
 Globally (all) on current line:        :s/OLD/NEW/g 

 Between two lines #,#:                 :#,#s/OLD/NEW/g
  
 Every occurrence in file:              :%s/OLD/NEW/g 

пятница, 25 октября 2013 г.

logrotate

Утилита для ротации логов, работает не как сервис, а обслуживается кноном.
У него есть настройки в
/etc/logrotate.config -- они общие для всех ротированей
Есть также директория
/etc/logrotate.d/ - в нее записываются настройки для конкретных ротированей.

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


# cd /etc/logrotate.d/
# logrotate --force name_of_rot_cnfgs

вторник, 22 октября 2013 г.

High Order Functions

Functions - first-class values. Тоесть в функциоанльных языках мы можем передавать функции как простых/сложных значений в методы и функции.

High Order Functions - функции, которые получают другие функции в параметрах, и/или возвращают функции в своих результатах.

Function type - тип, который определяет, что в параметр будет передаваться функция.
A => B
(A,B...X) => Z
A,B...Z - some types


Currying - название происходит от имени ученого, который это придумал впервые.
Это процесс, который позволяет вводить часть параметров сейчас, а остальные потом, что по факту означает создает функцией функцию.
def sum(f: Int=>Int): (a: Int, b: Int) => Int

В Scala есть сахар этого
def sum(f: Int=>Int)(a: Int, b: Int): Int

Anonynous function syntax: по принципу функционального типа
(x1: T1, ..., xn: Tn) => E


воскресенье, 20 октября 2013 г.

Blocks and Lexical Scopes in Scala

Блок:
- ограничивается фигурными скобками {...};
- является наборов определений и выражений;
- последний элемент в блоке и будет результатом блока;
- сам по себе блок является выражением;
- блок определяет область видимости определений(констант и переменных), созданных внутри его.


Lexical Scope:
пространство видимости, которое определяет граници видимости опредения - определение видимо в блоке, в котором оно было определено, а также во вложенных блоках. Опредения в отцовских блоков, перекрываются локальными определениями поточного блока с теми же самыми именами, и отцовсткие не изменяются в поточном и во вложенных блоках.

Expressions and statement

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

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

четверг, 26 сентября 2013 г.

Substitution Model

 Элементы програмирования

Любой нетривиальный язык программирования имеет:
1) элементарные выражения, представляющие наиболее простые элементы.
2) способы комбинирования первых.
3) механизм для абстрагирования сложных и комбинированных выражений под одним именем.

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

В функциональном программировании есть две стратегии выполнения(Evaluation Strategy)
1) Call By Value
2) Call By Name

Каждая из стратегий выгодна в разных конкретных случаях. Но чаще всего Scala используется СBV, в большинстве случаев этого оправдано.

Но когда в случае

def someOperation(x: Int, y: Int): Int = 1

someOperation(1+2, loop)

Мы зациклимся на втором шаге. Но если второму параметру применить стратегию оценки  СBN, то міы спокойно пройдем программу

Чтобы сменить дефолтовую стратегию на  СBN,  нужно интересуемый параметр объявить:
x: Int -  СBV
x:=> Int -  СBN


Поэтому предыдущее объявленеи нужно подредактировать:
def someOperation(x: Int, y: => Int): Int = 1

someOperation(1+2, loop)// так бесконечного цикла не будет
В зависимости от реализации функции может быть более выгодной та или иная стратегия.

суббота, 21 сентября 2013 г.

Как работает внутри Spring Web Portlet

Перед нашими контроллерами происходит следующее:
0. Первое с чего все начинается это идет вызов одного из методов FrameworkPortlet (обращение вообщето идет в DispatcherPortlet, который расширяет первый, но реализация методов находится в его родителе), в зависимости от фазы портлетного запроса.
// Delegate action requests to processRequest/doActionService.
void processAction(ActionRequest req, ActionResponse resp){..}
// Delegate render requests to processRequest/doRenderService.
void doDispatch(RenderRequest req, RenderResponse resp){...}
void serveResource(ResourceRequest request, ResourceResponse response){...}
void processEvent(EventRequest request, EventResponse response){...}

но все они делают в нутри одно и тоже
{
   processRequest(req, resp);

}

1. org.springframework.web.portlet.DispatcherPortlet extends FrameworkPortlet
  void processRequest(req, resp) //in FrameworkPortlet

         //Получается фаза жизненного цикла портлетного запроса
         String phase = (String) req.getAttribute(PortletRequest.LIFECYCLE_PHASE);

         //на основании фазы выбирается в условиях подходящий обработчик,
         //что является немного странным для меня - зачем все перенаправлять в один
         // метод, чтобы потом снова разделять? - например
         if (PortletRequest.ACTION_PHASE.equals(phase)) {
   doActionService((ActionRequest) request, (ActionResponse) response);
}


        // в конце метода не зависимо от успеха, запускается событие что портлетный запрос обработан
        this.portletApplicationContext.publishEvent(
new PortletRequestHandledEvent(this,
getPortletConfig().getPortletName(),
                                                                request.getPortletMode().toString(),
(request instanceof ActionRequest ? "action" : "render"),
request.getRequestedSessionId(),
                                                                getUsernameForRequest(request),
processingTime, failureCause));   


2. org.springframework.web.portlet.DispatcherPortlet
    void doActionService(req, resp)
            HandlerExecutionChain mappedHandler; //получает инстанцию НашКлассКонтроллера
            mappedHandler = getHandler(req);

            //определяет что за обработчик у нас, выбирая из двух типов либо контроллер у нас расширяет спринговый контроллер, либо помечен аннотациями
            HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
     
            //например у нас ha instanceof
            //org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter
            //handleAction потому что у нас фаза Action,
            //который внутри делает то, что вызывает ModelAndView doHandle(req, resp, handler),
            //проверяет чтобы результат обязательно был null потомучто это фаза Action
            ha.handleAction(req, resp, mappedHandler.getHandler());
                          

вторник, 10 сентября 2013 г.

Как получить вебконтент

В Java:
String xmlRequest = PortletRequestUtil.toXML(request, response);

ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);
JournalArticleDisplay articleDisplay = JournalContentUtil.getDisplay(
            themeDisplay.getLayout().getGroupId(),
            articleIdStr,
            null,
            themeDisplay.getLanguageId(),
            xmlRequest);
articleDisplay.getContent();

В JSP:
<%@ page import="com.liferay.portal.kernel.util.WebKeys" %>
<%@ page import="com.liferay.portal.theme.ThemeDisplay" %>

<liferay-ui:journal-article articleId="${articleId}"
                                                groupId="<%= ((ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY)).getPortletGroupId() %>"/>
                

пятница, 6 сентября 2013 г.

jMockit. State-based testing and Fakes

Один из двух подходов jMockit
Построено на реализации:
State-based testing не фокусируется на взаимодействии между тестируемым классом/юнитом и его зависимостями, а -- на саммих данных которыми обмениваются обьекты. Тесты пишутся не из перспективы теструемого класса, а с перспективы используемых классов, и не важно юнит это или депенденси. Главное в этим виде тесрирования сделать сверку в конце тестового метода, чтобы наши предположения совпали.

Понятия фейков характерны для интеграционного тестирования, где мы вяжемся на какието внешние сервисы, где мы их имитируем и не зависим от их текущего состояния.

Static Initializer Block

Блок загрженного в JVM класса, который вызывается только один раз до вызова конструктора класса или его метода мейн. Тоесть если мы создаем инстанцию класса, то только в этот момент будет вызван этот блок, все последующие создания обьектов уже этот блок вызывать не будут, таже история с методом мейн.

Правила:

  1. Код пишется в блоке static { }, который ставится в пределах класса.
  2. Блок ничего не возвращает - return.
  3. Никаких обращений к инстанции - this, super.
  4. Может выкидывать только  Unchecked Exceptions( инстанции классов RuntimeException, Error и их наследники).

Используется это для:

  1. Загрузка драйверов и другого в пространство имен (For example ‘Class.forName(“com.mysql.jdbc.Driver”)’).
  2. Проинициализировать сложные статические поля класса один раз(final static).
  3. Логирование.
  4. Создание и распарсивание подготовленных SQL-выражений. 

 
class Loader {
    static final String theName = "The Loader";
    static {
        System.out.println("Loader.static");
    }
    Loader() {
        System.out.println("Loader.Loader()");
    }
}


class Test extends Loader {
 final static Integer i;
 
    static {     
        System.out.println( "Test.static");
        i = new Integer(5);
    }
    
    {
     System.out.println( "Test.non-static");
    }
    
    Test() {
        System.out.println( "Test.Test()");
    }
    public static void main( String [] args ) {
        System.out.println( "Test.main");
        Test t = new Test();
        Test t2 = new Test();
        Test t3 = new Test();
        System.exit(0);
    }
}
Loader.static
Test.static
Test.main
Loader.Loader()
Test.non-static
Test.Test()
Loader.Loader()
Test.non-static
Test.Test()
Loader.Loader()
Test.non-static
Test.Test()

Java создание инстанций из классов Java

Если мы наследуем какой-то класс, то при создании нашего обьекта, если мы явно не вызываем определенный конструктор super([..]); будут вызваны все конструкторы без параметров вверх по цепочке (созданы инстанции каждого предка, чтобы мочь вызывать его методы и пользоваться полями - получается такой класстер инстанций, который воспринимается как одна).
Если у нашего предка, есть контруктор с параметрами и мы при определение наследника не вызываем супером конструктор отца, то компилятор выдаст ошибку - он не знает как создавать инстанцию предка - нужно либо явно вызывать существующий конструтор, либо определить отцовскому классу конструктор без параметров.

вторник, 3 сентября 2013 г.

Разработка ПО: факты против мифов

Вот наиболее распространенные мифы и факты, которые их опровергают.

Миф #1. Разработку ПО можно ускорить
Девять беременных женщин не родят ребенка за месяц. Добавление людей в отстающий проект только увеличит отставание. (Брукс)

Существует оптимальное, с точки зрения затрат, время выполнения графика для первой поставки. ВРЕМЯ [мес.] = 2,5 (ТРУДОЕМКОСТЬ [чел.* мес.])^1/3. Кривая стоимости резко растет, если запланированный график короче оптимального. Практически ни один проект невозможно завершить быстрее, чем за 3/4 расчетного оптимального графика вне зависимости от количества занятых в нем людей. (Барри Боэм

Наиболее эффективно программисты работают без жестких сроков. Сверхурочные и авралы снижают общую производительность. (Демарко)

Миф #2. Проблемы разработки ПО можно решить при помощи инструментов и процессов
Применение новых инструментов снижают производительность, но если повезет, может ее повысить на 2-20% (Гласс)

Существуют десятки методологий, но ни одна не гарантирует результат. Коуберн не обнаружил корреляции между успехом/провалом проектов и методологиями, которые применялись в проектах, будь то процессы, сертифицированные по CMMI Level 5 или процессы, построенные по принципу «как получится». Его вывод. Успешность программного проекта на 100% определяется людьми.

Миф #3. Разрабатывать ПО просто
Много лет только 1/3 проектов укладывается в треугольник: качество-стоимость-срок (Standish Group). Отраслевой прирост производительности составляет 3-5% в год (Демарко). Производительность программистов с похожим стажем и опытом могут отличаться в 10 раз (Брукс) или даже в 28 раз (Гласс).

Миф #4. Железный треугольник проекта
Разработка продукта длилась 5 лет вместо одного года. Бюджет проекта был превышен более чем в 5 раз. Это — провал? Нет — это был Microsoft Word!

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

Миф #5. Работу программистов нельзя измерить
Нельзя измерить работу отдельного программиста. Что будем мерить, то и получим. Но надо измерять работу проектной команды. Обязательно.
  • Процент протестированных вариантов использования.
  • Средняя производительность, SLOC в день на каждого участника проектной команды.
  • Дефектность продукта, bugs/KSLOC.
  • Качество архитектуры. Предлагаю читателям самим указать единицу измерения, в качестве упражнения.


Миф #6. Программисты анти-бюрократичны
Программисты – анти-идиотичны. Программисты сторонятся тех, кто усложняет их работу. Программисты самоорганизуются вокруг тех, кто облегчает их работу.

Миф #7. Программисты работают ради денег
Нет. Не ради денег. Но за деньги. Почувствуйте разницу.

Программист устроен просто. Он состоит из четырех компонентов: тело, сердце, разум и душа. Телу необходимы деньги и безопасность. Сердцу — любовь и признание. Разуму – развитие и самосовершенствование. Душе – самореализация.

Дайте все это вашим программистам, и вы получите максимальную эффективность. Что-то не найдете — уйдут к вашим конкурентам.

Источник: http://habrahabr.ru/post/192396/

четверг, 29 августа 2013 г.

Apply-method и Object

class FooMaker {
  def apply() = new Foo
} 

val new Foo = FooMaker() // вызов apply-метода
 
//--------------------------------
  
class Bar {
  def apply() = 0
}
val bar = new Bar
bar() // = 0

Как видно apply-метод вызывается как на классе так и интстанциях этого класса.

В scala есть понятие Object, он позволяет иметь только одну инстанцию этого класса, мы определяем получается сразу обьект, а не класс. Чаще всего это используется для фабрик. Вот пример широкораспространенной конструкци в scala :
class Bar(foo: String)

object Bar {
  def apply(foo: String) = new Bar(foo)
}

val bar = Bar()

Но еще обьекты используются не только для этого, определив обьек в CLI мы увидем вывод:
object ColorHolder {...}
defined module ColorHoler
Слово module - означает, что за задумкой архитекторов языка, обьект является частью модульной системы scala.
Ведь наш файл с методом мейн всегда содержит обьект в котором и написан запускающий код нашего приложения.

Разница между abstract class и trait

Пример абстрактного класса
abstract class Shape {
  def getArea(): Int
}

trait - коллекция полей и функционала, которые можно расширять либо "вмешивать" в классы. Разница между abstract class и trait:
1) Множественное наследование - Traits
2) Возможность конструктора - Abstract Class.

Scala type aliasing

Любой сложный тип можно локально переопределить и придать ему более читабельный вид:
class ConcurrentPool[K, V] {
  type Queque = ConcurrentLinkedQueque[V]
  ...
}

среда, 28 августа 2013 г.

Function Composition

Это техника создания третьей функции, которая возврщает результат путем передачи результата одной функции в параметр другой.
Вот пример с использованием метода compose:
scala> def f(s: String) = "f(" + s + ")"
f: (String)java.lang.String

scala> def g(s: String) = "g(" + s + ")"
g: (String)java.lang.String

scala> val fComposeG = f _ compose g _
fComposeG: (String) => java.lang.String = <function>

scala> fComposeG("yay")
res0: java.lang.String = f(g(yay))

Есть еще другой метод, который применяет функции наоборот, andThen:
scala> val fAndThenG = f _ andThen g _
fAndThenG: (String) => java.lang.String = 

scala> fAndThenG("yay")
res1: java.lang.String = g(f(yay))

 

Незалогиненый пользователь не попадал в Spring Portlet Controller

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

четверг, 22 августа 2013 г.

Можно обращаться к портлетам

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

Вот по такому урлу я обращлся: "http://galacasino.local:8083/?p_p_lifecycle=0&p_p_state=exclusive&p_p_id=cashieriframe2_WAR_cashierportlet&_cashieriframe2_WAR_cashierportlet_conf=DEPOSIT&_cashieriframe2_WAR_cashierportlet_modal=true&_cashieriframe2_WAR_cashierportlet_tmp=1377171814918&t=1377171814918"

как видно идет обращение к варнику и к портлете но не к инстанции
 type: "GET",

вторник, 20 августа 2013 г.

Powershell решение проблемы редиректа входящего потока

Так сделать не получиться, потому что < зарезеривирован под другие вещи:
somescript < commands.txt


Для этого нужно делать ход конем:
Get-Content commands.txt | somescript 

четверг, 25 июля 2013 г.

Grunt

Grunt - javascript task runner. Утилита сборки для джаваскрипта, ака ant для Java.

Разделена на три разных node модуля:
1. grunt - модуль, который нужно устанавливать локально в проект $ npm i grunt. Именно в нем содержится код и логика, которые запускают таски, загружают плагины.
2. grunt-cli - модуль, который устанавливается глобально $ npm i -g grunt, его задача состоит в том, чтобы мы могли выполнить таск в любом месте проекта - он просто подымается по каталогу вверх и находит установленный grunt в папке node_modules и запускает его.
3. grunt-init - модуль, который также нужно установить глобально $ npm i -g grunt-init / Это утилита "строительные леса", которая вынесла таск init гранта в отдельный модуль, и позволяет пользуясь шаблонами, которые размещаются ~/.grunt-init/*(они устанавливаются тоже модулями npm как плагины гранта, но как-то попадают туда), создавать разные заготовки заготовки. Этот модуль планируется быть замененным модулем Yo(http://yeoman.io/).

вторник, 23 июля 2013 г.

git бранчевание

Список поточных бранчей:
git branch
Или с указанием также на каждый бранеч хеша его последнего комита (HEAD)
git branch -v

Создать новый бранч, из HEAD поточного и переключиться на него:
git branch new_branch_name
git checkout new_branch_name

# или вариант в одну строку
git checkout -b new_branch_name 

Создать новый бранч из указанного, а не поточного
git checkout -b new_branch_name existed_local_branch_name
git checkout -b new_branch_name remote_name/existed_remote_branch_name

Удалить безопасно бранч, гит удалит его только в тому случае, если мы сделали мердж в master
git checkout -d existed_branch_name

Если же мы реально осознали, что работа в указанном бранче реально не должна попасть ни в историю, ни в проект, тогда удаляем силой:
git checkout -D existed_branch_name

Переименовать поточный бранч:
git checkout -m new_name_for_curbranch


Все это делается для того, чтобы мы в конце концов сомогли сделать:
$ git checkout master 
$ git merge already_tested_branch
$ git branch -d already_tested_branch

После этого возможны два варинта событий:
- master:HEAD еще не успел продвинуться дальше, поэтому происходит Fast forward мердж, что означает, что у нас будет ровная история master:HEAD - как буд-то разработка так и велась в master, а не в отдельной ветке.
- уже успели накомитить в master:HEAD, поэтому происходит 3-Way Merge, и при необходимости мы будем решать конфликты, после этого история будет бугристая.

Чтобы было видно бранчевание даже в случае когда не успели накомитить в master, мы можем смерджить со следующим ключом:
$ git merge --no-ff already_tested_branch
$ git branch -d already_tested_branch

Чтобы без сюрпризов и у нас точно не было ненужного ветвеления можем указать так(чаще всего это нужно если мы до этого уже делали --no-ff, или ставили ):
$ git merge --ff-only already_tested_branch

Есчли бранч был создан не только локально но и удаленно, то нужно его удалить удаленно тоже.
Нужно помнить, что когда мы пушим  мы неявно делаем следующее:
$ git push remote local_branch:remote_branch

Но если мы уже удалили локальную бранчу, то так мы сделать не можем потому что ее нет, поэтому мы удаляем удаленную таким образом:
$ git push remote_name :remote_branch
или же алиасом:
$ git push remote_name --delete remote_branch


Связать свою локальную бранчу с удаленной:
$ git branch --set-upstream mymaster origin/master

Варинаты undo

  • git checkout foo.txt
    • Undo local changes (like svn revert)
  • git reset HEAD foo.txt
    • Remove from staging area (local copy still modified).

воскресенье, 21 июля 2013 г.

media в каскадных таблицах стилей

@media - это css-правило, которое связывает группу вложенных выражений в блок, ограниченный скобками, применение в поточном устройстве которого определяется условием media query.

суббота, 20 июля 2013 г.

Принципиальная разница POST и GET запросов для NodeJs

На момент срабатывания колбека обратки запроса в http сервера, Get запрос полностью уже обработан, все  его данные полученные, потому что такой запрос приходит без тела, только с заголовками. А вот с Post другая история - когда колбек срабатывает, заголовки уже пришли, а вот боди, еще в пути, и обработать его в колбеке мы можем только подписавшись на событие потока Readable, который у нас представлен, его наследником http.InputMessage обьектом req.

Пример:
function(req, res) {
...........
 var body = '';
 req
    .on('readable', function() {
       body += req.read();

       if(body.length > 1e4) {
         res.statusCode = 413;
         res.end('Your messafe is too big for my little chat');
       }
     })
     .on('end', function() {
       try {
         body = JSON.parse(body);
       }catch(e) {
         res.statusCode = 400;
         res.end('Bad Request');
         return;
       }
         chat.publish(body.message);
         res.end('ok');
       });
}

пятница, 19 июля 2013 г.

Потоки записи в NodeJS

Потоки записи
Все потоки записи должны реализовывать абстрактный класс stream.Writable.
Данный класс имеет следующую событийную модель:


Можно заметить что stream.Writable имеет событие завершения finish, но stream.Readable имел end. Это для того чтобы обеспечить различие дуплексный поток, одновременный вывод и ввод.
Вот пример некоторых наследников данного класса

              stream.Writable
                 ^            ^
                  |             |
fs.WriteStream      http.ServerResponse
     
 Любой наследник гарантирует, что он предоставит событийную модель родителя. Можно заметить, что данная событийная модель не похожа на модель чтения.

Вот пояснение модели:
1. Мы пробуем записать часть наших данных, если данные записались из буфера сразу в место предназначения в ответ мы получаем тру, можем снова пытаться записать следующую часть.
2. Если же у нас данные из буфера не попали сразу в место предназначения, а стали ожидать своей очереди, то райт вернет фолс. Теперь мы подписуемся на событие потока drain(буфер отдренировался), вместо продолжать заполнять буфер, который рискует в таком случае переполниться, что означает для нас, что мы можем попытаться записать следующую часть, в момент когда, буфер слил все в место предназначения.
3. Когда мы заносим последний чанк данных это следует делать местодм end(...)


Дальше приведем пример, файлового сервера, проблемой для которого является считывание за один раз громадного файла в память, или обслуживание довольно большого количества клиентов с медленным соединением, который не очень быстро принимают передаваемые байты. Все эти варианты заставляют нас рисковать переполнить память нашего сервера.
Поэтому нужно поступать хитрее:
function sendFile(filePath, res) {
    var mime = require('mime').lookup(filePath); // npm install mime

    var file = new fs.ReadStream(filePath);
    file.on('readable', write);

    function write() {
        var fileContent = file.read();

        if (fileContent && !res.write(fileContent)) {//если буфер записи сливается на клинет быстро, мы не попадем в if, а будем и дальше записывать по мере прочтения чанков
            file.removeListener('readable', write); // пока не очищать буфер чтения, его ведь некуда сливать, будем захламлять только память

            res.once('drain', function() {
                file.on('readable', write);
                write();
            });
        }
    }
    file.on('end', function(){//дочитали
        res.end();//значит закрываем соединение с клиентом, мы отправили все что должны были
    });
}

Но в ноде уже есть более оптимизированная реализация данного алгоритма, поэтому выше написанный код, можно заменить на более короткий и оптимальный:
function sendFile(filePath, res) {
    var mime = require('mime').lookup(filePath); // npm install mime

    var file = new fs.ReadStream(filePath);
    file.pipe(res);//pipe есть у всех Readable потоков
    file.pipe(process.stdout);//кроме того пайпить мы можем в любое количество потоков одновременно
    file.on('error', function(err) {
       res.statusCode = 500;
       res.end('Server Error');
       console.log(err)  
    });
    //если оставить код без кода написанного ниже в этом блоке,
    //то в моменты когда клиент будет обрывать соединение,
    // не дождавщись всего файла, у нас закроется соединение записи,
    // но файл чтения останется открытым, держа буферы и замыкания в памяти.
    // при нормальном завершении соедиения, ответ сгенерирует finish, который
    // нам приносит класс stream.Writable.
    res.on('close', function(){//срабатывае, когда соединение обрывают
        file.destroy();//обеспечиваем закрытие файла чтения, и всех контекстов из замыкания  
    });

Потоки чтения в NodeJS

Потоки чтения
Все потоки чтения должны реализовывать абстрактный класс stream.Readable.
Данный класс имеет следующую событийную модель:

Вот пример некоторых наследников данного класса

              stream.Readable
                 ^            ^
                  |             |
fs.ReadStream      http.IncomingMessage
       
 Любой наследник гарантирует, что он предоставит событийную модель родителя.

Module fs

Главные моменты:
1) Всегда нужно в методы у которых есть колбеки, вставлять проверку на ошибку, потому что потом мы просто не сможем понять почему у нас что-то не работает. Н-р:
var fs = require('fs');

fs.writeFile('myfile.txt', 'my string for file', function(err){
  if(err) throw err; //без этого будет сложно понять почему у нас что-то не так 
  ...
})

2) Node всегда выводит кроссплатформенные коды ошибок, но мы не всегда можем понять по названию суть проблемы, а документации этого нет. Но за то у нас есть доступ в серце тоды, в исходники libuv, вот ссылка на хед-файл, где описаны все ошибки:
https://github.com/joyent/libuv/blob/master/include/uv.h

четверг, 18 июля 2013 г.

Логирование в nodejs

Модуль debug
Простейшее логирование, позволяет при запуске определять логи с помеченными метками.
Если все выводить console.log, то все у нас смешается и ничего не будет понятно по мере роста приложения. Кроме того, можно определить какие именно логи будут выводиться (с какими именно метками). 
var debug = require('debug')('my_debug');

...
debug(some_obj);//console.log
Чтобы вывести этот лог, мы должны в переменной окружения DEBUG установить метки, которые мы бы хотели вывести
$ DEBUG=my_debug,other_tag node script.js 

Модуль winston
Предназначен для более умудренного логирования.

var log = require('winston');

log.info(...);
log.debug(...);
log.error(...);
По-умолчанию винстон настроен так, чтобы выводить только инфо и еррор.

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

Логирование внутренних модулей node
Для этого нужно указать через запятую в переменной окружения NODE_DEBUG логи из каких внутренних модулей мы хотели бы выдеть.
$ NODE_DEBUG="cluster http module" node myscript.js

Способы отладки nodejs

Консольный встроенный
1) Вставляем в скрпите точки останова ключевым словом debugger;
2) Запускаем ноду в режиме отладки
$ node debug script.js

3) После этого получаем в терминале, вывод первых строк скрипта, подсветку первой строки, и подсказку того, что скрипт запущен в режиме отладки и остановлен на первой строке, ожидается ввода команд для управления отладки:
debug>

4) Можем нажать c - continue, что запустить скрипт в нормальном режиме, пока его выполнение не наткнется на ключевое слово debugger;. Дальше мы можем шагать по сприпту s(step), а также запускать repl, такой же командой, а там выводить переменные что нас интересуют и выполнять любой код, который мы введем.

среда, 17 июля 2013 г.

supervisor.js

Модуль для автоматического перезапуска ноды при креше процесса или, если внутри проекта поменялись файлы.
npm i -g supervisor


Теперь мы можем запустить наше приложение следующим образом:
supervisor myscript.js


Если нужно настроить в WebShtorm, то нужно не забыть обновить приложение для запуска и указать путь к supervisor

Чтобы в скрипт передать параметры(будут доступны через process.argv) мы должны перед именем скрипта поставить два минуса --:
supervisor -- server.js --port=3000

Подводные камни:
1) Новодобаленные файлы текущей версии supervisor не вызовут перезапуск ноды. Только если мы сошлемся на них напрямую в уже знакомых для supervisor файлах.
2) Когда папка node_modules проекта наполниться значительным количеством установленных модулей,  supervisor начнет кушать очень много процессорного времени. Чтобы этого избежать нужно modules устанавливать выше по иерархии директорий, либо указывать параметра игнорирования supervisor на папку node_modules.

вторник, 16 июля 2013 г.

underscore.js осмотр

Это библиотека утилит, которая предлагает набор функций, характерных для функционального программирования.
Создает родную атмосферу дла руби-разработчиков в браузере.
Как агитируют на сайте underscore.js - это галстук для смокинга jQuery и поддтяжек Backbone.js. 

понедельник, 15 июля 2013 г.

ssh тунель

Допустим у нас стоит задача посмотреть что творится в базе MySQL на продакшине, а там на удаленной машине порт 3306 закрыт наружу, только локальный сервер приложения имеет туда доступ. Для этого мы можем создать тунель:
$ ssh -f -N user@database.example.com -L 9906:127.0.0.1:3306
Чтобы сократить, можно воспользоваться алиасом, ~/.ssh/config:
Host tunnel
  HostName database.example.comm
  IdentityFile ~/.ssh/id_rsa_2
  LocalForward 9906 127.0.0.1:3306
  User user
$ ssh -f -N tunnel
Таким образом мы можем подключиться клиентом базы данных на локалке как-будто к localhost:9906, что на самом деле будет тунелем на удаленный database.example.comm, у которого закрыт наружу порт 3306, но у себя локально(127.0.0.1:3306) он же не закрыт, вот мы и пробрасываем с локального пората, по ssh порту на удаленный, а там ssh-сервер перекидывает пакеты на свой указанный локальных порт.

На стороне сервера /etc/ssh/sshd_config
AllowTcpForwarding yes
PermitTunnel yes
/etc/init.d/sshd restart

суббота, 13 июля 2013 г.

Ивентэмитер в NodeJs

events.EventEmitter
Класс который реализует событийную модель в ноде
var EventEmitter = require('events').EventEmitter; 
 
var ee = new EventEmitter;
 
ee.on('myevent', function(data) {});
ee.emit('myevent', {some: "data"});

//маленькая тонкость

ee.emit('error');//это свалит скрипт, если не будет подписки на событие с названием error, такая реализация только для события с этим названием

Есть несколько отличий между событийными моделями ноды и браузеров:

Как работает NodeJs в сравнении с другими серверами

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

четверг, 11 июля 2013 г.

Получение параметров в скрипты. optimist.js commander.js Module

1. Самый простой способ разбираться со стороковым значением process.argv.

cheerio Module

Серверная реализация Query Sizzle. Быстрее чем JSDOM
var cheerio = require('cheerio'),
    $ = cheerio.load('

Hello world

'); $('h2.title').text('Hello there!'); $('h2').addClass('welcome'); $.html(); //=>

Hello there!

вторник, 9 июля 2013 г.

Способы вывода строки по номеру из файла в linux


awk 'NR==123' NC_007779.ptt
sed -n '123p' NC_007779.ptt
cat NC_007779.ptt | head -123 | tail -1

lsof

LiSt Of opened Files. Выводит информацию о том, какие файлы используются указанными процессами.

lsof -i 4 -a -p 1234 #(просмотр всех соединений IPv4, открытых процессом с PID = 1234)
lsof -i tcp:80 #(просмотр информации о процессе, который прослушивает 80 TCP порт)
lsof /dev/hd4 #(Список открытых файлов на устройстве /dev/hd4)
lsof /dev/cdrom #(Список процессов, работающих с CD ROM)
lsof -c ssh #(Список подключений по ssh)

В базовой поставке NetBSD и FreeBSD есть аналоги: утилиты fstat и sockstat.

понедельник, 8 июля 2013 г.

Как вернуть процесс из фона

Походу кроме
fg <NUM>
, можно еще и
%proc_name

Например
$ %emacs

воскресенье, 7 июля 2013 г.

Основы работы с emacs

Это консольный текстовый редактор, который позволяет:
- читать и отправлять почту;
- компилировать код;
- открывать subshell в виде даба для кокой-нибудь итерпретации кода.

Запустисть емакс без X11(не создавать графический фрейм, если запускаем  emacs из xterm окна, емакс отображается в том же окне) (-nw, --no-window-system) и любой кастомизации (-Q):
emacs -nw -Q


^h, t - запустить туториал
^t, a - поиск по патерну комманды
^h, f - описывает указанную функцию лиспа
^h k - узнать информацию о конкретной комбинации клавиш 

^x ^c - quit
^x ^f - read a file into Emacs
^x ^s - save the file to disk
^x s - save all files

^v - прокрутить файл на высоту терминала вперед
alt+v - прокрутить файл на высоту терминала назад
^l - перерисовать терминал и курсор с строкой, на которой он стоял окажется по средине терминала, если мы еще раз нажмем, то курсор окажется в верху терминала со своей строкой, если еще раз - то вконце.

^p - переместить каретку на строку вверх
^n - переместить каретку на строку сниз
^f - переместить каретку на символ вперед
^b - на символ назад
alt+f - на слово вперед
alt+b - на слово назад
^a - в начало строки
^e - в конец строки
alt+a - в начало предложения
alt+b - в конец предложения

alt+<(shift+,) перейти в начало всего текста
alt+>(shift+.) перейти в конец всего текста

Передвижение с указанным повторением раз:
^u  
^u 3 alt+f- передвинуться на 3 слова вперед
^u 5 ^p- передвинуться на 5 строк вверх
также более быстры вариант, но который работает не на всех терминалах:
alt+

^g - выйти из доглоиграющей команды емакс; а также если мы начали вводить команду из состоящую из нескольких комбинаций, это способ отмены на полпути

Окна
Или табы.
^x 1 - уничтожить все окна и оставить только первое

Мульти-ввод
Таже идея что и с передвижением, но тут только в уствкой символов.
Чтобы получить например 12 звездочек подряд мы вводим:
^u 12 * - получаем ************

<ret> удалить символ до каретки
^d удалить символ после каретки
alt+<ret> удалить слово до каретки
alt+d удалить слово после каретки
^k кильнуть(вырезать) от каретки до конца строки
alt+k кильнуть(вырезать) от каретки до начала строки

^space начать выделять текст, выделяется он комбинациями премещения курсора(каретки)
^w удалить "убитый" текст
^y заянковать "убитый" текст(вставить вырезанный текст), самый последний вырезанный
^y alt+y вставить более ранне вырезанный текст. После того как мы заянкили кильнутый текст, нажимая альт-янк, мы будем менять вставленный текст на ранее вырезанный, так нажимая несколько раз мы вернемся к нужному вырезанному тексту.

^u NUM ^y - передвинуться сразу назад на NUM, и не нужно нажимать несколько раз alt+y

Когда мы вырезаем текст(^k) на его месте все еще остается пустая строка, если мы еще раз нажимаем ^k, то пропадает и пустая строка, но кроме этого это включает режим дополнения вырезанного текста -- если мы еще будем вырезать так строки, то они все вырезаны со своими пустыми строками будут считаться одним выризанием, и заянкуем мы все эти строки одним нажатием вставить.

^/ или ^_(shift+-) или ^x u - Undo, отмена редакции

Работа с файлами

^x ^f - найти(открыть) файл

Линия внизу емакс когда мы туда вводим имя файла для открытия, в этом контексте называется минибуффер(^g - отмена ввода).

Когда мы сохраняем файл ^x ^s, то файл сохранятся с именем оригинала, но с нашими изменениями, но при этом сам оригинал тоже не теряется он сохраняется после этого в файле с именем ~.

Последующее открытие файлов, не теряет текущий, все открытые файлы находятся в буферах(обьект buffer), и мы можем между ними переходить:
^x ^b - список буфферов
^x 1 - скрыть список буфферов, это вообще-то удаляет все кроме одного окна, которые разделяют табы на фреймы.
^x b - открыть нужный буффер, введя его имя(автозаполнение работает)
Кстати среди списка буферов, находятся не все которые представляют файлы. Например *Messages* представляют буфер, который хранит ссобщения, что нам выводились, а *Completions* списки для выбора автокомплита, которые нам выводились.

^x s - емакс выведет подтверждение для каждого файла, который мы изменили и мы можем выбрать какой файл сохранять, а какой нет.

Команды с короткими именами и команды с длинными именами
команды вида ^x ... ожидают введениее одного символа для выполнения команды. Это символьные.
alt+... - ожидают введение длинного имени. Это именные команды, для них действует автокомплит по табу.

alt+x replace-string - ожидает два аргумента, заменивает все строки после позиции каретки предложенными.

Автосохранение
Емакс делает автосохранение и рядом с оригиналами появляются файлы #original.txt#, если мы крешимся и не успеваем сохраниться, можно сосстановиться из автосохранения, либо вручную, либо в емаке, открыв файл и введя alt+x recover-file. После сохранения эти файлы автосейвов удаляются из диска и появляются через определенный период, потом снова удаляются, если мы сами сохраняемся.

Участки терминала
Место где появляются подсказки нажатых комбинаций и куда мы вводим именные команды называется echo area.
Mode line - участок терминала, где дается информация о редактируемом файле и режиме емакс.
-=--:**--F1  TUTORIAL       63% L730   (Fundamental) ----

1) ** - означают, что в файле есть несохраненные изменения
2) L730, что картка находится на 730 строке, и что это 63% от всего файла.
3) (Fundamental) - тут отображается режим редактирования, major-mode, Fundamental по-умолчанию, бывают также: Lisp mode, Text mode, etc.
Моды отличаются командами - в разных языках по разному коментируются строки кода, это команды тоже отличаются, переходить в мод тоже есть конкертные комманды. alt+x fundamental - способ перейти в дефолтный мод:)
alt+x text-mode - перейти в текстовый режим, отиличие, что апострофы и символы после них считаются одним словом с предыдущим текстом.
^h m - получить информацию о текущем моде
Кроме мажорных модов бывают еще и minor-mode, они откличаются маленькими правками и их можно подключать к мажорному моду, всегде может быть включен один мажорный мод и сколько угодно минорных.
Для текстового мода полезный alt+x auto-fill-mode, он делает перевод строки на новую, если она не помещается в терминале, в строку вставляется именно символ конца строки. Если ввести снова эту комманду, то мы отключим этот режим. Разрыв наступает после ввода 70 символов. Чтобы поменять количество символов до разрыва, ^x f <NUM>, можно ввести сразу ^u 20 ^x f. Факт того, что мы переключили количество символов в строке, не означает, что у нас переформатируется ввесь текст файла, все последующие да, или же мы можем стать кареткой на како-нибудь параграф и нажать alt+q.

Поиск
^s -  начать инкрементный поиск от каретки и вниз. В эхо ерии появиться "I-search:", потом когда мы вводим символы по мере подхождения отдельных слов, они будут выделяется в тексте, и вводя следующий символ, можно будет заметить как количвество выделенных уменьшается. Если мы еще нажимаем ^s, то мы будем двигаться по выделенным словам "поточным веделением". Если нажимать <Ret>, то мы будем возвращаться по словам. Если же мы еще не двигались вперед, или вернулись к первому в поиске слову, то нажимая  <Ret&gt, мы будем удалять последние символы слова поиска, и количество подошедших слов снова начнет расти.

^r - начать поиск от каретки и вверх. Все что касается ^s касается и ^r.


Множественные окна
^x 2 - разделить терминал на два горизонтальных окна.
^+alt+v - проскролить окно, которое в текущий момент без фокуса
^x o - переместить фокус на другое окно.
^x 1 - оставит только одно окно, в котором в момент нажатия находится курсор.
^x 4 ^f - начать искать файл для неактивного окна, если не вводить ничего в эхо строке, а нанажать <Enter>, то у нас появится списко файлов во втором окне и мы можем выбрать необходимый файл, выделить его имя и нажать <Enter>, так мы его откроем.


Множественные фреймы
Как я понял, фреймы это графические окна, в которых открывается терминал.
^x make-frame <Enter> - как я понял откроет новое графическое окно с терминалом, а в нем будет запущен емакс.
^x delete-frame <Enter> - закроет фрейм

Recursive editing level
Как  я понял это режим, когда мы вводим длинные команды. Его можно заметить по квадратным скобкам вокрут имени мажорного мода [(Fundamental)], я пока такого не замечал.
Чтобы из него выбраться нужно нажать <ESC> <ESC> <ESC>, или ^g.

Получение помощи
^h c [hot_keys_comb_OR_command] - краткое описание
^h k [hot_keys_comb_OR_command] - полное описание
^h f [function] - описывает значение по имени функции(лисп), которая привязана к какой-то комбинации
^h v [varibale_name] - описать значение переменной, такие переменные например используеются для настройки редактора.
^h a [keyword] - вводится ключевое слово, в ответ выводятся все команды, которые могут касаться этого слова.
^h i  это команда очень важная в хелпах, read included Manuals (a.k.a. Info). Мы переходим в специальный буфер *info*, где можно почитать мануалы для пакетов, установленных на нашей системе.
Когда мы попадаем в *info* там мир своих команд.
нажимаем "m" (menu) и можем ввести имя утилиты командной строки:)