Как собрать Deb-пакеты (Debian Binary Packages) из уже установленных программ
Представьте себе следующий сценарий. Вы установили несколько пакетов Debian в своей системе. И вы хотите установить те же пакеты в другой системе. Но вы потеряли двоичные архивы, то есть файлы deb. При этом у вас нет возможности скачать пакеты с их официального сайта или репозитория? Что если конкретная версия определенного пакета больше не доступна? Или, например, вы хотите собрать deb-пакет из установленной программы, но в файлах программы (не конфигурационном файле) внесены важные для вас изменения? Не переживайте! Поскольку они уже установлены в вашей системе, вы можете легко восстановить файлы .deb.
Для решения подобных проблем нам подойдет инструмент dpkg-repack, данная утилита позволяет собирать файлы установленной программы в deb-пакет. Несмотря на то, что инструмент dpkg-repack не имеет графического интерфейса, его работа максимально проста.
Установка dpkg-repack в Debian, Ubuntu и производных
Пакет dpkg-repack доступен в репозиториях по умолчанию в Debian, Ubuntu и его производных. Чтобы установить dpkg-repack достаточно запустить следующую команду:
sudo apt install dpkg-repack
Как собрать Deb-пакет из установленной программы с помощью dpkg-repack
В качестве примера будет собран deb-пакет стабильной версии браузера Opera.
dpkg -l | grep opera-stable
Я мог бы скачать deb-пакет браузера, но именно в данном случае, имею ввиду в случае с браузером Opera, мне гораздо удобнее будет собрать установочный, исправленный пакет. В браузере Opera есть известная проблема с воспроизведением HTML видео с помощью кодека H.264 (легко можно проверить при включении проигрывания прямых трансляций на Youtube). Проблема встречалась и в Яндекс.Браузере и когда-то в браузере Vivaldi. По этой причине было бы гораздо лучше иметь deb-пакет браузера Opera для Linux с решенной проблемой воспроизведения видео.
Проблему с воспроизведением HTML видео в браузере Opera я решил заменой файла libffmpeg.so в директории /usr/lib/x86_64-linux-gnu/opera , это именно та директория в которую устанавливается браузер. Поэтому собранный пакет будет содержать в себе рабочий файл libffmpeg.so и при этом в нем не будет файлов пользователя (конфигурационных файлов).
Перейдём к непосредственной сборке deb-пакета Opera-stable. Выполняем следующую команду:
dpkg-repack opera-stable
Времени на сборку пакета ушло чуть меньше одной минуты. Собранный установочный пакет будет расположен в Домашней папке
В случае проблем, связанных с разрешениями попробуйте собрать пакет из среды fakeroot:
fakeroot -u dpkg-repack opera-stable
При этом при сборке другой программы я столкнулся с ошибкой “ предупреждение: неизвестное информационное поле «Original-Maintainer» во входных данных в элемент в файле состояния dpkg”, решить которую не получилось.
Просмотр содержимого deb-файла
Посмотреть содержимое установочного файла можно следующей командой:
dpkg --contents opera-stable_68.0.3618.125_amd64.deb
Установить собранный пакет рекомендую либо с помощью утилиты Gdebi, либо консольным вариантом:
sudo dpkg -i opera-stable_68.0.3618.125_amd64.deb
Для решения возможных проблем с зависимостями стоит воспользоваться следующей командой:
sudo apt install -f
Для более подробной информации по работает с утилитой dpkg-repack обратитесь к справочным страницам:
man dpkg-repack
Пользователи операционных систем Debian, Ubuntu и производных, если у вас не установлена версия браузера Opera с исправлением проблемы воспроизведения видео, то было бы интересно узнать ваш опыт проверки исправленной версии браузера. Скачать можно по ссылке: opera-stable_69.0.3686.36_amd64.deb
Как собрать бинарный deb пакет: подробное HowTo
Сегодня я расскажу на абстрактном примере как правильно создать *.deb пакет для Ubuntu/Debian. Пакет мы будем делать бинарный. Пакеты, компилирующие бинарники из исходников здесь не рассматриваются: осилив изложенные ниже знания, в дальнейшем по готовым примерам можно понять суть и действовать по аналогии 🙂
В статье не будет никакой лишней возни «вручную»: формат пакета эволюционировал в достаточно простую, а главное — логичную структуру, и всё делается буквально на коленке, с применением пары специализированных утилит.
В качестве бонуса в конце статьи будет пример быстрого создания собственного локального репозитория: установка пакетов из репозитория позволяет автоматически отслеживать зависимости, и конечно же! — устанавливать всё одной консольной командой на нескольких машинах 🙂
Для тех, кто не хочет вдаваться в мощную систему установки софта в Linux, рекомендую посетить сайт проги CheckInstall: она автоматически создаёт deb-пакет из команды «make install» 😉 А мы вместе с любопытными —
Источники
- Opennet:L Введение в создание пакетов для дистрибутива GNU Debian/Linux
- Debian.org: Debian Policy Manual — официальная
- Ubuntu Wiki: PackagingGuide/Basic
Подготовка
Зачем это всё?
- Скрипты, выполняющиеся до, после
и вместоустановки пакета 🙂 - Автоматическое управление конфигурационными файлами: пакет не позволит затереть старые конфиги новыми без спроса
- Работа с шаблонами: возможность задавать пользователю вопросы при установке (. )
- Изменение файлов других пакетов
Что потребуется
Конечно, для создания полноценного пакета хватит архиваторов tar, gz, ar, но можно исключить лишнюю возню, и воспользоваться инструментами, созданными для облегчения жизни 🙂
Ставим:
$ sudo apt-get install dpkg debconf debhelper lintian
Что мы будем делать
Для примера будет рассмотрен некий скрипт /usr/bin/super.sh. Не важно что внутри, главное — как он появится на правильном месте 🙂
Подготовка папки
В домашнем каталоге (или где удобно) создаём папку, в которой будут лежать все файлы будущего пакета: mkdir ~/supersh . Далее будем называть её корень пакета.
В корне пакета создаём папку «DEBIAN» (заглавными буквами, это важно!). Эта папка содержит управляющую генерацией пакета информацию, и не копируется на диск при установке пакета.
Также корневая папка пакета содержит будущий «корень диска»: при установке пакета все файлы (кроме папки «debian») распаковываются в корень /. поэтому наш скрипт должен лежать по такому пути, относительно корня пакета: «usr/bin/super.sh»
Белым по чёрному:
mkdir -p ~/supersh/DEBIAN # управляющая папка
mkdir -p ~/supersh/usr/bin # путь к скрипту
cp super.sh ~/supersh/usr/bin/ # копируем наш скрипт в нужное место
В итоге имеем:
supersh/DEBIAN/
supersh/usr/
supersh/usr/bin/
supersh/usr/bin/super.sh
Создание пакета: DEBIAN/*
Как я уже сказал, папка DEBIAN содержит файлы, используемые при установке. Здесь я опишу (с примерами) каждый файл.
Для создания полноценного пакета достаточно контрольного файла «control», все остальные используются либо для прикрепления текстовой информации (changelog, лицензия), либо для управления расширенными возможностями установки приложений.
Из описанных ниже файлов в папке DEBIAN/* выбираем необходимые, и заполняем согласно инструкции 🙂
В наше примере реально используется только обязательный DEBIAN/control.
DEBIAN/control: Основная информация
control — центральный файл пакета, описывающего все основные свойства. Файл — текстовый, состоящий из пар «Атрибут: значение». Можно использовать комментарии: символ «#» в начале строки (возможность была добавлена в версии dpkg >= 1.10.11, надеяться на комментарии не стоит :).
В таблице приведены все поля, определённые для контрольного файла. Обязательные поля выделены жирным: без них пакет не будет считаться составленным верно.
Атрибут | Описание | Примеры |
---|---|---|
— основные — | ||
Package: | Имя пакета: [a-zA-Z0-9-] — только латиница, цифры, и дефис. Имя используется при установке: apt-get install | Package: supersh |
Version: | Версия пакета (и проги внутри). Используется для определения «обновлять ли». Формат принят такой: — . Рекомендую всегда указывать версию пакета: при изменении структуры пакета цифра увеличивается на единичку. Допустимые символы достаточно вольные: можно использовать дату и буквы. Примеры смотрите сегодня в своём репозитории 🙂 |
Version: 1.0-1 Version: 2009.12.12-1 |
Provides | Имя приложения (возможно, виртуальное), регистрируемое в системе в результате установки этого пакета. Используется редко: в основном, если нужно изменить имя пакета, или если более одного пакета предлагают одинаковый функционал. Например, пакеты Apache и nginx предоставляют возможность демона httpd: Provides: httpd Вы наверняка сталкивались с ошибкой при попытке установки: «is a virtual package». Это оно и есть 🙂 |
Provides: supersh |
Maintainer | Имя и почта мэйнтейнера пакета: человека, который «дебианизировал» приложение. Формат произвольный, но принято имя | Maintainer: o_O Tync |
Architecture | Архитектура процессора, для которой предназначен пакет. Допустимые значения: i386, amd64, all, source all используется для скриптов: они же портативные, верно? 🙂 source используется для компилируемых пакетов с исходниками |
Architecture: all |
Section | Определяет задачу, для которой приложение обычно используется (группа приложений). Возможные значения: admin, base, comm, contrib, devel, doc, editors, electronics, embedded, games, gnome, graphics, hamradio, interpreters, kde, libs, libdevel, mail, math, misc, net, news, non-free, oldlibs, otherosfs, perl, python, science, shells, sound, tex, text, utils, web, x11 |
Section: misc |
Description | Описание пакета. Описание состоит из двух частей: короткое описание (70 символов) на той же строке, и длинное описание на последующих строках, начинающихся с пробела. В расширенном описании все переводы строки игнорируются. Для вставки \n используется одиночная точка. |
Description: Short. ␣Long ␣goes here. ␣. ␣New line. |
— связи и зависимости — | ||
Depends | Список пакетов через запятую, которые требуются для установки этого пакета. После имени пакета можно в круглых скобках указать ограничение на версию, используя операторы: >, =. Если оператор не указан — используется >= |
Depends: dpkg, libz (>= 1.2.3), jpeg (= 6b), png ( < 2.0) |
Pre-Depends | Список пакетов, которые требуются в процессе установки этого пакета. Эти зависимости могут потребоваться для скриптов установки пакета: например, пакет flash-installer требует wget Можно использовать ограничения на версию (см. Depends). |
Pre-Depends: wget (>= 1.0) |
Conflicts | Список пакетов, которые не могут быть установлены одновременно с этим. Установка не удастся, если хоть один из перечисленных пакетов уже будет установлен. |
Conflicts: crapscript |
Replaces | Список пакетов, файлы которых модифицируются этим пакетом. Требуется в случае создания «пакета-патча», изменяющего что-либо: в противном случае при замене файлов чужого пакета возникнет ошибка при установке. У меня, например, такой пакет патчит UT2004 и убирает звук наводящейся ракетницы 🙂 |
Replaces: ut2004 |
Recommends | Список пакетов, рекомендуемых к установке Эти пакеты не обязательны, но обычно используются вместе с текущим |
Recommends: superplatform |
Suggests | Список пакетов, предлагаемых к установке. Эти пакеты не обязательны, но с ними прога работает ещё лучше 🙂 По идее, менеджер пакетов должен предлагать установить их. |
Suggests: supersh-modules |
Build-Depends | (Только для Architecture: source) Список пакетов, требуемых для компиляции исходников. То же, что и Depends, но логически отделено. |
Build-Depends: cmake |
— экстра — | ||
Installed-Size | Размер файлов пакета в килобайтах. Просто цифра, округлённая до ближайшего целого. Используется менеджером пакетов для определения суммарного требуемого объёма на диске. |
Installed-Size: 3 |
Priority | Приоритет пакета: насколько он важен в системе Возможные значения: extra, optional, standard, important, required (такие пакеты не удаляются вообще!). |
Priority: optional |
Esssential | Если установить этот атрибут в значение «yes», пакет нельзя будет удалить. | Esssential: yes |
Origin | Строка: откуда получены программы в пакете. Обычно используется URL сайта автора, почта или имя. | Origin: brain |
X-Source | Полная ссылка на *.tar.gz архив с исходниками | X-Source: . *.tgz |
Да, вот такие солидные возможности у контрольного файла 🙂
А в нашем примере он выглядит так:
Package: supersh
Version: 1.0-1
Section: misc
Architecture: all
Depends: bash, sed (>= 3.02-8)
Maintainer: o_O Tync
Description: Super Shell Script
␣A super example script.
␣.
␣It does nothing 🙂
DEBIAN/copyright: © / лицензия
Текст лицензии. Файл не обязателен, но лучше подчеркнуть своё авторство 😉
DEBIAN/changelog: история изменений
Changelog в специальном формате: используется dpkg для получения номера версии, ревизии, дистрибутива и важности пакета. Лучше посмотреть в официальной документации 😉 а я лишь приведу пример:
supersh (1.0-1) stable; urgency=medium
— o_O Tync Sun, 13 Dec 2009 00:11:46 +0300
DEBIAN/rules: правила компиляции
Используется для управления компиляцией пакета: это когда Architeture: source 🙂
См. официальную документацию
DEBIAN/conffiles: список файлов конфигурации
Обычно пакеты содержат болванки конфигурационных файлов, например, размещаемых в /etc. Очевидно, что если конфиг в пакете обновляется, пользователь потеряет свой отредактированный конфиг. Эта проблема легко решается использованием папок типа «config.d», содержимое которых включается в основной конфиг, заменяя собой повторяющиеся опции.
Файл «DEBIAN/conffiles» позволяет решить проблему иначе: он содержит список файлов конфигурации (по одному на строке). Если в текущей версии пакета один из этих файлов обновляется, то пользователь получает предупреждение о конфликте версий конфигов, и может выбрать: удалить, заменить, или сделать merge.
С этой ситуацией наверняка сталкивался каждый линуксоид, копавшийся в конфигах 🙂 А ноги растут отсюда.
На каждой строке должен быть полный абсолютный путь до каждого конфига. Например:
/etc/supersh/init.conf
/etc/supersh/actions.conf
DEBIAN/dirs: список папок для создания
«Список абсолютных путей к папкам, которые требуются программе, но по каким-либо причинам не создаются.» — гласит официальная документация. На практике – здесь перечисляются все папки, так или иначе используемые программой: и где лежат бинарники, и которые используются программой.
По одной на строке. Например:
/var/log/supersh
/var/lib/supersh
Удобно использовать для создания нескольких пустых папок.
DEBIAN/menu: создание пунктов меню
Хитрый файл для создания пунктов меню. У меня он так и не заработал 🙂 Складывается ощущение, что его содержимое используется либо в необычных оконных менеджерах, либо в каком-то консольном меню… или же использовалось ранее и было забыто 🙂
Пример:
?package(supersh):needs=»text» section=»Applications/Programming» title=»Super Shell Script» command=»/usr/bin/super.sh»
TODO: узнать зачем нужно. Об этом написано в man5 menufile , честно говоря я не вникал 🙂
UPD: Правильный способ добавления пункта меню
Файл /DEBIAN/menu создаёт неизвестно что и непонятно где: элементы графического меню всё равно не создаются. Поэтому будем делать правильно 🙂
В /usr/share/applications видим кучку *.desktop файлов: это и есть пункты меню. Они представляют собой текстовые файлы с синтаксисом наподобие ini-файла. Открываем, учимся, делаем так же и кладём получившийся *.desktop файл в usr/share/applications/ . Иконка для него должна лежать в usr/share/pixmaps .
После этого в postinst скрипт нужно добавить выполнение команды обновления меню update-menus :
if [ «$1» = «configure» ] && [ -x «`which update-menus 2>/dev/null`» ] ; then
update-menus
fi
Работа со скриптами установки пакета будет рассмотрена далее.
Спасибо Condorious за наводку 🙂
DEBIAN/md5sums: контрольные суммы файлов
Используется для проверки целостности пакета. Важный файл.
Заполняется так (cwd=корень пакета):
$ md5deep -r usr > DEBIAN/md5sums
DEBIAN/watch: мониторинг сайта, откуда была скачана прога
Функция полезна, если Вы мэйнтейните от нескольких десятков пакетов, и уследить за всеми обновлениями сложно.
Файл содержит инструкции для программ uscan и uupdate. Используя эту возможность, можно следить за сайтом, откуда были получены исходники пакета, и обеспечивать контроль качества дистрибутива в целом.
Пример:
# Site Directory Pattern Version Script
ftp.obsession.se /gentoo gentoo-(.*)\.tar\.gz debian uupdate
И ещё пример для uscan(1):
version=3
madwimax.googlecode.com/files/madwimax-(.*)\.tar\.gz
Лучше почитайте официальную документацию, такие мощные вещи нечастно требуются простым смертным 🙂
DEBIAN/cron.d: инсталляция заданий cron
Файл содержит кусок crontab для инсталляции. Пример объясняет всё:
#
# Launches super.sh periodically
#
0 4 * * * root [ -x /usr/bin/super.sh ] && usr/bin/super.sh
DEBIAN/inid.d: init-скрипт
В этот файл пишется содержимое init-скрипта. О написании init-скриптов в инете можно найти
Скриптинг
Мы подошли к самому интересному: встраиванию скриптов в deb пакеты. Скрипты позволяют управлять установкой, переустановкой и удалением пакета, выполняя действия, которые нельзя сделать простым копированием файлов в правильные места. Это может быть скачивание дополнительных файлов (как это делает flash-installer), изменение существующих, а также — вывод интерактивных (GUI или ncurses) диалогов, позволяющих пользователю сконфигурировать пакет под себя: например, mysql спрашивает какой установить пароль для root.
Все скрипты выполняются от пользователя root (а как же ещё :). Также они получают аргументы (которые обрабатывать не обязательно), конкретизирующие на каком именно этапе находится установка. Подробнее об этом здесь.
DEBIAN/(preinst|postinst|prerm|postrm): скрипты установки
Всего можно создать до четырёх скриптов в одном пакете:
Скрипт | Назначение |
---|---|
DEBIAN/preinst | Выполняется перед установкой пакета: он может подготовить что-либо для успешной установки |
DEBIAN/postinst | Выполняется сразу после установки пакета: он настраивает установленный пакет так, чтоб он был готов к работе. Здесь также выполняется интерактивная конфигурация пакета: это делается при помощи dh_input и файла DEBIAN/templates |
DEBIAN/prerm | Выполняется непосредственно перед удалением пакета: обычно этот скрипт подчищает установочные пути пакета так, чтоб ничего лишнего не завалялось 🙂 |
DEBIAN/postrm | Выполняется сразу после удаления пакета: вычищает остатки |
Обратите внимание, что ошибки, возникающие в этих скриптах никак не логируются: ничего интереснее кода возврата скрипта нигде не сохраняется, и логирование необходимо делать вручную! Пользователи одного моего пакета терпели неудачу при установке на Linux Mint, и не было даже возможности попросить у них лог ошибок (которого нету) чтобы выдебагать причину 🙂
Рекомендую использовать в начале каждого скрипта следующую болванку: она будет сохранять в syslog все возникающие ошибки.
#!/bin/bash
set -e # fail on any error
set -u # treat unset variables as errors
# ======[ Trap Errors ]======#
set -E # let shell functions inherit ERR trap
# Trap non-normal exit signals:
# 1/HUP, 2/INT, 3/QUIT, 15/TERM, ERR
trap err_handler 1 2 3 15 ERR
function err_handler local exit_status=$
logger -s -p «syslog.err» -t «ootync.deb» «supersh.deb script ‘$0’ error code $exit_status (line $BASH_LINENO: ‘$BASH_COMMAND’)»
exit $exit_status
>
. Ваш код установочного скрипта .
exit 0
WARNING: болванка пока не тестировалась широко, проверьте лишний раз! На невозможность отладки наткнулся совсем недавно 🙂
DEBIAN/templates: шаблоны для диалогов
Как уже было сказано, в скрипте DEBIAN/config можно задавать пользователю вопросы: ввести строку, выбрать один из вариантов, поставить галочку,… Этим занимается «библиотека» bash функций debhelper пакета debconf, умеющая кроме этого ещё массу полезных вещей. Здесь их не рассматриваю 🙂
Файл DEBIAN/templates содержит данные, используемые при выводе диалоговых окон (GUI или ncurses). Файл содержит блоки, разделённые пустой строкой. Каждый блок определяет ресурсы, используемые в одном конкретном диалоговом окне.
Шапка для всех типов диалогов стандартная:
Template: supersh/template-name
Type: string
Default: Default-value
Description: Dialog-title
␣Dialog-text
Template — уникальный (в пределах одного пакета) идентификатор шаблона. Если в скрипте нужно вызвать определённый диалог — используется именно это имя.
Type — тип шаблона. Определены такие типы: string, password, boolean, select, multiselect, text, note, error.
Default-value — значение по умолчанию: пользователь может просто согласиться с ним.
Description — как и в контрольном файле, состоит из двух полей: короткое описание, и длинный текст. Первое — это заголовок «окна», второе — более развёрнутое описание того, что требуется от пользователя. Рекомендуется не использовать слов вроде «введите», а сразу суть: «Приветствие скрипта», «Точка монтирования»,…
Тип | Описание шаблона |
---|---|
string | Приглашение на ввод текстовой строки |
password | Приглашение на ввод пароля. Для этого типа шаблона нет значения Default по понятным причинам 🙂 |
boolean | Галочка 🙂 Имеет строковое значение «true» или «false» |
select | Возможность выбора одного из нескольких вариантов. Варианты предлагаются в дополнительном атрибуте шаблона: Choices: yes, no, maybe |
multiselect | Возможность выбора нескольких вариантов галочками. Варианты предлагаются в дополнительном атрибуте шаблона: Choices: sex, drugs, rock-n-roll |
text | Выводит на экран текст: некоторая не очень важная информация |
note | Выводит на экран текст: важная информация |
error | Выводит на экран текст: очень важная информация, критическая. |
Для шаблонов text, note, error также нет значения Default, так как они лишь отображают информацию 🙂
Поиграемся с следующим шаблоном:
Template: supersh/greeting
Type: string
Description: Welcome message
␣The message you wish the script to welcome you with.
Default: Greetings, my master!
Основы использования debconf и debhelper
Это лишь работоспособные наброски. В оригинале почитать о шаблонах и работе с ними можно здесь: man 7 debconf-devel 🙂
Чтобы использовать шаблоны в своём скрипте настройки DEBIAN/config, необходимо сначала подключить функции debhelper:
. /usr/share/debconf/confmodule . Также этот файл нужно подключить в скрипте postinst: иначе скрипт DEBIAN/config вообще не выполнится!
Эти функции доступны в пакете debconf, не забудьте включить его в зависимости!
Примитивный пример использования. Файл DEBIAN/config
#!/bin/bash -e
# Подключение команд debconf
. /usr/share/debconf/confmodule
case «$1» in
configure|reconfigure)
# Запрос
db_input medium «supersh/greeting» || true # инициализация
db_go || true # вывод запроса на экран
# Обработка ответа
db_get «supersh/greeting» # Получение значения в переменную $RET
greeting=»$RET»
echo «$greeting» > /etc/supersh/greeting.txt
;;
*)
echo «config called with unknown argument \`$1′» >&2
exit 1
;;
esac
# Запрос
db_input medium «supersh/greeting» || true # инициализация
db_go || true # вывод запроса на экран
# Обработка ответа
db_get «supersh/greeting» # Получение значения в переменную $RET
greeting=»$RET»
echo «$greeting» > /etc/supersh/greeting.txt
Здесь уже кроется неприятная засада: обратите внимание, что функции db_input передаётся приоритет диалога medium. Для debconf можно установить минимальный приоритет: диалоги с приоритетом ниже которого не отображаются, а берётся значение по умолчанию (Default шаблона)! Чтобы этого ТОЧНО не случилось — используем приоритет critical 🙂 Кроме того, при установке из GUI порог вывода вопросов выше, и многие из них не отображаются вообще.
Возможные приоритеты: low — всегда используется default, medium — дефаулт обычно вполне подходит, high — дефаулт нежелателен, critical — внимание пользователя жизненно важно.
|| true используется чтобы скрипт не помер из-за ключика «-e» переданного bash.
В этом скрипте тоже рекомендуется использовать ту болванку для отлова ошибок, иначе с распространяемым пакетом могут возникнуть проблемы при отладке 🙂
Все тонкости использования debconf (функции, способы, параметры, коды ошибок) описаны в достаточно многословном мане: man debconf-devel .
И последнее: при удалении пакета командой purge — debconf должен также вычистить из своей базы сведения о пакете. Например, он сохраняет выбор пользователя при запросах db_input.
Чтобы вычистить эти данные, нужно в postinst-скрипт добавить следующее:
if [ «$1» == «purge» ] && [ -e /usr/share/debconf/confmodule ] ; then
. /usr/share/debconf/confmodule
db_purge
fi
Собираем пакет! 🙂
Ура! Все нужные файлы созданы, лежат по нужным папочкам. Теперь пора собирать пакет 🙂
Первое, что нужно сделать — это рекурсивно выставить всем файлам в корне пакета пользователя и группу root:root (или другие, если потребуется). Это нужно затем, что файлы пакета упаковываются в tar.gz архив который сохраняет и права доступа к файлам, и владельца. Потому нужно выполнить:
$ sudo chown -R root:root .
Однако делать это не обязательно. Есть отличная команда fakeroot которая при создании архива подменит владельца файлос root-ом.
В нашем примере, скрипт должен иметь бит выполнимости.
Потом выходим на папку назад, чтоб было видно корневую папку пакета, и пакет создаётся лёгким пинком сам:
$ fakeroot dpkg-deb —build supersh
Созданный пакет необходимо переименовать, чтобы он соответствовал порядку именования *.deb пакетов: __.deb
$ mv supersh.deb supersh_1.0-1_all.deb
Всё, пакет готов!
Автоматическая проверка пакета
Существует утилита lintian, позволяющая проверить пакет и выявить типичные ошибки в его структуре. Делается это так:
$ lintian supersh_1.0-1_all.deb
Установка пакета
$ sudo dpkg -i supersh_1.0-1_all.deb
Создаём собственный репозиторий пакетов
Теперь у нас есть собственный пакет. Когда их будет несколько, и тем более — с зависимостями, окажется, что намного удобнее быстренько поднять собственный локальный микро-репозиторий, и включить его в список источников менеджера пакетов 🙂 Здесь я опишу быстрый HowTo «как создать свой репозиторий». Идею будет легко развить, почитывая соответствующую документацию 🙂
Сперва установим помощника:
$ sudo apt-get install reprepro
Описание будущего репозитория
Центр репозитория — его описание. Главное в нём — список компонент репозитория. Мы создадим компоненты «soft» и «games».
Выберите папку для будущего репозитория. Все действия производятся из её корня.
Создаём файл conf/distributions следующего содержания:
Description: my local repository
Origin: Ubuntu
Suite: testing
AlsoAcceptFor: unstable experimental
Codename: karmic
Version: 5.0
Architectures: i386 amd64 source
Components: soft games
UDebComponents: soft games
В нашем деле создания простого репозитория все поля не играют принципиальной роли, и используются лишь для визуального определения «что есть что» 🙂
Создание репозитория
Репозиторий описан! Теперь сгенерируем болванку на основе описания. Команды выполняются в корне репозитория:
$ reprepro export
$ reprepro createsymlinks
И добавим готовый репозиторий в /etc/apt/sources.list:
deb file:///path/to/repo/ karmic soft games
Этот репозиторий можно также расшарить при помощи веб-сервера.
Управление пакетами в репозитории
В корень репозитория кладём *.deb файлы для добавления, и добавляем их в компоненту soft дистрибутива karmic:
reprepro -C soft includedeb karmic *.deb
теперь пакеты доступны из менеджера пакетов 🙂
Удаление пакетов:
reprepro -C soft remove karmic supersh
Финиш
- Создание source пакетов, компилирующих исходники: на примере Zabbix об этом отлично рассказал хабраюзер mahoro в своей статье
- Debconf, debhelper в конфигурационных скриптах: читаем маны по debconf-devel и debhelper. Они также позволяют создать скелет пакета командой dh_make.
- Продвинутые способы создания документации в пакетах: файлы DEBIAN/docs, DEBIAN/manpage.*
- Создание init скриптов
- Управление заданиями cron
- Подписывание репозитория ключём gpg
UPD: @ICD2 подсказывает, что есть GUIшная прога для создания пакетов: GiftWrap.
P.S. В статье наверняка встречаются неточности и ошибки. Давайте причешем её вместе! 🙂
Сборка пакетов
Дистрибутивы, основанные на Debian – это не только отличная система управления пакетами APT, которая сама разрешает зависимости, но и удобные инструменты для создания пакетов и своих репозиториев. Если уж вы решились собрать программу из исходников, то советую ещё изучить, как дебианизировать исходники. Это отнимет чуть больше времени, чем стандартное
./configure && make && make install
но зато позволит сохранить систему в чистоте. Удалить программы, установленные командой make install, можно только командой
make uninstall
но не все исходники это поддерживают, а что ещё чаще — исходники удаляют после установки, тогда удалить программу можно только вручную. Но чтобы это сделать, нужно точно знать что и куда установилось. А это уж точно никто не знает, кроме самих разработчиков программы (ну или тех, кто более-менее разбирался в исходниках программы).
Ну и что? Главное — работает!
APT не знает ничего о программах, установленных вручную. Соответственно, могут быть конфликты, или просто непонятные ошибки.
Очень часто исходники по умолчанию «рассчитаны» на определённый дистрибутив, или, наоборот, рассчитаны только на установку из исходников, при этом выполняются разного рода «удобные» настройки в конфигурационных файлах. Так, например, очень любят прописывать mime-типы. Но проблема в том, что переводы разные бывают и в Nautilus может выскочить ошибка
"Имя файла показывает, что файл является типом файла . Содержимое файла показывает, что файл является файлом типа "
и документ не будет открываться. Таких «недочётов» может быть очень много. А теперь, если представить что это удалить нельзя, поскольку пользователь не запоминал что и куда поставилось, наступает паника и как результат — переустановка.
Но как быть, если программу хочется поставить, а версия в deb-пакете устарела, или такой вообще нет?
Есть два выхода:
Использовать программу checkinstall . Она собирает всё в один пакет. К сожалению, она позволяет решить только вопрос с удалением программы. И даже если APT будет знать, что программа установлена, он в лучшем случае сообщит, что есть конфликт файлов,
файл /some/path/to/some/file уже есть в пакете "имя пакета собранного с помощью checkinstall"
Чаще всего такие случаи очень корректно разрешаются путём удаления конфликтного пакета. Но на разбор ситуации уйдёт некоторое время.
Cобрать нормальный пакет, как это делают мантейнеры. В котором будет корректная версия, зависимости и расположение файлов будет соответствовать политике дистрибутива. Вижу вам всё ещё интересно . Это радует.
Классификация случаев сборки
Возможны следующие случаи сборки пакетов:
сборка из исходников;
сборка из бинарных файлов;
исходники или бинарные файлы берутся:
не из репозитория;
из репозитория другого дистрибутива;
из репозитория другого выпуска Ubuntu, из PPA или из Debian;
из репозитория текущего выпуска Ubuntu;
недоступна;
берётся из репозитория Ubuntu, из PPA или из Debian:
из другой версии программы;
из текущей версии программы:
не из репозитория текущего выпуска Ubuntu;
из репозитория текущего выпуска Ubuntu;
ни в репозитории Ubuntu текущего выпуска, ни в PPA нет нужной версии программы;
доступная версия программы по каким-либо причинам не устраивает (не устраивает код или данные программы, параметры конфигурации или управляющая информация пакета);
и то, и другое.
Сборка из исходников
Дано: некий исходник gcoolprog-0.5.3.tar.bz2. Нужно из него собрать пакет.
Решение: ниже идёт вариант, как я обычно поступаю в таком случае.
Первым делом смотрю, нет ли deb-пакета той же версии, но допустим под Debian. Если есть делаю так: есть нужная версия пакета в репозитории debian или в будущем релизе Ununtu
Если нет той же версии, но есть предыдущей. Тут можно сказать как повезёт, если изменения в исходниках не коснулись положения файлов, то скорее всего дебианизация от старого пакета подойдёт, нужно лишь сменить версию. Теперь вариант в репозитории есть пакет предыдущей версии.
Ну и самый страшный случай — нигде никаких deb-пакетов нет, только tar.gz и rpm. Ни в коем случае не использовать rpm! Делаем по первому варианту.
Что необходимо
Полное Руководство начинающего разработчика Debian доступно тут.
К сожалению, на русском, информация немного устарела, свежая инструкция доступна на английском. Но принципы не изменились, поэтому если интересны детали лучше прочитать руководство от и до.
Нам понадобятся как минимум программы, устанавливаемые командой
sudo apt-get install autoconf automake libtool autotools-dev dpkg-dev fakeroot
Можно так же autobook — это документация по утилитам GNU Autoconf , Automake , и Libtool . Ну и конечно то, что требуют сами исходные коды для корректной сборки.
Создание ключа шифрования
Этот шаг не обязателен, его можно пропустить.
Чтобы создать ключ, зайдите в Приложения → Стандартные → Пароли и ключи шифрования. В открывшемся окне, в меню Ключ → Новый ключ, выбираем ключ pgp. Заполняем поля Полное имя и Электронный адрес.
В мире свободного программного обеспечения, для предотвращения «краж» или «подделок», принято подписывать свои «ценные» вещи электронным ключом, открытая часть которого хранится на общедоступных серверах и позволяет другим пользователям легко выяснить подлинность и целостность той или иной вещи.
Поэтому отнеситесь к созданию ключа очень ответственно.
Никто вас не заставляет вписывать сюда реальные имя и фамилию, или ещё какие-нибудь личные данные, но если вас не разыскивает интерпол — думаю указать фамилию и имя будет верным решением, хотя можно и просто свой ник В общем, решайте сами. А вот почтовый адрес укажите реальный, и который вы не поменяете.
Можно завести ящик, если ещё нет, на каком-нибудь популярном почтовом сервере: например, gmail.com или yandex.ru .
Это позволит в будущем легко связаться с вами человеку, который вас не знает, но по той или иной причине встретил «вещь», подписанную вами.
Далее вас спросят ввести пароль, как дополнительную защиту. Он может быть полезен, если вы будете использовать закрытый ключ на машинах, которым вы не можете на 100% доверять. Обратная сторона — вам придётся вводить пароль каждый раз, как только вы будете что-то подписывать.
Хотя последняя версия программы seahorse имеет демон, который автоматически запускается в сеансе GNOME, и умеет «запоминать пароль» на время сеанса, но пока не все программы умеют с ней работать.
Итак, вы создали ключ — теперь его можно будет использовать при создании пакетов.
Для этого, в файл ~/.bashrc, или в другой стартовый скрипт, вашего любимого шелла (для zsh ~/.zshrc), нужно вписать переменные
export DEBEMAIL=ваш@имейл
На основании e-mail будет искаться ключ в pgp, при подписи пакета.
Нужно завершить сеанс и зайти заново, чтобы изменения вступили в силу.
Помните, что если вы бэкпортируете пакет, дебианизированный не вами, обязательно нужно изменить версию командой
dch -i
для того, чтобы в изменения вписался ваш e-mail. А для того, чтобы ваш открытый ключ попал на сервер, необходимо в настройках «seahorse → Пароли и ключи шифрования», настроить соединение с сервером публичных ключей.
Для этого, в меню Правка→Параметры на закладке Публикация ключей необходимо поставить галку Публиковать ключи….
Теперь можно выбрать ключ и в меню по правой кнопке выбрать Синхронизировать и опубликовать ключи.
Дебианизация недоступна
Итак, у нас есть только gcoolprog-0.5.3.tar.gz.
Обычно я выполняю следующие действия:
Предварительно подготавливаю рабочую директорию
mkdir ~/src/gcoolprog mkdir ~/src/gcoolprog/0.5.3 cd ~/src/gcoolprog/0.5.3 wget "http://" #можно конечно и просто через браузер скачать но обычно так быстрее
Получаем файл gcoolprog-0.5.3.tar.gz. Распакуем его перейдем в полученный каталог:
tar zxvf gcoolprog-0.5.3.tar.gz cd gcoolprog-0.5.3
Для корректной сборки нужно, чтобы корневая директория содержала не только название, но и версию!
Ниже будем считать директорию ~/src/gcoolprog/0.5.3/gcoolprog-0.5.3 корневой директорией исходников.
Далее выполняем «черновую» сборку. Т.е. сконфигурируем и соберем приложение, без его установки:
./configure --prefix=/usr && make
Если команда выполнилась успешно, то осталось только дебианизировать.
Дебианизация
Ничего страшного в этом нет, как я уже говорил есть скрипты, которые сильно упрощают этот процесс.
Вообще смысл всей этой процедуры — создать директорию debian в корне исходников, с нужными файлами конфигурации и скриптом(ами).
Для этого, в корне исходных текстов, выполним
dh_make --createorig
На что мы должны получить следующий диалог
Type of package: single binary, multiple binary, library, kernel module or cdbs? [s/m/l/k/b] s Maintainer name : denis Email-Address : Ubuntu_user@mail.ru Date : Mon, 13 Aug 2007 12:40:33 +0400 Package Name : gcoolprog Version : 0.5.3 License : blank Type of Package : Single Hit to confirm:
Тут мы указываем сформировать пакет, для одиночного бинарного файла.
Но мы с вами молодцы и всё у нас прошло без ошибок — появился каталог debian в корне исходников, посмотрев его содержимое, Вы увидите кучу файлов (расширение .ex) с примерами на все случаи жизни.
Будем считать, что программа у нас простая – обычно ни один из этих файлов не нужен.
Первым делом, нужно добавить описание программы в файле debian/control
Description:
Вместо и (без угловых кавычек) нужно вписать описание, что это за программа.
Именно эти сведения увидит пользователь, когда посмотрит описание пакета.
Второй момент — это поправить файл debian/rules
в секции binary-arch: нужно раскомментировать (т.е. убрать # в начале строки)
dh_install
без этого мы получим пустой пакет.
Иногда debian/rules содержит лишь:
Что приемлемо с использованием debhelper.
Этих настроек будет достаточно для сборки пакета с одной программой, которая не содержит разделяемых библиотек, т.е. только бинарник в /usr/bin и данные в /usr/share.
Сборка пакета
Теперь, соберём пакет:
dpkg-buildpackage -rfakeroot
В директории выше, т.е. в ~/src/gcoolprog/0.5.3, мы получим файлы
gcoolprog_0.5.3-1.diff.gz gcoolprog_0.5.3-1_i386.changes gcoolprog_0.5.3-1_i386.deb gcoolprog_0.5.3.orig.tar.gz
Вот теперь мы можем установить пакет
dpkg -i *.deb
Дебианизация берётся из репозитория Ubuntu, из PPA или из Debian
Дебианизация берётся из другой версии программы
В этом случае, очень удобно взять дебианизацию оттуда и поправить для новой версии.
Как я уже сказал, возможно нам повезёт и достаточно будет только сменить версию. Но не будем гадать.
Ниже я не буду комментировать то, что описано в предыдущем решении.
Предварительно подготовим рабочую директорию
mkdir ~/src/gcoolprog mkdir ~/src/gcoolprog/0.5.3 cd ~/src/gcoolprog/0.5.3 wget "http://"
получаем файл gcoolprog-0.5.3.tar.bz2
bunzip2 gcoolprog-0.5.3.tar.bz2 gzip gcoolprog-0.5.3.tar mv gcoolprog-0.5.3.tar.gz gcoolprog_0.5.3.orig.tar.gz
теперь распаковываем его
tar zxvf ./gcoolprog_0.5.3.orig.tar.gz
скачиваем предыдущую версию с http://packages.ubuntu.com или http://packages.debian.org, файл gcoolprog_0.5.1.diff.gz (в самом низу в секции More Information on gcoolprog)
wget "http://archive.ubuntu.com/ubuntu/pool/universe/g/gcoolprog/gcoolprog_0.5.1.diff.gz" gunzip gcoolprog_0.5.1.diff.gz patch -p0 ./gcoolprog_0.5.1.diff
~/src/gcoolprog/0.5.3/gcoolprog-0.5.1/debian
копируем каталог gcoolprog-0.5.1/debian в директорию ~/src/gcoolprog/0.5.3/gcoolprog-0.5.3
cp -a ~/src/gcoolprog/0.5.3/gcoolprog-0.5.1/debian ~/src/gcoolprog/0.5.3/gcoolprog-0.5.3
дальше нам нужно изменить версию командой
dch -i
этой командой изменяется файл debian/changelog например увидим
gcoolprog (0.5.1-1ubuntu2) feisty; urgency=low * -- denis ubuntu_user@mail.ru> Mon, 13 Aug 2007 14:13:27 +0400
но поскольку у нас версия 0.5.3, то нужно изменить значения на
gcoolprog (0.5.3-1ubuntu1) feisty; urgency=low * New upstream release. -- denis ubuntu_user@mail.ru> Mon, 13 Aug 2007 14:13:27 +0400
сохраните изменения. Теперь можно выполнить команду сборки в пакет.
dpkg-buildpackage -rfakeroot
cd .. ls -1 gcoolprog_0.5.3-1.diff.gz gcoolprog_0.5.3-1_i386.changes gcoolprog_0.5.3-1_i386.deb gcoolprog_0.5.3.orig.tar.gz dpkg -i *.deb
Дебианизация берётся из текущей версии программы
Дебианизация берётся не из репозитория текущего выпуска Ubuntu
Для Debian нужно использовать сайт http://packages.debian.org, для Ubuntu — http://packages.ubuntu.com. Тогда, например, в Ubuntu ищем пакет gcoolprog в репозитории будущего релиза.
Предварительно подготовим рабочую директорию
mkdir ~/src/gcoolprog mkdir ~/src/gcoolprog/0.5.3 cd ~/src/gcoolprog/0.5.3
теперь скачиваем три файла
wget http://archive.ubuntu.com/ubuntu/pool/universe/g/gcoolprog/gcoolprog_0.5.3-1.dsc wget http://archive.ubuntu.com/ubuntu/pool/universe/g/gcoolprog/gcoolprog_0.5.3.orig.tar.gz wget http://archive.ubuntu.com/ubuntu/pool/universe/g/gcoolprog/gcoolprog_0.5.3-1.diff.gz
или тоже самое, но одной командой
dget http://archive.ubuntu.com/ubuntu/pool/universe/g/gcoolprog/gcoolprog_0.5.3-1.dsc
из пакета devscripts
затем распакуем командой
dpkg-source -x ./gcoolprog_0.5.3-1.dsc
получим каталог gcoolprog-0.5.3.Перейдём в него и сменим версию:
cd gcoolprog-0.5.3 dch -i
gcoolprog (0.5.3-1ubuntu1) feisty; urgency=low * backport from gutsy -- denis ubuntu_user@mail.ru> Mon, 13 Aug 2007 14:13:27 +0400
теперь можно собирать пакет
dpkg-buildpackage -rfakeroot
cd .. ls -1. gcoolprog_0.5.3-1.diff.gz gcoolprog_0.5.3-1_i386.changes gcoolprog_0.5.3-1_i386.deb gcoolprog_0.5.3.orig.tar.gz dpkg -i *.deb
Дебианизация берётся из репозитория текущего выпуска Ubuntu
В случае, когда для нужной версии программы имеется пакет в репозитории текущего выпуска Ubuntu, но он по каким-либо причинам не устраивает и в его исходники нужно внести изменения (например, применить какой-нибудь патч) и пересобрать, основываясь на уже имеющейся в пакете дебианизации, можно поступить следующим образом.
Для сборки понадобятся следующие пакеты: build-essential devscripts fakeroot. Потребуются также пакеты для разработки, мы их установим в дальнейшем.
cd ~/src apt-get source gcoolprog
apt-get source скачивает исходники из репозитория Ubuntu в текущую директорию. Многие пакеты в репозитории имеют общие друг с другом исходники, поэтому кроме исходников выбранного пакета могут скачаться и исходники других пакетов (общие для нескольких пакетов исходники).
Далее вносим изменения в исходники и собираем из них обратно пакеты.
Устанавливаем необходимые для сборки пакеты для разработки:
sudo apt-get build-dep gcoolprog
cd gcoolprog-0.5.3 debuild -b -us -uc
debuild следует запускать в директории исходников. Параметры -b -us -uc передаются программе dpkg-buildpackage. Первый требует собирать только бинарные пакеты, второй и третий — не подписывать цифровой подписью, соответственно, пакет исходников и файл .changes. Получившиеся в результате сборки пакеты будут в директории на один уровень выше.
Сборка из бинарных файлов
Ниже идёт пример как можно поступить в случае, если доступен только deb-пакет и нет его дебианизированных исходников.
Для начала советую прочитать это. И это. Тут полная документация на русском.
Предположим, что работаем в каталоге ~/tmp. Создадим подкаталог ~/tmp/someprog, чтобы распаковать файлы какого-нибудь пакета, нужно выполнить
dpkg -x ~./tmp/some-prog-123.deb ./someprog
Для того, чтобы извлечь контрольную информацию, выполним
mkdir ~/tmp/someprog/DEBIAN dpkg -e ~/tmp/some-prog-123.deb ./someprog/DEBIAN
ну а теперь, чтобы всё это собрать обратно в пакет, нужно выполнить
dpkg -b ./someprog ~/tmp/some-prog-123-new.deb
В каталоге ~/tmp/someprog/DEBIAN содержатся файлы, описывающие, что это за пакет, от чего он зависит, и контрольные суммы файлов, находящихся в нём. Для того, чтобы собрать свой пакет, нужно поместить файлы в каталоге ~/tmp/someprog так, как будто это корневой каталог.То есть, если нужно, чтобы файл установился в /usr/bin,нужно его поместить в каталог ~/tmp/someprog/usr/bin, ну и, соответственно, если что-то должно лежать в /etc, то в ~/tmp/someprog/etc и т.д.
Затем в ~/tmp/someprog создать каталог DEBIAN, обязательно большими буквами, и в нём файл ~/tmp/someprog/DEBIAN/control, в этом файле описывается название пакета, его зависимости и описание, формат очень простой. Например:
Package: libcurl3 Version: 7.15.2-2 Section: libs Priority: optional Architecture: i386 Depends: libc6 (>= 2.3.5-1), libcomerr2 (>= 1.33-3), libidn11 (>= 0.5.18), libkrb53 (>= 1.4.2), libssl0.9.8 (>= 0.9.8a-1),zlib1g (>= 1:1.2.1), ca-certificates Suggests: libldap2 Replaces: libcurl2 ( Source: curl Description: Multi-protocol file transfer library libcurl is designed to be a solid, usable, reliable and portable multi-protocol file transfer library. . SSL support is provided by OpenSSL. To enable LDAP support package libldap2-dev is required. . This is the shared version of libcurl. . Homepage: http://curl.haxx.se
Ну а теперь собрать:
dpkg -b ./someprog some-prog-123-new.deb
Этой информации достаточно, чтобы собрать/пересобрать простенький пакет. На самом деле можно ещё запускать скрипты при установке пакета, при его удалении и много чего ещё, что нужно нормальному maintainer’у.
Ссылки
Некоторые команды мне подсказал Александр Герасёв http://gq.net.ru/2007/03/16/building-deb-packages/
Официальное полное руководство на Русском http://www.debian.org/doc/maint-guide/
Уголок разработчика Debian http://www.debian.org/devel/
Хороший цикл статей Цикл статей по сборке RPM и DEB пакетов , правда автор предвзято относится к сборке deb-пакетов, но если на это не обращать внимания, вполне приличный обзор.
Описание процесса сборки пакета deb
Обновлено: 26.05.2023 Опубликовано: 11.08.2021
Данная инструкция является шпаргалкой по сборке пакетов для deb-систем (Debian, Ubuntu, Mint и так далее). Мы рассмотрим пример работы с исходниками nginx, а также разберем подробнее опции, которые можно задействовать при сборке. На практике, данное действие не имеет смысла, так как уже собранный nginx можно получить на сайте разработчика или в репозитории системы, но для нас важно понять процесс сборки, после чего можно будет применить данные знания для своих проектов.
Подготовка системы
Процесс сборки требует установки дополнительных компонентов, что приводит к скоплению мусора из ненужных пакетов. Рекомендуется делать сборку на отдельном компьютере или в контейнере Docker. Подробнее об установке последнего в инструкции Установка Docker на Linux. Независимо от среды, в которой мы будем собирать пакеты, необходимо выполнить предварительные настройки. 1. Установка пакетов:
apt update
apt install dpkg-dev devscripts equivs wget
- dpkg-dev — содержит набор инструментов для работы с исходными файлами для пакетов deb.
- devscripts — набор скриптов для сборки пакетов.
- equivs — необходим для запуска утилиты mk-build-deps для установки зависимых пакетов.
- wget — утилита для загрузки файлов по http. Нужна для загрузки архивов с исходниками.
2. Создание пользователя.
Делать готовые установочные сборки пакетов очень опасно от пользователя root. Если мы допустим ошибку с путями, файлы могут перетереть или удалить важные для работы директории. Стоит создать отдельного пользователя и работать под ним. Однако, если мы работаем в специальной виртуальной среде или контейнере Docker, нам это не страшно. Тогда данный пункт можно пропустить и работать из-под root.
useradd builder -m
* в данном примере мы создадим пользователя builder. Опция -m сразу создаст домашний каталог для пользователя.
Теперь заходим под данным пользователем — последующие команды мы будем выполнять от него:
3. Создадим каталог, в котором будет происходит сборка:
mkdir -p debbuild
Перейдем в debbuild:
Мы готовы к сборке.
Сборка из исходников
В нашем примере мы возьмем исходники для сборки nginx (для выполнения configure, make, make install . ) и соберем из них свой пакет для установки NGINX. Процесс будет разбит на несколько этапов:
- Предварительная настройка.
- Создание файлов с инструкциями для сборки пакета.
- Выполнение сборки и проверки.
Рассмотрим каждый из этапов подробнее.
Подготовка
Создадим каталог с названием собираемого приложения (с учетом версии):
mkdir -p nginx-1.20.1/debian
* в нем обязательно каталог debian.
Перейдем в созданный каталог:
Теперь создадим несколько важных файлов.
Создание файлов сборки (основные)
Для выполнения сборки нужно создать, минимум, 4 файла.
1. Control-файл.
Это основной файл с описанием процесса сборки. Вводим:
Пример для нашего случая:
Source: nginx
Section: misc
Priority: optional
Maintainer: Dmitriy Moks
Build-Depends: libpcre3-dev,
zlib1g-dev
Standards-Version: 1.20.1
Homepage: https://nginx.org
Package: nginx
Architecture: amd64
Provides: nginx
Description: NGINX packages.
The description can be written in several lines.
Each line have to be 73 chars maximum.
* значения для опции Build-Depends задаются экспериментально — лучше всего попробовать сначала собрать требуемый пакет вручную, чтобы понять, какие потребуется доустановить пакеты. Рекомендуется это делать на чистой системе, чтобы не получить искаженный результат (на используемой системе уже могут быть пакеты, которых не будет на другом компьютере, где будет происходить сборка).
* более подробное описание файла control представлено ниже.
2. Файл changelog.
В данном файле описывается история изменений пакета. Также сборщик берет из этого файла номер версии и релиза.
Создаем файл командой:
nginx (1.20.1) stable; urgency=medium
* Initial release
— Dmitriy Mosk Tue, 03 Aug 2021 17:34:42 +0300
* в файле указано, что первые изменения внес Dmitriy Mosk 03 августа. Для начала сборки этого будет достаточно. Описание ниже.
3. Файл rules.
Описываем правила компиляции пакета во время его сборки. Создаем файл:
#!/usr/bin/make -f export DH_VERBOSE = 1 url='http://nginx.org/download/nginx-1.20.1.tar.gz' build_dir='nginx' override_dh_auto_clean: if [ ! -f $(build_dir) ]; then rm -rf $(build_dir); fi mkdir $(build_dir) dh_auto_clean override_dh_auto_configure: wget $(url) -O $(build_dir).tar.gz tar -xzf $(build_dir).tar.gz -C $(build_dir)/ --strip-components=1 rm -f $(build_dir).tar.gz cd $(build_dir) && ./configure override_dh_usrlocal: %: dh $@ --sourcedirectory=$(build_dir)/
* важно обратить внимание на факт, что содержимое файла может сильно отличаться в зависимости от того, что мы собираем и какой версии собираемое программное обеспечение. В данном примере мы создали файл для независимой работы — сборщик сам скачает исходник и распакует его в рабочий каталог (в данном примере, nginx). Также мне пришлось переопределить этап dh_usrlocal, так как на нем возникала ошибка, связанная с невозможностью удалить каталог командой rmdir.
* в нашей системе должен быть установлен wget, как и все остальные утилиты, которыми мы захотим воспользоваться.
* более подробное описание файла rules ниже.
4. Файл compat.
Указываем на уровень совместимости с debhelper (вспомогательный инструмент для сборки пакетов). Создаем файл:
* нам необходимо использовать версию в соответствии с версией Debian, на основе которой организован дистрибутив Linux, в котором идет сборка — в нашем примере 9. Сама по себе сборка без данного файла (или при указании версии ниже текущей, на дистрибутиве которого собирается пакет) запустится, но быстро остановится с ошибкой dh_auto_clean: Compatibility levels before 9 are deprecated (level X in use), где Х — текущий уровень совместимости.
Дополнительные файлы сборки
Данные файлы не являются обязательными. Они могут увеличить возможности собираемого пакета, а также нужны для нашего удобства.
1. Файл postinst.
Является скриптом, который будет запущен после установки пакета на целевой системе. Любые постинсталляционные настройки можно выполнить с его помощью, например:
#!/bin/sh
# postinst script for dmosk
#
# see: dh_installdeb(1)
* в данном примере мы просто создадим учетную запись dmosk. Опция set -e говорит о том, что при возникновении ошибки, необходимо сразу прервать работу скрипта.
Может быть использован более сложный сценарий с обработкой аргументов, например:
case «$1» in
configure)
systemctl is-enabled —quiet nginx && systemctl disable nginx
;;
upgrade)
systemctl is-active —quiet nginx
;;
*)
echo «postinst called with unknown argument \`$1′» >&2
exit 1
;;
esac
* таким образом, при установке приложения посредством, например, команды apt upgrade, после инсталляции будет выполнена только команда sytemctls is-active —quiet nginx.
2. Файл postrm.
Это скрипт, который выполнится после удаления пакета:
#!/bin/sh -e
# postrm script for dmosk
#
# see: dh_installdeb(1)
case «$1» in
purge|remove|abort-install|disappear)
rm -rf /var/log/app
rm -rf /opt/app/test
;;
*)
echo «postrm called with unknown argument \`$1′» >&2
exit 1
;;
esac
* в данном примере мы предположили, что после удаления нужно удалить 2 каталога /var/log/app и /opt/app/test.
3. Файл preinst.
Скрипт выполнения перед установкой пакета.
4. Файл prerm.
Скрипт выполнения перед удалением пакета.
#!/bin/sh -e
# prerm script for dmosk
#
# see: dh_installdeb(1)
case «$1» in
purge|remove|abort-install|disappear)
systemctl is-active —quiet nginx && systemctl stop nginx &>/dev/null || :
;;
*)
echo «prerm called with unknown argument \`$1′» >&2
exit 1
;;
esac
Сборка пакета
У нас созданы все необходимые файлы, выполнены предварительные действия, и мы готовы к сборке.
Проверяем, что у нас установлены необходимые пакеты и, при необходимости, установим их:
* команда является частью пакета equivs, который мы установили в начале инструкции. Она читает опцию Build-Depends файла control и устанавливает необходимые пакеты.
Для запуска утилиты в тихом режиме (без запросов на подтверждения) команду можно ввести так:
echo yes | mk-build-deps -ri
Выполним сборку командой:
debuild -us -uc -b
Если мы все сделали правильно, в конце мы увидим что-то на подобие:
W: nginx: missing-depends-line
E: nginx: dir-in-usr-local usr/local/nginx/logs/
E: nginx: dir-in-usr-local usr/local/nginx/sbin/
E: nginx: file-in-usr-local usr/local/nginx/sbin/nginx
W: nginx: file-in-unusual-dir usr/local/nginx/sbin/nginx
Finished running lintian.
Пакет сформирован и должен находится в директории на уровень ниже:
Среди списка файлов мы должны увидеть пакет с нашим названием:
nginx-1.20.1 nginx_1.20.1_amd64.build nginx_1.20.1_amd64.changes
nginx-dbgsym_1.20.1_amd64.deb nginx_1.20.1_amd64.buildinfo nginx_1.20.1_amd64.deb
Пример сборки из исходных файлов
Данный пример мы не будем рассматривать подробно. Только покажем файл с правилами для сбоки нового пакета из файлов с исходниками, которые есть на нашем компьютере.
Предположим, у нас есть свое приложение, состоящее из нескольких рабочих файлов, документации и скриптов и нам нужно его упаковать в пакет для установки в каталог /opt.
И приведем его к виду:
#!/usr/bin/make -f #export DH_VERBOSE = 1 build_dir=debian/PKG_NAME PKG_PREFIX=/opt/PKG_NAME override_dh_install: mkdir -p $(build_dir)/$(PKG_PREFIX) || : mkdir -p $(build_dir)/usr/share/doc/PKG_NAME || : cp /PKG_SOURCE/install/* $(build_dir)/$(PKG_PREFIX)/ cp /PKG_SOURCE/DOC/* $(build_dir)/usr/share/doc/PKG_NAME/ cp /PKG_SOURCE/scripts/*.sh $(build_dir)/$(PKG_PREFIX)/ override_dh_fixperms: dh_fixperms find $(build_dir)/ -type f -exec chmod 644 <> \; find $(build_dir)/ -type d -exec chmod 755 <> \; chmod +x $(build_dir)/$(PKG_PREFIX)/*.sh chown root:root -R $(build_dir) %: dh $@
Остальные файлы и запуск сборки были нами рассмотрены выше. Мы же разберем подробнее, что происходит в текущем примере.
Предполагается, что исходные файлы нашего приложения находятся в каталоге /PKG_SOURCE. Нам нужно, чтобы рабочий пакет выполнял установку файлов в каталог /opt/PKG_NAME, а именно:
- Все файлы из папки /PKG_SOURCE/install.
- Все скрипты из папки /PKG_SOURCE/scripts.
Документацию из каталога /PKG_SOURCE/DOC мы должны поместить в /usr/share/doc/PKG_NAME (где PKG_NAME — название для нашего пакета).
Теперь по сценарию сборки. Мы переопределили поведение dh_install — создали каталоги для размещения файлов и документации. Обратите внимание, что сборка идет относительно базового каталога debian/.
Также мы немного поменяли выполнение dh_fixperms, а именно, всем файлам назвачили права 644, а всем каталогам 755. Скриптам мы добавили возможность запуска (+x).
Само собой, каждый конкретный пакет должен собираться по своему сценарию. В данном примере мы рассмотрели очень простой сценарий.
Описание служебных файлов
Попробуем разобраться в синтаксисе обязательных файлов, которые мы создали для выполнения сборки.
Control
Данный файл содержит основную информацию о собираемом пакете. Рассмотрим по отдельности обязательные опции и дополнительные.
Основные (без которых сборщик вернет ошибку):
Опция | Описание | Пример |
---|---|---|
Source | Определяет имя пакета источника. | nginx |
Maintainer | Имя и адрес электронной почты сборщика пакета. | Dmitriy Moks |
Package | Имя собираемого пакета. | nginx |
Architecture | Архитектура собираемого пакета. | amd64 |
Дополнительные опции файла control:
Опция | Описание |
---|---|
Section | Классификация задачи, для которой может быть использовано приложение. Чаще всего применяются: misc, utils, net, mail, text, x11. Возможные значения: admin, base, comm, contrib, devel, doc, editors, electronics, embedded, games, gnome, graphics, hamradio, interpreters, kde, libs, libdevel, mail, math, misc, net, news, non-free, oldlibs, otherosfs, perl, python, science, shells, sound, tex, text, utils, web, x11. |
Priority | Определяет важность пакета для системы. Возможные варианты: required, standard, optional, extra, important. Влияет на поведение при удалении — например, пакет, отмеченный как required, не может быть удален. |
Build-Depends | Перечисляет список пакетов, которые требуются для сборки. Если в системе не будет перечисленных пакетов, сборщик вернет ошибку. Есть разные форматы записи, например: 1. Перечисляем зависимости: libpcre3-dev, zlib1g-dev 2. Используем логическое или: apache2 | httpd, php — в данном примере мы трубем, чтобы были установлены php и одни из веб-серверов (apache2 или httpd). 3. Указание версии: libpcre3-dev (= 13), zlib1g-dev (> 14), apache2 (>= 15), httpd ( < 16), nginx ( (обратите внимание, данный перечень можно записать через запятую в одну строчку или по одной/несколько пакетов на каждой строчке также через запятую). |
Standards-Version | Указывает на версию пакета. |
Homepage | Домашняя страница для собираемого пакета. |
Provides | Имя пакета, под которым будет зарегистрировано приложение после установки. Как правило, указывается таким же, как и имя собираемого пакета. Но в редких случаях, может понадобиться поменять на свое. |
Depends | Список пакетов, которые требуются для установки собираемого пакета на конечной системе. Также как и в Build-Depends, возможен разный формат написания. |
Description | Произвольное описание для пакета. Необходимо проследить, чтобы размер одной строки не превышал 73 символа. Каждая последующая строка описания должна начинаться, как минимум, с одного пробела. |
Полный перечень опций можно найти в официальном руководстве.
Rules
В данном файле мы задаем поведение при компиляции пакета. Как правило, его содержимое сводится к:
* отступы должны быть табуляциями, иначе система вернет ошибку.
. что означает, что все действия по установке пакета из исходника должны быть шаблонные.
При компиляции будет запущено три группы команд:
- debian/rules clean. Выполняет чистку каталога сборки и его подготовку.
- debian/rules build. Подготовка к сборке и сборка.
- debian/rules binary. Установка и создание бинарного пакета.
У каждой выше озвученной группы есть свои этапы, через которые проходит процесс сборки. Подробнее про данные этапы можно почитать на сайте debian.org.
Однако, для каждого из этапов мы можем переопределять поведение и задавать настройки (с помощью приставки override_ в файле). Рассмотрим примеры некоторых этапов и настроек.
Каталог источника
Задается с помощью параметра —sourcedirectory, например:
dh $@ --sourcedirectory=src/
* в данном примере мы укажем сборщику, что брать исходные файлы нужно в каталоге src (относительно рабочего каталога). При таком определении источника, не забываем заранее создать каталог (в данном примере, mkdir src).
override_dh_auto_configure
Выполняет конфигурирование. Нам может потребоваться изменить опции на свои, например:
override_dh_auto_configure: cd src/ && ./configure --prefix=/usr
* обратите внимание, что если у нас исходник находится в отдельном каталоге, мы должны перейти в него и сразу (&&) запустить команду для конфигурирования. Если эти команды ввести в разных строках, то мы получим ошибку — перед выполнением каждой команды сборщик возвращается в исходную директорию.
dh_auto_build
На данном этапе выполняется сборка (make). Можно перед этим процессом закачивать исходник и распаковывать его в каталог src:
override_dh_auto_build: dh_auto_build -- PG_CONFIG=/opt/pgpro/std-11/bin/pg_config
* в конечном итоге, мы запускаем тот же dh_auto_build, но с передачей дополнительной опции.
dh_auto_test
Выполняем цель test файла Makefile. Иногда, в процессе сборки пакета на данном этапе возвращается ошибка, хотя сама по себе компиляция и сборка прошли корректно. В таком случае, этап можно пропустить:
override_dh_auto_test:
* для пропуска любого из этапов просто вставляем соответствующую строку с пустым перечнем действий.
dh_auto_install
На данном этапе выполняется установка пакета (make install). Рассмотрим такой пример:
override_dh_auto_install: dh_auto_install -- PG_CONFIG=/opt/pgpro/std-11/bin/pg_config
* такая настройка выполнит установку, передав команде make install дополнительный параметр PG_CONFIG=/opt/pgpro/std-11/bin/pg_config. На практике, эта опция задает путь расположения конфига postgresql pro.
dh_fixperms
Задает стандартные права на файлы. Мы же можем захотеть назначить свои или отдельного владельца, например:
override_dh_fixperms: dh_fixperms chown nginx:nginx -R nginx
* в данном примере всем файлам внутри каталога будет задан владелец пользователь nginx. Обратите внимание, что мы сначала позволяем системе выставить права по своему алгоритму (dh_fixperms), после чего выполняем свою команду.
override_dh_gencontrol
Позволяет переопределить некоторые опции в файле control, например:
override_dh_gencontrol: dh_gencontrol -- -DSource="$(PKG_NAME)" -DDepends:"$(DEPENDS)"
* в данном примере мы меняем значения некоторым полям:
Сами переменные мы можем передать при запуске сборки. Подробнее процедура описана ниже.
Changelog
Файл используется системой сборки для получения номера версии пакета, его ревизии, срочности и раздела. Также в него можно заносить список изменений.
Типичный пример для файла:
gentoo (0.9.12-1) unstable; urgency=medium
* Initial release. (Closes: #nnnn)
— Josip Rodin Mon, 22 Mar 2010 00:37:31 +0100
- первая строчка указывает на:
- имя пакета (gentoo).
- версию (0.9.12-1).
- релиз (unstable).
- важность пакета (urgency=medium).
Описание дополнительных файлов
Ранее мы уже говорили о таких файлах, как:
- postinst — скрипт для запуска после установки пакета на целевой системе.
- postrm — выполнится после удаления пакета.
- preinst — скрипт выполнения перед установкой пакета.
- prerm — скрипт выполнения перед удалением пакета
Это дополнительные файлы, которые помогут нам сделать пакет более функциональным и удобным.
Рассмотрим некоторые дополнительные файлы.
Conffiles
Позволяет отметить файлы как конфигурационные. Такие файлы не будут удалены при деинсталляции пакета или заменены при обновлении. Важно знать, что программа dh_installdeb, которая помечает файлы как конфигурационные автоматически делает отметку для содержимого каталога /etc. Поэтому, нам не нужно создавать conffiles, если наши конфиги находятся в каталоге /etc.
Пример содержимого файла:
$mypackage.links
Название файла состоит из названия пакета + .links. Позволяет создать символьные ссылки при установке пакета. Например:
* в нашем примере будет создаваться симлинк /usr/bin/mybin из файла /opt/package_name/mybin.
Дополнительно
В данном разделе опишем некоторые полезные возможности.
1. Передача переменной.
При запуске сборки может понадобиться передать переменную, значение которой будет использоваться в нашем скрипте rules. Это делается с помощью опции -e:
debuild -eRELEASE=Ubuntu -eVERSION=22.04 -us -uc -b
* в нашем примере мы передали 2 переменные release и version.
В файле rules можно использовать данные переменные, например:
echo $(RELEASE)
echo $(VERSION)* применение не самое практичное, но для нашего примера достаточно.
2. Команда для редактирования Changelog.
Как было сказано выше, файл Changelog нужен для описания верий и изменений пакета. Для упрощения автоматизации работы со сборками, есть команда dch, которая сама вносит изменения в данный файл.
dch -m -v «1.5.5» -D «stable» «Fix errors»
. добавит строку с версией 1.5.5 и описанием Fix errors.
А если у нас нет файла debian/changelog, то его также можно создать с помощью команды dch:
dch —create —package pkg_name -m -v «1.5.5» -D «stable» «Fix errors»
Возможные ошибки
Рассмотрим некоторые проблемы, с которыми мы можем столкнуться в процессе сборки пакетов deb.
1. dpkg-shlibdeps: error: cannot find library
Причина: после сборки и установки пакетов сборщик проверяет наличие библиотек, которые нужны устанавливаемым файлам. На основе этого строятся зависимости при установке нашего собираемого пакета. Однако, хелпер shlibdeps ищет только в известных ему местах, а необходимые библиотеки могут располагаться в альтернативных каталогах, например /opt.
Решение: мы можем переопределить запуск хелпера shlibdeps, указав ему пути, где нужно искать библиотеки:
override_dh_shlibdeps:
dh_shlibdeps -l /usr/local/lib -l /usr/local/lib64 -l $(shell pwd)/debian/lib* в нашем примере мы указали три каталога, где нужно выполнить поиск — /usr/local/lib, /usr/local/lib64 и lib, которая находится в рабочем каталоге debian.