среда, 23 декабря 2009 г.

Groovy first steps

Озаботившись скриптовой обвязкой для очередной инсталляции, где выразительности unix shell явно недостаточно, подумал о том, что поздняк метаться. Perl, Python, Ruby и прочие скриптовые языки хороши каждый по-своему, но от Java мне все равно никуда не деться. В то же время с Groovy я получу примерно тот же уровень комфорта при ad-hook scripting с сохранением всего, что я уже умею и сделал. Ибо код Groovy не просто компилируется в байткод JVM (таких языков много), но максимально синтаксически и семантически похож на Java.

Предварительные требования для Groovy: установленный JDK и прописанный JAVA_HOME (в ALT Linux для этого достаточно сказать apt-get install java-1.6.0-sun-devel tzdata-java). Процесс установки выглядит так:
# cd /opt
# wget http://dist.groovy.codehaus.org/distributions/groovy-binary-1.7.0.zip
# unzip groovy-binary-1.7.0.zip 
# ln -s groovy-1.7.0 groovy
# cat > /etc/profile.d/groovyhome.sh << EOF
> GROOVY_HOME=/opt/groovy
> export GROOVY_HOME
> export PATH=$PATH:$GROOVY_HOME/bin
> EOF
# chmod 755 /etc/profile.d/groovyhome.sh
Причины неиспользования groovy из альтовского репозитария (или JPackage в общем случае) просты - огромный список зависимостей, большая часть которых мне никогда не потребуется, и, как следствие, протухшие версии зависимых пакетов да и самого groovy. Проблема переносимости в случае ad-hook scripting менее актуальна, однако при увеличении размеров проекта она вполне может проявиться.

Теперь перелогинимся и убедимся в том, что Groovy у нас есть:
$ groovy -version
Groovy Version: 1.7.0 JVM: 1.6.0_17
а затем напишем традиционный Hello World:
$ cat > hello.groovy << EOF
> #!/usr/bin/env groovy
>
> def hello(name) {
>     println("Hello $name!")
> }
>
> hello("World")
> EOF
$ chmod 755 hello.groovy
$ ./hello.groovy 
Hello World!
Ну и тормоз же он однако:
$ time ./hello.groovy 
Hello World!
3.18user 0.18system 0:02.22elapsed 151%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (1major+25068minor)pagefaults 0swaps
И даже предварительная компиляция и запуск готового байткода помогает не сильно:
$ groovyc hello.groovy 
$ time java -cp .:$GROOVY_HOME/embeddable/groovy-all-1.7.0.jar hello
Hello World!
1.88user 0.10system 0:01.60elapsed 123%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (1major+15771minor)pagefaults 0swaps
Хотя здесь как раз нет ничего удивительного - скоростью запуска JVM никогда не отличалась. Для разных мелочей эту проблему можно обойти с помощью Groovy Shell:
$ groovysh 
Groovy Shell (1.7.0, JVM: 1.6.0_17)
Type 'help' or '\h' for help.
------------------------------------------------------------------------------------
groovy:000> def hello(name) {      
groovy:001> println("Hello $name!")
groovy:002> }
===> true
groovy:000> hello("World")         
Hello World!
===> null
groovy:000> exit
Для отлаженных скриптов лишних 3 секунд на запуск уже не очень жалко, ну а запускать их (и JVM вообще) слишком часто никто в здравом уме не станет - постоянно запущенный сервис будет работать значительно эффективнее.

среда, 9 декабря 2009 г.

Развитие ALT Linux Live Lite

Давно ожидаемый комбинаторый взрыв возможных конфигураций Live Lite заставил меня задействовать autoconf в одноименном бранче профиля. Выглядит примерно так:
$ autoconf

$ ./configure --help
...
  --with-aptconf=file       custom apt.conf location, e.g '--with-aptconf=/etc/apt/apt.conf'
  --with-release=release    install altlinux-release-* package
  --with-kernel=kernel      install kernel-image-* package
  --with-boot=boot          boot : propagator, nfs, nbd
  --with-features=features  features : see live/features directory ...
  --with-user=user          user : default user name
  --with-locale=locale      locale : en_US, ru_RU, ...
  --with-timezone=timezone  timezone : Europe/London, Europe/Moscow, ...

$ ls live/features
apps-firefox
apps-mobile
apps-office
de-xfce
dm-autologin
dm-autologin-gdm
dm-gdm
fakeinstall
sound
tools-console
tools-network
xorg
Типичная feature выглядит следующим образом:
$ cat live/features/dm-autologin/packages 
autologin

$ cat live/features/dm-autologin/image-scripts.d/01-autologin 
#!/bin/sh -e
cat >> /etc/sysconfig/autologin << EOF
USER=altlive
EXEC=/usr/bin/xinit
EXEC_ARGS=/usr/bin/startx
EOF
И пока для моих инсталляций такой способ формирования образов выглядит удобнее m-p-d. Желающие могут загрузить образы, собранные на текущем branch/5.1 (общая часть --with-release=5.1 --with-kernel=el-smp --with-user=user --with-timezone=Europe/Moscow --with-locale=ru_RU):
  • i586 --with-features=fakeinstall,tools-console,tools-network
  • i586 --with-features=fakeinstall,tools-console,tools-network,xorg,dm-autologin-gdm,de-xfce,apps-firefox,apps-office,apps-mobile,sound
  • x86_64 --with-features=fakeinstall,tools-console,tools-network
  • x86_64 --with-features=fakeinstall,tools-console,tools-network,xorg,dm-autologin-gdm,de-xfce,apps-firefox,apps-office,apps-mobile,sound
Немного измененная процедура установки выглядит теперь так:
  • размечаем диск с помощью [c|s]fdisk/mkswap/mkfs.ext4 или parted
  • вызываем /live/install (диск) (раздел для корня) - при этом загруженная система переносится на корневой раздел, настраивается fstab (туда прописываются корень и все найденные своп-разделы) и lilo
  • перезагружаемся с жесткого диска
  • настраиваем FQDN в /etc/sysconfig/network
  • настраиваем сеть
  • меняем рутовский пароль и пароль пользователя user - по дефолту они пустые

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

Сетевая загрузка ALT Linux Live Lite

Пропагатор позволяет загружать ALT Linux Live Lite не только с локальных устройств, но и по сети, однако при этом образ загружаемой системы размещается в RAM - и это не очень хорошо в тех случаях, когда памяти мало. По аналогии с ALTSP можно монтировать корень загружаемой по сети системы непосредственно по NFS/NBD - профиль можно взять там же - но в бранче netboot.

Не удержался и сделал "ALTSP на коленке" - в настройках pxelinux можно указать параметры nbdswap для сетевого свопа и xdmcp для подключения к удаленному десктопу. Результаты в бранче netboot-xdmcp.

среда, 23 сентября 2009 г.

ALT Linux Live Lite

ALT Linux 4.0 Server Lite умер, да здравствует ALT Linux Live Lite! Как видно из названия, это в первую очередь live-система с минимальным набором необходимых инструментов, однако она также пригодна к установке самой себя на жесткий диск в ручном режиме:
  • размечаем диск с помощью fdisk/sfdisk/cfdisk
  • вызываем /live/install (диск) (раздел для корня) (раздел для свопа) - при этом инициализируется своп, создается и заполняется файловая система ext3 на корневом разделе, настраивается fstab и lilo
  • перезагружаемся с жесткого диска
  • настраиваем FQDN в /etc/sysconfig/network
  • настраиваем сеть
  • удаляем PermitRootLogin yes из /etc/openssh/sshd_config - это удобно для удаленной установки через выключенный по умолчанию ssh, но не очень подходит в production
  • создаем хотя бы одного пользователя и включаем его в группу wheel - по умолчанию таких пользователей еще нет
Система собрана на текущем Сизифе, доступны iso для архитертур i586 и x86_64 iso потеряны а, профиль можно взять здесь.

четверг, 13 августа 2009 г.

Telephone eXchange Management Library

На GitHub отправилась TXMLib (Telephone eXchange Management Library) - небольшая библиотека, предоставляющая унифицированный API к общим операциям различных цифровых АТС. Пока поддерживается только измерение параметров абонентской линии только для АТС типа EWSD, MT-20/25 и DX-200 (а также ее потомка АТСЦ-90), однако дизайн библиотеки позволяет сравнительно легко добавлять поддержку новых типов АТС и новых типов операций.

Для этого потребуется описать наследников классов:
  • txm.lib.common.core.CommandManager - для выделения ответов на команды из терминала АТС - поддержка чего-то отличного от текстового терминала возможна, но пока детально не проработана
  • txm.lib.common.core.OperationManager - для перевода унифицированных операций в конкретные команды АТС
Помимо хорошей экономии на общем коде и повышения его читабельности по сравнению с инструментами типа expect мы также получаем дополнительный бонус в виде сформированного графа операций, команд, их результатов и ошибок, готового к сериализации в XML (см. класс txm.lib.examples.OperationExample) или, например, в реляционную БД посредством ORM.

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

Разумеется, диспетчеризацией операций и их передачей по сети TXMLib не занимается - это следующая задача для другого инструмента.

вторник, 17 февраля 2009 г.

ALT Linux 4.1 Desktop Lite - неофициальная сборка

Время от времени в community@lists.altlinux.ru спрашивают: а где бы раздобыть ALT Linux 4.1 Desktop Lite, который до релиза, как известно, не дожил :(

Поскольку я собирал для себя нечто подобное, но с другим дизайном и с другими дефолтами, и лучше поздно, чем никогда, выкладываю пересобранные на сегодняшнем branch/4.1 cd-образы:
Инсталлятор от официального не отличается ничем, свежеустановленная система выглядит так:


Если кому-то вдруг захочется это собрать, профиль можно взять здесь. Планы по сборке аналогичного дистрибутива на branch/5.0 есть, но если кто-нибудь меня опередит, я буду только рад :)

воскресенье, 15 февраля 2009 г.

Практическое введение в Git

Возможно, я плохо искал, но простого пошагового введения в Git на русском для тех разработчиков и админов, которые кое-как научились использовать CVS или SVN, до сих пор нет. Много полезных материалов и ссылок можно найти на ALT Linux Wiki, однако значительная их часть содержит альтовскую дистрибутивостроительную специфику или, наоборот, несколько далека от практических задач. Я попытаюсь описать один из типичных сценариев использования Git без привязки к каким-либо задачам и без излишних подробностей - за ними лучше сразу идти в Git User's Manual.

Итак, основная идея Git, как и любой распределенной SCM, заключается в том, что мы имеем дело с локальными коммитами в индивидуальных репозитариях разработчиков и с мехнизмами обмена коммитами между репозитариями. Главное преимущество - гибкость (можно вести локальные бранчи с локальными коммитами, не забивая основной репозитарий результатами неудачных или удачных экспериментов), обратная сторона - некоторое увеличение сложности взаимодействия по сравнению с централизованными SCM.

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

Устанавливаем все необходимое и заводим на сервере центральный репозитарий:
# apt-get install git-core
# mkdir /home/repo/alpha.git
# cd /home/repo/alpha.git
# git init --bare --shared=true
Работать с ним будем по ssh, поэтому создаем для разработчиков учетные записи и добавляем их в группу, во владение которой передаем репозитарий:
# useradd -d /var/empty/ -s /usr/bin/git-shell user1
# useradd -d /var/empty/ -s /usr/bin/git-shell user2
# groupadd alpha
# usermod -G alpha user1
# usermod -G alpha user2
# chown -R root:alpha /home/repo/alpha.git
Теперь один из разработчиков может создать локальный репозитарий и сделать в нем несколько коммитов:
[user1@workstation1 ~]$ mkdir alpha
[user1@workstation1 ~]$ cd alpha
[user1@workstation1 alpha]$ git init
[user1@workstation1 alpha]$ git config user.name 'User 1'
[user1@workstation1 alpha]$ git config user.email 'user1@workstation1'
[user1@workstation1 alpha]$ echo 'line 1' > file
[user1@workstation1 alpha]$ git add .
[user1@workstation1 alpha]$ git commit -a -m 'add line 1'
[user1@workstation1 alpha]$ echo 'line 2' >> file
[user1@workstation1 alpha]$ git commit -a -m 'add line 2'
Каждый коммит принадлежит одному или нескольким бранчам. Для первого коммита автоматически создается бранч с именем master, в него же по умолчанию попадают следующие коммиты.

Несколько полезных команд:
  • git branch - показать список бранчей, выделив текущий, создать, удалить или переименовать бранч
  • git status - показать текущее состояние рабочей копии (какие новые файлы появились, а какие были удалены, что закоммитили, а что нет, и т.д.)
  • git log - показать историю коммитов, каждый из которых идентифицируется с помощью хеша sha1
  • git show - показать подробности последнего коммита или любого коммита по его хешу
  • git diff - показать разницу между последним коммитом и рабочей копией или между коммитами
Теперь подготовим наш репозитарий к отгрузке коммитов в центральный репозитарий на сервере:
[user1@workstation1 alpha]$ git remote add origin user1@gitserver:/home/repo/alpha.git
И отправим туда коммиты, принадлежащие локальному бранчу master - они попадут в удаленный бранч с таким же именем:
[user1@workstation1 alpha]$ git push origin master
В дальнейшем можно будет ограничиться git push, т.к. origin - дефолтное имя удаленного репозитария, а бранч master в нем уже существует. С другой стороны, ничто не мешает явно указывать URL удаленного репозитария и имена локального и удаленного бранчей:
[user1@workstation1 alpha]$ git push user1@gitserver:/home/repo/alpha.git master:master
Для получения коммитов из центрального репозитария в локальный бранч master его нужно было бы создать с параметром --track, однако бранч уже существует, поэтому просто укажем соответствующий ему удаленный бранч в настройках:
$ cat >> .git/config << EOF
> [branch "master"]
>       remote = origin
>       merge = refs/heads/master
> EOF
Получить новые коммиты из центрального репозитария можно так:
[user1@workstation1 alpha]$ git fetch
[user1@workstation1 alpha]$ git merge origin/master
или просто:
[user1@workstation1 alpha]$ git pull
В случае конфликтующих изменений операция merge не будет завершена коммитом - в этом случае нужно будет выполнить git commit самостоятельно после разрешения конфликта.

Разумеется новые коммиты могут появиться в центральном репозитарии только после того, как другой разработчик клонирует его, внесет туда какие-либо изменения и отправит их обратно - при этом настраивать свой репозитарий для взаимодействия с удаленным ему уже не потребуется:
[user2@workstation2 ~]$ git clone user2@gitserver:/home/repo/alpha.git
[user2@workstation2 ~]$ cd alpha/
[user2@workstation2 alpha]$ git config user.name 'User 1'
[user2@workstation2 alpha]$ git config user.email 'user2@workstation2'
[user2@workstation2 alpha]$ echo 'line 3' >> file
[user2@workstation2 alpha]$ git commit -a -m 'add line 3'
[user2@workstation2 alpha]$ git push
Теперь чуть подробнее о том, ради чего все эти мучения - ведь для выполнения аналогичных операций средствами CVS или SVN потребовалось бы меньше операций. Дело в том, что до тех пор, пока мы не отгрузили коммиты в удаленный репозитарий, мы вольны распоряжаться ими как нам вздумается. Например, заведем для экспериментов новый локальный бранч и сделаем в нем еще пару коммитов:
[user1@workstation1 alpha]$ git-checkout -b experimental
[user1@workstation1 alpha]$ echo 'line 4' >> file
[user1@workstation1 alpha]$ git commit -a -m 'add line 4'
[user1@workstation1 alpha]$ echo 'line 5' >> file
[user1@workstation1 alpha]$ git commit -a -m 'add line 5'
Если какие-то коммиты лучше было бы не делать, можно откатиться к любому заданному коммиту, указав его:
  • явно в виде sha1 id - их покажет git log
  • по имени тэга - его можно создать для коммита по его sha1 id с помощью git tag
  • относительно другого коммита - например, последнему коммиту, на который указывает HEAD, предшествует HEAD^:
[user1@workstation1 alpha]$ git reset --hard HEAD^
Также бывают полезны параметр --soft (откатиться, но сохранить содержимое измененных файлов для последующего редактирования) и параметр --amend команды git commit (включить содержимое старого коммита в новый).

Вернемся в бранч master, сделаем в нем еще один коммит и втянем туда результаты экспериментов:
[user1@workstation1 alpha]$ git checkout master
[user1@workstation1 alpha]$ subst '/line 1/iline 0' file
[user1@workstation1 alpha]$ git commit -a -m 'add line 0'
[user1@workstation1 alpha]$ git merge experimental
Вместо операции merge, которая создает общий коммит для бранчей, иногда бывает полезно использовать rebase - эта операция переупорядочивает коммиты для того, чтобы сохранить историю линейной. Очень полезно для изучения истории использовать gitk, gitg или qgit - эти инструменты помогут представить описанное более наглядно.

Разумеется, после того, как мы сделали git push, с историей лучше не забавляться - этим мы сильно осложним жизнь тем, кто уже основывает свои новые коммиты на ней. А вот до git push - сколько угодно :)

понедельник, 2 февраля 2009 г.

Redmine quickstart

Похоже, что изначально не приглянувшийся мне Redmine несколько удобнее Trac:
  • есть приличная русификация
  • есть поддержка подпроектов
  • есть web-интерфейс для управления проектами и правами доступа к ним - прям аж обидно, и зачем я тратил время на Trac appliance?
  • и самое главное - дефолтный дизайн отлично гармонирует с дизайном моего блога :)
В качестве ложки дегтя пока заметил лишь то, что принимать информацию об авторизации от Apache он не умеет, правда умеет LDAP, который уже можно прикрутить к Apache. И опакетить его, к сожалению, так просто не выйдет (updated: поэтому вышло непросто).

Мне пришлось поставить из тарболла:
# apt-get install ruby-rake ruby-stdlibs ruby-activerecord-sqlite3-adapter rubygems
# useradd -d /opt/redmine -s /dev/null redmine
# su - redmine -s /bin/bash
$ wget http://rubyforge.org/frs/download.php/49319/redmine-0.8.0.tar.gz
$ tar -zxf redmine-0.8.0.tar.gz 
$ cd redmine-0.8.0
$ cat > config/database.yml << EOF
> production:
>   adapter: sqlite3
>   dbfile: db/production.db
> EOF
$ rake db:migrate RAILS_ENV="production"
$ rake redmine:load_default_data RAILS_ENV="production"
$ ruby script/server -e production
Теперь подключаемся к http://server:3000/ и логинимся под именем admin с таким же точно паролем. Несмотря на грозные предупреждения в руководстве по установке с более новыми, нежели указано, версиями ruby и sqlite вроде бы все работает.

четверг, 29 января 2009 г.

Trac appliance

И все-таки быстрый запуск Trac оказывается не слишком быстрым, а результат - не слишком удобным в сопровождении, особенно когда совместно с Trac предполагается использовать систему управления версиями. Более удобный use case представляется для меня сейчас таким:
  • N проектов - каждый представляет из себя проект Trac и, возможно, настроенный для использования с ним репозитарий Git или Subversion
  • M пользователей - каждый имеет полный доступ к некоторым проектам (т.е. может работать в Trac и коммитить в репозитарий), а к некоторым не имеет вовсе.
Проекты/пользователи должны создаваться/удаляться одной командой, для разрешения/запрета доступа пользователя к проекту также должно быть достаточно одной команды.

Проблема заключается в выборе технологии авторизации и аутентификации, которые позволили бы реализовать описанную схему. Для standalone версий Trac, Git и Subversion ведение единой базы данных пользователей и прав доступа к проектам невозможно, поэтому придется задействовать Apache и его средства управления доступом - соответственно репозитарии Git и Subversion будут доступны по протоколу WebDAV. При этом никто не мешает при необходимости использовать более гибкие настройки прав доступа внутри проектов средствами самих Trac и Subversion.

Готовое решение доступно в виде основного пакета appliance-trac и дополнительных appliance-trac-scm-git и appliance-trac-scm-svn, собираемых из одноименного репозитария. Устанавливаем требуемое штатным для ALT Linux образом:
trac-scm-git
Создаем проект (указываем имя и тип репозитария - если последним параметром будет что-то отличное от git или svn, то репозитарий просто не будет создан):
# appliance-trac-create alpha git
Средствами Apache создаем пользователя:
# htpasswd2 -b /var/www/appliance-trac/passwd user userpwd
Включаем его в соответствующую группу Apache, имя которой соответствует имени проекта:
# vim /var/www/appliance-trac/group
При необходимости пользователя можно сделать администратором Trac:
# trac-admin /var/www/appliance-trac/env/alpha permission add user TRAC_ADMIN
Теперь пользователь user может работать с проектом через web-интерфейс по ссылке http://server//appliance-trac/env/alpha и напрямую с репозитарием:
$ cat > ~/.netrc << EOF
> machine server
> login user
> password userpwd
> EOF
$ git-clone http://server/appliance-trac/scm/git/alpha.git
$ cd alpha/
$ echo "new line" >> README 
$ git commit -a -m 'new commit'
$ git-http-push http://server/appliance-trac/scm/git/alpha.git heads/master
После того, как проект стал ненужным, его можно удалить:
# appliance-trac-drop alpha git

суббота, 10 января 2009 г.

Trac quickstart

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

После установки и запуска штатным для ALT Linux образом:
# apt-get install trac
# service trac start
Trac готов к обслуживанию проектов, размещенных в каталоге /var/lib/trac, однако хотя бы один проект еще нужно создать:
# su - trac -s /bin/sh
$ trac-admin alpha initenv alpha sqlite:db/trac.db "" ""
$ vim alpha/conf/trac.ini # edit [header_logo] and [project] sections
После этого проект будет доступен на чтение всем желающим по ссылке http://localhost:8000/alpha. Для создания и редактирования багов и wiki-страниц необходимо авторизоваться, а для этого сначала создать пользователей следующим образом:
$ trac-passwd -u user -p usrpwd >> /etc/trac/passwd
Для полного управления проектом нужно выдать пользователю user соответствующие права:
$ trac-admin alpha permission add user TRAC_ADMIN
Такая схема разграничения прав доступа удобна для свободных проектов. Для проектов, процесс работы над которыми не должен быть публично доступным, необходима другая схема: как минимум, у пользователя anonymous необходимо изъять все права и явно выдать их группе authenticated. В этом случае все авторизовавшиеся пользователи будут иметь доступ ко все проектам, а это тоже не всегда оправдано. Для того, чтобы можно было ограничить права на уровне отдельных проектов, потребуется также изъять все права у группы authenticated, и передать их отдельной группе, а затем включать требуемых пользователей в эту группу:
$ trac-restrict-env alpha developers
$ trac-admin alpha permission add user developers
Конечно, возможна и более тонкая настройка прав доступа - но об этом подробно написано в документации Trac