09.08.2007

Управление пакетами. Создание собственных RPM.

Несколько лет назад, когда Linux использовали на инфраструктурных серверах и компьютерах энтузиастов, было «модно» собирать ПО из исходных текстов. Плох тот линуксоид, который не может пройти книжку LFS и собрать свой дистрибутив.

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

Решение подобной проблемы – использование специального ПО и политики управления пакетами с целью стандартизации управления жизненным циклом ПО. Одним из решений для управления ПО является использование формата RPM, а также одноименного менеджера пакетов.

RPM – что это такое?

Что такое пакет? Прежде всего пакет – это единица управление ПО. Пакет состоит из:

  1. Файлов, исполняемых и конфигурационных
  2. Предустановочных действий.
  3. Постустановочных действий
  4. Действий, необходимых для удаления ПО.
  5. Различной служебной информации (списки и контрольные суммы файлов и т.д.)

Соответственно, пакет – это несколько больше, чем просто архив файлов. RPM-пакеты – основной способ управления ПО во многих дистрибутивах Linux. Разумно использовать его и для управления собственным ПО / ПО третьих лиц, которое не распространяется в виде RPM по умолчанию. Именно этим мы и займемся. Примеры из данной статьи разобраны и протестированы на RHEL5, хотя по аналогии будут работать и во многих других дистрибутивах.

Подготовка окружения для сборки RPM

В любой системе существует стандартная инфраструктура для сборки RPM. По умолчанию она расположена в /usr/src/redhat/. Если подобного каталога нет, установите пакет rpm-build. Его наличие позволяет собирать пакеты, имея административные привилегии, что не всегда безопасно. Мы будем использовать сборку под непривилегированным пользователем, которого назовем brewbuilder.

Для демонстрации нам потребуется пакет hello-1.0.tar.gz, который можно взять с сервера ftp://62.205.185.52/765591143807cc23efcfb4f1b436ebbc/hello-1.0.tar.gz

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

$ mkdir -p ~/workspace/redhat/{RPMS,SRPMS,SPECS,SOURCES,BUILD}
$ echo '%_topdir /home/brewbuilder/workspace/redhat' > ~/.rpmmacros

Теперь мы готовы к сборке. Для сборки нам необходим единственный файл hello-1.0.tar.gz, который надо разместить в ~/workspace/redhat/SOURCES.

Часть основная – содержательная. SPEC-файл.

SPEC-файл – центральная часть процесса сборки. Написание корректного SPEC-файла и является целью нашей сегодняшней работы. Итак приступим.

Есть простой способ обеспечить себе шаблон для сборки – запустите emacs. =) Сложный – сделайте себе шаблон в вашем любимом редакторе (читай VIM) или запомните необходимые стадии. Мы приведем сразу весь SPEC-файл, позже разобрав его построчно. (Нумерация строк приведена только для удобства, в реальном SPEC-файле нумерация не нужна.)

  1. Name: hello
  2. Version: 1.0
  3. Release: 1
  4. Summary: A sample package, saying hello, world
  5. Group: Applications/Productivity
  6. License: GPL
  7. Source0: hello-1.0.tar.gz
  8. BuildArch: i386
  9. BuildRoot: %{_tmppath}/hello-root

  10. %description
  11. This package basically does nothing, but it potentially could
  12. do something useful.


  13. %prep
  14. %setup -q -n %{name}-%{version}

  15. %build
  16. make

  17. %install
  18. mkdir -p $RPM_BUILD_ROOT/usr/local/{bin,lib,share}
  19. mkdir -p $RPM_BUILD_ROOT/usr/local/share/man/man1
  20. install libhello.so.1.0 $RPM_BUILD_ROOT/usr/local/lib
  21. install hello $RPM_BUILD_ROOT/usr/local/bin
  22. gzip -9c hello.1 > hello.1.gz &&
  23. install hello.1.gz $RPM_BUILD_ROOT/usr/local/share/man/man1

  24. %files
  25. %defattr(-,root,root)
  26. /usr/local/lib/libhello.so.1.0
  27. /usr/local/bin/hello
  28. /usr/local/share/man/man1/hello.1.gz

  29. %clean
  30. make clean
  31. rm -rf $RPM_BUILD_ROOT

  32. %post
  33. echo "/usr/local/lib" >> /etc/ld.so.conf
  34. ldconfig

  35. %changelog
  36. * Tue Jul 17 2007 Andrey Meganov
  37. - Initial build

Итак, начнем. В строчках [1-6] находится стандартное описание пакета. Эти поля необходимы, но назначение их чисто описательное за исключением поля Source0, в котором указано имя архива с исходными текстами. Помимо поля Source0, могут быть и Source1, Patch0 и далее по аналогии.

Строчки [11-13] (секция %description) задают описание пакета. Это стандартное многострочное описание, выводимое командой rpm -qi.

Строки [16-17] (секция %prep) отвечаю за подготовку пакета к сборке. Единственная строчка в нашем случае – макрос %setup отвечает за «тихую» (флаг -q) распаковку исходников Source0 в каталог %{name}-%{version}. В этой секции полагается размещать подготовку исходников с сборке, применение патчей и т.п.

Строки [19-20] (секция %build) отвечают за сборку исходников. В нашем случае это делается просто командой make. В общем случае это почти всегда комманды ./configure –prefix=$RPM_BUILD_ROOT/usr; make.

Секция %install [22-28] отвечает за установку файлов в окружении сборки. В нашем случае стандартной цели make install нет, поэтому мы устанавливаем все вручную. В общем случае make install в этой секции почти всегда решит ваши проблемы. Заметьте, что все пути начинаются с $RPM_BUILD_ROOT. Это достаточно важно и это главная причина не собирать пакеты под пользователем root. В случае если вы – root и вы забудете $RPM_BUILD_ROOT в начале пути, то вместо установки в «песочнице» ваш файл будет установлен на вашей рабочей системе, чего вы вряд ли хотите. =)

Секция %files [30-34] – одна из наиболее важных частей нашего SPEC-файла. Она описывает файлы, входящие в RPM-пакет. В этой секции желательно определить макросом %defattr(-,root,root) атрибуты по умолчанию (владелец – root, группа root, доп. атрибутов нет.), иначе при установке RPM-пакета пользователь увидит жалобы на то, что пользователь brewbuilder не существует. При создании списка файлов можно использовать шаблоны с символами '*' и '?', но делать это следует осмотрительно, так как указание списка файлов как /* приведет к включению лишних файлов в пакет. Специально можно пометить конфигурационные файлы (%config), что приведет к специальному обращению с ними, например при обновлении пакета, документацию (%doc) и пустые директории, принадлежащие пакету (%dir). Подробнее об использовании этих и других опций вы сможете прочитать в отдельных статьях.

Секция %clean [36-38] описывает очистку временного окружения сборки и обычно ничего кроме двух указанных команд не содержит.

Секция %post [40-42] описывает постинсталляционный скрипт. В нашем случае мы добавляем /usr/local/lib к пути, по которым доступны разделяемые библиотеки и успокаиваемся на этом. При написании данной секции мы сделали очевидную ошибку. Ошибка заключается в том, что мы не выдержали транзакционность. При удалении пакета мы не можем просто убрать строчку /usr/local/lib из файла /etc/ld.so.conf, потому что мы не можем рассчитывать, что никто другой не проверял наличие там этой строчки. С другой стороны, если мы – последний пакет, которому эта строчка нужна – неплохо было бы все таки иметь возможность удалить ее – для чистоты процесса. Для этого придумали директории, вроде /etc/ld.so.conf.d/. Чтобы добавить путь к библиотекам корректно, нам просто необходимо создать свой файл со строчкой /usr/local/lib в этой директории, а при удалении пакета (например, в неописанной в данной статье секции %preun) удалить этот файл.

И последняя секция %changelog содержит историю пакета. История пишется записями с фиксированным форматом даты, имени и адреса электронной почты. Формат дальнейших заметок произволен. Рекомендуется серьезно отнестись к changelog'ам, дабы избежать проблем в будущем.

Сборка пакета

Сборка пакета осуществляется одной командой

rpmbuild -ba [путь к SPEC-файлу]

После чего вы можете исследовать директории %_topdir/RPMS и %_topdir/SRPMS, найти там собранные пакеты и исследовать их командами rpm -q ...., установить и удалить соответственно.

Заключение

Вот мы и собрали наш первый RPM-пакет. Если вы хотите узнать более тонкие моменты сборки RPM, то рекомендуем прочесть книгу RPM Guide, доступную по адресу http://docs.fedoraproject.org/drafts/rpm-guide-en/. В дальнейшем мы обязательно расскажем о подписи RPM-пакетов и создании собственных репозитариев для yum.

Комментариев нет: