Pull to refresh

Стать мэинтейнером. Часть вторая

Reading time 9 min
Views 4.8K
На второй день мы уже пообвыклись с идеей, что в дебиане и убунту любят действительно свободное программное обеспечение и уже начинаем задумываться о том, как бы нам начать собирать свой первый пакет. Но стоп! А какими программами мы вообще умеем пользоваться? Что?! OpenOffice.org Writer и Kopete? Не, ну так дело не пойдёт. Сегодня я расскажу вам обязательный минимум, который понадобится каждому будущему сопровождающему пакеты (я решил принять этот термин, оставив заморское слово «мэинтейнер» только в заголовке, как дань первой статье), да и просто любому убунтоводу пригодится в жизни.
(Части 1, 3 и 4)


GPG


И начём мы с утилиты GnuPG или просто GPG. Что это такое? GPG — это ваше удостоверение личности, возможность продемонстрировать в интернете, что под вашим именем скрываетесь именно вы, а не злопасный враг, это возможность зашифровать почтовое или jabber-сообщение, это возможность подписать файл, сохранив отпечаток в отдельном файле. Согласитесь, это намного надежнее, чем простой md5-хэш — вы еще и даёте понять, что файл (или файлы) в таком состоянии сохранили именно вы, а не кто-то посторонний. В общем, GPG — это очень полезный и нужный в хозяйстве инструмент. Я не буду рассказывать все его возможности, их можно почитать и в мане, а я расскажу только самое основное. Итак, ставим пакет командой
$ sudo apt-get install gnupg

Теперь нам необходимо создать свою собственную пару ключей. Набираем
$ gpg --gen-key

Стандартный тип ключа (DSA и ElGamal) нас вполне устроит, стандартный размер (2048 бит) тоже. Срок действия (без ограничения) тоже устроит стандартный. Дальше нам надо ввести информацию о себе. Debian предлагает в качестве примера: «Baba Yaga (pensioner) <yaga@deepforest.ru>», где информация в скобках — это комментарий. Его нам вводить необязательно, можно просто ограничиться именем и e-mail'ом:
Ваше настоящее имя: Ivan Ivanov
Email-адрес: ivan@ivanov.iv
Комментарий:
Вы выбрали следующий User ID:
"Ivan Ivanov <ivan@ivanov.iv>"

Если вы введете имя и e-mail, указанные для вашего логина в /etc/passwd, то этот ключ будет по умолчанию использоваться для подписи и шифрования всего, что только можно.
Дальше нам необходимо ввести пароль. В связи с тем, что при подписывании пакета вам не раз придётся его вводить, я не раз слышал высказывания типа «да создай ты отдельный ключ без пароля, чо там такого секретного, никто его у тебя с ноутбука воровать не будет, да и вообще». Не поддавайтесь на такие провокации. Ваш gpg-ключ — это ваш паспорт и даже больше. Создавать ключ без пароля — всё равно что носить сумку со сломанной молнией — даже если мы её всегда держим перед собой и пересекаем метро бегом исключительно бегом — зачем провоцировать потенциальных воров? Поэтому мы придумываем сложный запоминающийся пароль и наконец получаем вожделенную пару ключей:
$ gpg --list-keys
/home/user/.gnupg/pubring.gpg
----------------------------------
pub 1024D/3904FAE7 2009-01-30
uid Ivan Ivanov <ivan@ivanov.iv>
sub 2048g/2DA010F1 2009-01-30

Дальше нам надо отправить наш публичный ключ на какой-нибудь сервер ключей, чтобы любой мог его себе заимпортировать:
$ gpg --keyserver subkeys.pgp.net --send-keys 3904FAE7
gpg: отправляю ключ 3904FAE7 на hkp сервер subkeys.pgp.net

Теперь любой желающий может ввести команду
$ gpg --keyserver subkeys.pgp.net --recv-keys 3904FAE7
и получить ваш публичный ключ. 3904FAE7 в данном случае — это ваш персональный id ключа.
Теперь добавим в ваш ~/.bashrc две строчки:
export DEBFULLNAME="Ivan Ivanov"
export DEBEMAIL="ivan@ivanov.iv"
, которые будут использоваться в дальнейшем при создании и подписании пакетов. На этом мы можем пока оставить GPG и перейти к следующей части.

APT


Да, сейчас мы поговорим о волшебном наборе утилит APT и его применении в сборке пакетов. К сожалению, многие знакомы с этим пакетом довольно поверхностно, а ведь скольких проблем мы могли бы избежать.
Для начала запомним утилиту apt-key. Она нам пригодится, если мы будем подключать сторонний репозиторий. Данная утилита управляет списком доверенных ключей, которыми могут быть подписаны различные репозитории. Если мы выполним команду
$ sudo apt-key list
то получим стандартный список ключей, которыми подписаны официальный репозитории вашего дистрибутива. Как добавить туда ключ еще одного репозитория? Например, так:
$ wget -O - qutim.org/debian/archive.key | sudo apt-key add -
При помощи wget мы скачаем с сайта публичный ключ репозитория qutIM'а и передадим его на вход команде apt-key. Теперь пакеты, подписанные данным ключом, будут считаться «хорошими» и устанавливаться без предупреждений.

Идём дальше. Я обещал рассказать, чем вот этот подход является таким ужасным. Разумеется, будь мы истинными пользователями Slackware, держащими в голове все установленные пакеты с десятками зависимостей, нам не составляло бы труда скомпилировать и поставить еще одну программу из исходников (знакомые пользователи Slackware говорят, что в последних версиях даже появился полноценный менеджер пакетов, возможно даже честно сп...украденный из Debian'а, но они всё равно предпочитают по старинке отслеживать все зависимости вручную). Но мы же с вами знаем, что такое пакетный дистрибутив, зависимости, контроль версий в конце концов. Ставить pidgin в /opt/ некультурно хотя бы по той простой причине, что однажды забывшись, мы ткнём в меню кнопку pidgin и запустим старую версию, с неработающей аськой.
«Можно ведь указать префикс /usr/», — скажете вы. Конечно, и первое же обновление пакета в репозитории потрёт вашу исправленную версию. Кому это в самом деле нужно? Нет, мы сделаем всё культурно. Поскольку pidgin большой, некрасивый и тяжелый пакет, и вообще я его не люблю, я расскажу вам всё на примере пакета ccache, кэширующего объектные файлы компилятора при сборке.
Как известно, данный пакет делает файлы «gcc», «g++» и еще несколько подобных — симлинками на свой исполняемый файл /usr/bin/ccache, а сам смотрит на название вызванного файла, в соответствии с которым и подставляет нужный компилятор. Но вот в чём проблема — многие исходники при компиляции обращаются к файлу «c++», который должен быть симлинком на любой подходящий компилятор, а компилятора «c++» ccache и не знает. Что же делать? Я решил не мучиться, не переучивать исходники и не создавать лишних файлов, а обойтись грязным хаком.
Итак, чтобы работать с исходными пакетами, мы смотрим файл /etc/apt/sources.list. Если мы видим там закомментированные строки, начинающиеся на «deb-src», смело их раскомментируем, это указания, где брать файлы пакетов с исходниками.
Теперь мы берем знакомую нам практически с детства заветную команду apt-get и выполняем ее три раза с разными параметрами:
$ sudo apt-get update
$ sudo apt-get install devscripts lintian
$ apt-get source ccache
Первой командой мы обновляем список доступных пакетов после редактирования sources.list, второй устанавливаем скрипты, необходимые для сборки пакетов, а третьей скачиваем пакет с исходниками ccache. Заметьте, чтобы скачать пакет с исходниками, нам даже не нужны права суперпользователя. Тем временем APT нам сообщает:
Получено:1 http.us.debian.org sid/main ccache 2.4-16 (dsc) [1118B]
Получено:2 http.us.debian.org sid/main ccache 2.4-16 (tar) [86,4kB]
Получено:3 http.us.debian.org sid/main ccache 2.4-16 (diff) [44,1kB]
Получено 132kБ за 2s (51,1kБ/c)
dpkg-source: извлечение ccache в ccache-2.4
dpkg-source: инфо: распаковывается ccache_2.4.orig.tar.gz
dpkg-source: инфо: накладывается ccache_2.4-16.diff.gz

Обратите внимание: исходный пакет состоит из трёх файлов: файла .orig.tar.gz — это архив с неизмененными исходниками — такими, какими их распространяет сам разработчик программы, файл .diff.gz — это diff-файл, хранящий в себе все изменения исходников, включая debian-инструкции по сборке (об этих инструкциях в следующий раз), и файл .dsc, в котором хранится краткая информация о пакете, хэши первых двух файлов, а сам dsc-файл подписан GPG-подписью автора пакета. При желании мы могли бы получить открытый ключ и проверить эту подпись, но поскольку пакет взят нами из официального репозитория, то мы такими глупостями заниматься не будем. Поэтому мы заходим в каталог ccache-2.4 и при помощи любимого текстового редактора меняем в файле execute.c строку "x_asprintf(&fname, "%s/%s", tok, name);" на строки:
if (strcmp(name, "c++") == 0) {
x_asprintf(&fname, "%s/%s", tok, "g++");
} else {
x_asprintf(&fname, "%s/%s", tok, name);
}

Понятно, что большинству из вас эта программа и этот патч никогда не понадобятся, но по крайней мере в следующий раз при желании исправить пакет, например, заменить в нём иконки на свои любимые или добавить в «О программе» строку «Здесь был Вася», вы будете представлять, что делать.
Итак, мы исправили исходники, что нам надо сделать дальше? Совершенно верно, надо увеличить номер версии пакета. Набираем всё в том же каталоге команду
$ dch -i
При этом запустится ваш любимый редактор (у меня это vim), в котором уже будет открыт changelog, и добавлен шаблон записи о новой версии. Если вы к моменту выполнения этой команды уже перезапускали ваш bash или просто переоткрывали консоль, то в качестве автора изменений будут подставлены ваше имя и e-mail, которые мы добавляли в файл ~.bashrc. У меня, например, предложенный шаблон выглядит так:
ccache (2.4-16.1) unstable; urgency=low

* Non-maintainer upload.
*

-- Vsevolod Velichko <torkvemada@nigma.ru> Fri, 30 Jan 2009 06:05:36 +0300

Запись «Non-maintainer upload» добавлена автоматически, чтобы показать, что данную версию пакета создал не сопровождающий пакета, а сторонний человек. Предложеннный номер версии нас не устраивает, давайте его увеличим и добавим немножко информативности в сведения об изменениях. В результате наша запись принимает вот такой вид:
ccache (2.4-17) unstable; urgency=low

* Non-maintainer upload
* Patched for the "c++" as compiler name support

-- Vsevolod Velichko <torkvemada@nigma.ru> Fri, 30 Jan 2009 06:05:36 +0300
Сохраняем и выходим. Теперь надо посмотреть, все ли необходимые для сборки данного пакета программы у нас есть. Открываем в любимом редакторе файл ccache-2.4/debian/control и ищем в нем следующую строку:
Build-Depends: debhelper (>> 6), autotools-dev, zlib1g-dev
В ней записано, какие пакеты, кроме стандартных, потребуются для сборки пакета. Набираем для гарантии:
$ sudo apt-get install debhelper autotools-dev zlib1g-dev
убеждаемся, что все требуемые пакеты поставились или уже стоят, после чего можем переходить собственно к сборке.
Другим способом установить все необходимые для сборки пакеты является:
$ sudo apt-get build-dep ccache
Этот способ подходит вам, когда все ваши изменения находятся на уровне патчей и не добавляют в программу ничего, что требовало бы новых зависимостей — каких-то дополнительных библиотек, запуска внешних программ при сборке, или еще чего.
Всё в том же каталоге ccache-2.4 набираем волшебную команду
$ debuild --lintian-opts -i
Команда со столь неблагозвучным названием, как debuild, занимается ничем иным, как тем, что собирает пакет, затем натравливает на него программу lintian, которая отлавливает нехорошо оформленные пакеты, а в завершение добивает собранный пакет командой debsign, которая подписывает собранный пакет (на этом этапе, если в changelog вы правильно указали своё имя и email, у вас спросят пароль от вашего gpg-ключа, который мы генерировали в первой части). Посмотрим на вывод lintian, он сообщает нам, какие ошибки были обнаружены при сборке:
Now running lintian…
W: ccache source: source-nmu-has-incorrect-version-number 2.4-17
N:
N: A source NMU should have a Debian revision of "-x.x" (or "+nmuX" for a
N: native package). This is to prevent stealing version numbers from the
N: maintainer.
N:
N: Maybe you didn't intend this upload to be a NMU, in that case, please
N: doublecheck that the most recent entry in the changelog is byte-for-byte
N: identical to the maintainer or one of the uploaders. If this is a local
N: package (not intended for Debian), you can suppress this warning by
N: putting «local» in the version number or «local package» on the first
N: line of the changelog entry.
N:
N: Refer to Debian Developer's Reference section 5.11.2 (NMU version
N: numbering) for details.
N:
N: Severity: normal; Certainty: certain
N:

Правда, удобно? Не только расскажут, в чём ошибка, но и отправят к соответствующему разделу документации разработчика Debian. Тут я хочу отметить, что в Debian утилита lintian намного строже относится к пакетам, чем в Ubuntu, поэтому если вы хотите получить идеальный пакет — соберите его в Debian, а потом портируйте в убунту, комар носа не подточит. В данном случае нам сообщили, что наша единственная ошибка состоит в том, что преднамеренно изменив предложенный нам номер новой версии, мы изменили его неправильно. Теперь выйдем из каталога на уровень выше и установим собранный пакет:
$ sudo dpkg -i ccache_2.4-17_amd64.deb

Что нам осталось? Самый внимательный читатель, дочитавший до этого места, обязательно задастся вопросом: а что, если выйдет новая версия ccache, с номером версии больше, чем 2.4-17? На этот вопрос есть не менее двух решений. Первое указать при сборке версию не 2.4-17, а заведомо большую, например, 5.7-99. Но и такое решение однажды оказалось недейственным, когда пропатченный мною proftpd неожиданно заменился новой версией, которая наконец доросла до указанного мною номера. Второе решение немножко более элегантное. Набираем:
$ sudo aptitude hold ccache
Данная команда поставит на ccache статус hold, то есть зафиксирует текущую установленную версию и не будет устанавливать из репозитория более новые.

Итог


Данная статья на самом деле должна была быть еще больше, но в силу позднего (или даже уже раннего) времени, а также довольно большого объёма того, что я уже набрал, осветить всё, что я хотел, не представляется возможным. Я решил отбросить как минимум рассказ про команды sed и awk, понадеявшись на то, что вы освоите их при необходимости сами.
Что еще осталось за кадром? Создание репозитория из собранных вами пакетов. Данный рассказ займёт больше нескольких строчек, поэтому он остался на следующий раз.
Еще возможно кто-то скажет, что приведенный способ патчить пакет тоже не является верным, и будет абсолютно прав. Если мы задумаемся о том, что нам придётся проделывать всю ту же процедуру редактирования файлов при желании пропатчить новую версию пакета, становится ясно, что наш способ подходит только для быстрой правки — например, если разработчики обещали внести исправление в пиджин в новой версии, а мы хотим его применить уже сейчас. Для исправлений на постоянной основе нам пригодятся утилиты diff и dpatch. Но их я вам предлагаю уже освоить самим в качестве домашнего задания, равно как и самостоятельно собрать исправленный пакет pidgin для ваших нужд. Оставляйте ваши пожелания, что бы вы хотели узнать, я постараюсь в следующих частях это максимально осветить.
Tags:
Hubs:
+48
Comments 79
Comments Comments 79

Articles