Linux deb что это
Еще раз о deb пакетах
Подготовка
Чтобы начать создавать deb пакеты, нужно установить несколько пакетов:
Подготовка папки с исходниками
Для того, чтобы dh_make и другие утилиты могли работать с папкой с исходниками, нужно привести ее в специфичный вид.
Папка должна называться имяпакета-версия. Т.е. если у меня есть папка Plugins с программой версии 0.1, то я создаю папку с именем plugins-0.1.
Теперь нужно создать архив с этой папкой. Архив должен содержать в имени *.orig.tar.gz, т.е.:
Последний подготовительный шаг, это создание в папке с исходниками папки debian со множеством служебных файлов. Чтобы это сделать, нужно выполнить команду:
В процессе выполнения этой команды будет задан вопрос о том, какой тип архива мы создаем, самый простой это single.
Настройка пакета
Вся настройка пакета происходит путем редактирования файлов в каталоге debian. Рассмотрим те файлы, которые будем использовать:
changelog
Данный файл содержит историю изменения пакета и текущую версию пакета. Посмотрим на его содержимое:
В начале идет название пакета — libvksplugins, затем его версия. Версия делиться на две части символом «-». Первая часть показывает версию программы в пакете, вторая «ревизию» пакета. Ревизия это версия пакета, т.е. если раньше такого пакета не было, то ревизия равна 1. Если же пакет с такой версией программы уже был, но в нем произошли изменения, то ревизия увеличивается.
Слово unstable показывает, что пакет является не стабильным, т.е. он не был протестирован должным образом на машинах пользователей.
Надпись urgency=low показывает срочность изменения. Т.к. срочности нет, то значение равно low. Если бы, мы делали пакет для исправления серьезной уязвимости или ошибки, то значение можно было бы установить в high.
После первой строки идет пустая строка, а за ней первая запись:
В Debian, changelog используется для автоматического закрытия ошибок в системах отслеживания ошибок в программных продуктах. Т.к. в данном случае, я не использую такую систему, то эта строка принимает вид:
Последняя строка является подписью человека, сделавшего запись. В ней содержится имя и адрес, а также дата изменения.
После установки deb пакета, файл changelog устанавливается в
control
Файл debian/control является главным конфигом, при создании deb пакета. Вот пример такого файла:
Видно, что файл разбит на секции при помощи пустых строк. Каждая секция описывает один пакет, создаваемый из папки с исходниками. Рассмотрим их по порядку:
Source Данная секция говорит о том, что нужно создать пакет исходных кодов. Параметром указано libvksplugins, это значит, что пакет исходных кодов будет называться libvksplugins.
Priority Эта секция устанавливает приоритет пакета. Т.к. система может прекрасно обойтись без нового пакета, то значение секции установлено в optional. Т.е. этот пакет не обязателен для установки. Подробнее о приоритетах написано здесь.
Maintainer Эта секция описывает контакты человека, создающего пакет. Ее формат довольно прост и дополнительного описание не требует.
Build-Depends Одна из самых важных секций, устанавливающая зависимости пакета. Зависимости, указанные в данной секции должны быть выполнены, чтобы можно было собрать пакет. Т.е. список зависимостей для сборки и установки могут отличаться.
Видно, что в зависимостях стоят debhelper (>= 9), cmake. Зависимость debhelper (>= 9) ставиться для всех пакетов по умолчанию. Она нужна для корректной работы программ вида dh_*.
Второй элемент cmake был добавлен потому, что папка с исходниками содержала файл CMakeLists.txt, т.е. для сборки используется система сборки CMake. Для того, чтобы узнать, какие зависимости есть у программы, можно почитать ее документацию. Кроме этого, можно воспользоваться командой dpkg-depcheck. Данная команда должна запускаться так:
Но, т.к. при использовании CMake нет скрипта конфигурирования, то я использую ее так:
Из примечательных тут можно отметить:
cmake
qt4-qmake
libqt4-dev
Остальные являются зависимостями данных. Причем, cmake уже есть в списке зависимостей сборки. В принципе, можно его оставить как есть или указать используемую версию:
При этом в CMakeLists.txt указана версия cmake, которую нужно использовать:
Я думаю, что разработчику виднее, и поэтому указываю версию из CMakeLists.txt. Для Qt 4 все понятно с номерами версий, но для очистки совести проверим и их версии:
Т.е. для Qt 4 указываем версию 4.8.6:
Standards-Version Версия стандарта, в соответствии с которым создан файл. Это значение не нужно менять.
Section. Секция для пакета, т.е. группа пакетов, выполняющая одну задачу. В Политике Debian разделе 2.4 этот вопрос описан более подробно.
Homepage Домашняя страница проекта. Т.к. данный код писал я и у него нет страницы, просто удаляю эту строку.
Vcs-* Ссылки на репозитории проекта. Их у меня тоже нет, поэтому удаляю эти строки.
Другие пакеты После секции файла, где описывается пакет с исходниками, идут секции, которые описывают другие пакеты, создаваемые из пакета с исходниками. Схема создания пакетов:
Из схемы видно, что из исходников программы, я хочу получить 4 пакета:
Мой персональный ответ на данный вопрос, заключается в том, что такое разбиение помогает структурировать программу по тому, как я хочу с ней работать. Для разработки я поставлю dev пакет, а для использования нет.
Кроме описанных выше пакетов, можно создать dbg пакет с отладочной сборкой программы. Это может пригодиться, если программа падает и у Вас есть под рукой отладчик. Однако, я так и не смог понять как это делать. Документация не дает ответа на этот вопрос. Если делать так как описано в ней, то я либо получаю пустой пакет либо получаю кучу ошибок при сборке.
Схема на рисунке выше показывает, что пакет с исходниками называется libvksplugins_source, однако, в файле control указано, что пакет с исходниками будет называться libvksplugins. На самом деле, он действительно будет называться libvksplugins, а пакет с бинарниками, будет называться libvksplugins… deb. Суть этой путаницы в том, что пакет с исходниками представляет собой tar архив и служебные файлы, тогда как пакет бинарников это архив с расширение deb.
Настройка пакета библиотеки Посмотрим внимательно на описание пакета библиотеки:
Для пакетов, содержащих скрипты или тексты, нужно указывать значение как all.
Третья строка, описывает зависимости создаваемого пакета. Вот как она описана в 4й главе Руководства начинающего разработчика Debian:
Т.е. эта строка говорит о том, что сборщик пакета сам определит зависимости.
Последний раздел данной секции это описание пакета. Первая строка содержит кратное описание, последующие строки содержат более подробное описание. Подробное описание, должно иметь определенный формат:
Настройка пакета документации Вместе с библиотекой поставляется документация, чтобы она была в отдельном пакете, добавляем его описание:
rules
Данный файл является аналогом Makefile для сборки пакетов. По умолчанию, он создается в таком виде:
Видно, что это bash скрипт с синтаксисом Makefile. Единственная интересная конструкция здесь это
Т.к. исходники используют систему сборки CMake, то нужно изменить эту запись следующим образом:
Содержимое пакетов
После того, как мы указали в debian/control какие пакеты мы хотим получить, нужно указать какие файлы в какой пакет помещать. Для этого, для каждого названия пакета из файла control, нужно создать в папке debian два файла. Первый должен называться пакет.dirs, а второй пакет.install. Суть файлов в том, что первый указывает, какие папки нужно создать для пакета, а второй, какие файлы включить в пакет.
Посмотрим на их содержимое:
Важный момент, отсутствие начальной дроби в путях и отсутствие дроби в конце пути к папке. Проверив, куда CMake устанавливает файлы библиотеки, можно сформировать такие файлы:
Завершение настройки
Т.к. исходники мои, то никаких дополнительных описаний и ограничений copyright у меня нет, поэтому я удаляю все лишние файлы из каталога debian.
Сборка пакетов
После настройки, сборка пакетов происходит довольно просто, нужно в папке проекта (которая включает подпапку debian) выполнить команду:
Заключение
Если вы дочитали до сюда — значит вы любите читать.
Этот текст является результатом моего опыта внедрения deb пакетов на работе. Опыт показал, что наличие сетевого репозитория (reprepro) и внимательное отслеживание версий, позволяют без проблем обновлять и тестировать различные версии ПО на парке из 30 машин с системами Astra Linux 1.3, 1.4 и Эльбрус ОС.
3 способа установить deb файлы на Ubuntu Linux
В этой статье для начинающих объясняется, как устанавливать deb-пакеты в Ubuntu. Также показано, как впоследствии удалить эти пакеты deb.
Это еще одна статья в серии новичков Ubuntu. Если вы абсолютно новичок в Ubuntu, вы можете поинтересоваться, как устанавливать приложения. Самый простой способ — использовать Ubuntu Software Center. Найдите приложение по его имени и установите его оттуда.
Жизнь была бы слишком простой, если бы вы могли найти все приложения в Центре программного обеспечения. Но этого не происходит, к сожалению.
Вы можете найти эти пакеты DEB в разделе загрузки на сайте поставщика программного обеспечения. Например, если вы хотите установить Google Chrome в Ubuntu, вы можете загрузить пакет DEB для Chrome со своего веб-сайта.
Теперь возникает вопрос, как установить файлы deb? Существует несколько способов установки пакетов DEB в Ubuntu. Я покажу их вам один за другим в этом уроке.
Вы можете выбрать инструмент GUI или инструмент командной строки для установки пакета deb. Выбор за вами.
Давайте посмотрим, как установить deb файлы.
Способ 1: использование программного центра по умолчанию
Откроется центр программного обеспечения, и вы должны увидеть возможность установки программного обеспечения. Все, что вам нужно сделать, это нажать кнопку установки и ввести свой пароль для входа.
Способ 2. Использование приложения Gdebi для установки пакетов deb с зависимостями.
Опять же, жизнь была бы намного проще, если бы все прошло гладко. Но это не жизнь, как мы ее знаем.
Что происходит, так это то, что программа может зависеть от другого программного обеспечения (библиотек). Когда разработчик готовит пакет DEB для вас, он / она может предположить, что ваша система уже имеет эту часть программного обеспечения в вашей системе.
Но если это не так, и ваша система не имеет необходимых компонентов программного обеспечения, вы столкнетесь с печально известной «ошибкой зависимости».
Центр программного обеспечения не может самостоятельно обрабатывать такие ошибки, поэтому вам придется использовать другой инструмент под названием gdebi.
gdebi — это легкое приложение с графическим интерфейсом, единственная цель которого — установить пакеты deb.
Лично я предпочитаю gdebi центру программного обеспечения для установки файлов deb. Это легкое приложение, поэтому установка кажется быстрее. Вы можете прочитать подробно об использовании gDebi и сделать его по умолчанию для установки пакетов DEB.
Вы можете установить gdebi из центра программного обеспечения или используя команду ниже:
Способ 3: установить deb файлы в командной строке с помощью dpkg
Если вы хотите установить deb файлы в команде lime, вы можете использовать команду apt или dpkg. Команда Apt на самом деле использует команду dpkg, но apt более популярна и проста в использовании.
Если вы хотите использовать команду apt для файлов deb, используйте ее следующим образом, где /path/to/file.deb — путь до вашего deb-файла:
Если вы хотите использовать команду dpkg для установки пакетов deb, вот как это сделать:
Если при установке пакетов deb вы получили ошибку зависимости, вы можете использовать следующую команду для устранения проблем зависимости:
Как удалить пакеты deb
Удаление пакета deb не имеет большого значения. И нет, вам не нужен оригинальный файл deb, который вы использовали для установки программы.
Способ 1: удаление пакетов deb с помощью команд apt
Все, что вам нужно, это имя программы, которую вы установили, и затем вы можете использовать apt или dpkg, чтобы удалить эту программу. Для этого введите вот эту команду, где program_name название программы, которую вы хотите удалить.
Теперь возникает вопрос, как найти точное имя программы, которое нужно использовать в команде удаления? У команды apt есть решение и для этого.
Команда grep удалит из вывода все строки, в которых нет слова grid и мы получим только то, что нас интересует. То есть в данном случае вместо большого списка будет только та строка, которая интересует. Это намного проще, чем искать глазами, правда?
Как видите, установлена программа appgrid. Теперь вы можете использовать это имя программы с командой apt remove.
Способ 2: удалить пакеты deb с помощью команд dpkg
Вы также можете использовать dpkg, чтобы найти имя установленной программы:
Вывод выдаст все установленные пакеты, которые содержат слово grid:
ii в приведенной выше команде вывод означает, что пакет был правильно установлен.
Теперь, когда у вас есть имя программы, вы можете использовать команду dpkg, чтобы удалить ее:
Я надеюсь, что это руководство для начинающих помогло вам установить deb файлы в Ubuntu. Я добавил часть удаления, чтобы вы могли лучше контролировать установленные вами программы.
Более подробно о deb-пакетах вы можете почитать на официальном сайте Debian тут.
Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.
Типичный способ установки пакета из файла DEB:
С помощью этих команд устанавливаются пакеты из стандартных репозиториев — это самый надёжный способ в том плане, что для устанавливаемого пакету будут установлены зависимости и в будущем этот пакет будет обновляться вместе с другими программами в системе. То есть установка из стандартных репозиториев является приоритетной.
Установка без учёта зависимостей
Следующая команда установит пакет без проверки зависимостей:
При выполнении операции менеджером пакетов, например, обновление кэша:
может возникнуть сообщение об отсутствующих зависимостях, исправить это можно командой:
Установка DEB файла с помощью apt
Программа apt также умеет устанавливать пакеты из указанных файлов, при этом одновременно будут установлены необходимые зависимости для этого пакета:
Установка пакетов с помощью gdebi
Вы можете установить программу gdebi:
И затем устанавливать пакеты с помощью неё:
gdebi также установит необходимые зависимости. На самом деле, gdebi появилась когда apt-get не могла устанавливать локальные файлы (или эта возможность не была документирована), сейчас же вместо gdebi можно использовать apt, которая предустановлена в каждом дистрибутиве, основанном на Debian.
Создание deb пакетов
В этой статье мы рассмотрим как собрать deb пакет для своей программы без использования каких-либо сторонних инструментов. Мы не будем рассматривать подпись пакетов для репозиториев, потому что для каждого вида репозиториев команды будут отличаться.
Создание deb пакетов
Шаг 1. Подготовка
Давайте создадим для этого примера небольшую программу на Си. Она будет называться hellolosst и будет выводить на экран строку Hello from losst.ru в терминал при запуске. Сначала создайте папку hellolosst и перейдите в неё:
mkdir hellolosst
cd hellolosst
Затем поместите в неё файл с исходным кодом:
#include
int main() <
printf(«Hello from losst.ru\n»);
>
Для компиляции программы выполните такую команду:
Затем вы можете её выполнить:
Таким образом, теперь у нас есть программа, которую надо упаковать в deb пакет.
2. Создание манифеста
В каждом deb пакете содержаться не только файлы самой программы, но и файл манифеста, в котором описан пакет, его зависимости и параметры. Этот файл имеет название control и должен находится в папке DEBIAN. Для сборки пакета будем использовать папку package, чтобы файлы программы не путались с исходными файлами и те не попали в пакет. Создайте эти папку:
Прежде чем вы сможете создать этот файл надо узнать несколько вещей. Первым делом надо посмотреть размер файлов программы, поскольку в данном случае файл один, достаточно посмотреть его размер:
Если файлов несколько, то можно удалить исходники и посмотреть общий размер папки с файлами программы. Дальше надо понять от каких пакетов будет зависеть ваша программа. Для этого воспользуйтесь командой objdump:
В данном случае программе необходима только libc. Чтобы посмотреть в каком пакете она находится выполните:
Пакет называется libc6. Затем создайте файл манифеста со следующим содержимым:
Это минимальный набор параметров в файле манифеста. Вот их значение:
3. Расположение файлов
Манифест готов. Теперь в папке пакета надо создать структуру папок, аналог того, что есть в корневой файловой системе. В данном случае надо создать папку usr/bin и поместить туда исполняемый файл:
4. Скрипты установки
#!/bin/bash
echo «Hello from losst installed»
Разработчики Debian не рекомендуют использовать эти скрипты без крайней надобности, поскольку они дают вам полный контроль над системой пользователя и вы можете случайно что-то повредить. Обычно эти скрипты используются для того чтобы задавать пользователям вопросы и на основе этого генерировать конфигурационные файлы.
5. Сборка и проверка пакета
Осталось собрать настроенный пакет. Для этого используйте такую команду:
Теперь вы знаете как как собрать deb пакет. После завершения сборки можете установить его с помощью apt:
После этого исполняемый файл программы появится в /usr/bin, а сообщение из postinst будет выведено после установки.
Выводы
В этой небольшой статье мы рассмотрели как выполняется создание deb пакета с помощью инструмента dpkg-deb. Как видите, всё очень просто. Вам достаточно написать манифест и расположить файлы там, где они должны быть. Мы рассмотрели здесь только самые основы. На самом деле создание пакетов намного сложнее. Существует целый набор утилит debhelpers, которые используются на различных этапах сборки и установки deb пакетов, подробнее обо всём этом вы можете прочитать в официальной документации.
Linux многоликий: как работать на любом дистрибутиве
Создать приложение для резервного копирования, работающее на любом дистрибутиве — задачка непростая. Чтобы обеспечить работу Veeam Agent for Linux на дистрибутивах от RHEL 6 и Debian 6, до openSUSE Leap 15.1 и Ubuntu 19.04 приходится решать спектр проблем, особенно если учесть, что в состав программного продукта входит модуль ядра.
Статья создана по материалам выступления на конференции LinuxPiter 2019.
Linux — это не просто одна из самых популярных ОС. По сути, это платформа, на базе которой можно сделать что-то уникальное, что-то своё. Благодаря этому у Linux множество дистрибутивов, которые отличаются набором программных компонентов. И тут возникает проблема: чтобы программный продукт функционировал на любом дистрибутиве, приходится учитывать особенности каждого.
Начнём с очевидной проблемы распространения продукта для разных дистрибутивов.
Самый типичный способ распространения программных продуктов — это выложить пакет на репозиторий, чтобы встроенный в систему пакетный менеджер смог его оттуда установить.
Однако популярных форматов пакетов у нас два: rpm и deb. Значит, придётся поддержать каждый.
В мире deb-пакетов уровень совместимости поразителен. Один и тот же пакет одинаково хорошо ставится и работает как на Debian 6, так и на Ubuntu 19.04. Стандарты процесса построения пакетов и работы с ними, заложенные в старых Debian дистрибутивах, остаются актуальными и в новомодных Linux Mint и elementary OS. Поэтому в случае Veeam Agent for Linux достаточно одного deb-пакета для каждой аппаратной платформы.
А вот в мире rpm-пакетов различия велики. Во-первых, из-за того, что есть два совершенно независимых дистрибьютера Red Hat и SUSE, для которых совершенно не нужна совместимость. Во-вторых, у этих дистрибьютеров есть дистрибутивы с тех. поддержкой и экспериментальные. Между ними совместимость тоже не нужна. У нас получилось, что для el6, el7 и el8 свои пакеты. Отдельно пакет для Fedora. Пакеты для SLES11 и 12 и отдельный для openSUSE. Основная проблема — в зависимостях и именах пакетов.
Проблема зависимостей
В результате список зависимостей оказывается уникальным для дистрибутива.
Хуже бывает, когда под старым именем пакета начинает прятаться обновлённая версия.
В Fedora 24 обновился пакет ncurses c версии 5 до версии 6. Наш продукт собирался именно с 5-той версией, для обеспечения совместимости со старыми дистрибутивами. Чтобы воспользоваться старой 5-той версией библиотеки на Fedora 24, пришлось использовать пакет ncurses-compat-libs.
В результате для Fedora появляется два пакета, с разными зависимостями.
Дальше интереснее. После очередного обновления дистрибутива пакет ncurses-compat-libs с 5-той версией библиотеки оказывается недоступным. Для дистрибьютера накладно тянуть старые библиотеки в новую версию дистрибутива. Спустя некоторое время проблема повторилась и в дистрибутивах SUSE.
В результате для некоторых дистрибутивов пришлось отказаться от явной зависимости от ncurses-libs, а продукт поправить так, чтобы он мог работать с любой версией библиотеки.
Кстати, в 8-й версии Red Hat больше нет мета-пакета python, который ссылался на старый добрый python 2.7. Есть python2 и python3.
Альтернатива пакетным менеджерам
Проблема с зависимостями стара и давно очевидна. Вспомнить хотя бы Dependency hell.
Объединить разнообразные библиотеки и приложения так, чтобы все они стабильно работали и не конфликтовали — собственно, эту задачу и пытается решать любой дистрибьютор Linux.
Совсем иначе пытается решать эту проблему пакетный менеджер Snappy от Canonical. Основная идея: приложение выполняется в изолированной и защищённой от основной системы песочнице. Если приложению нужны библиотеки, то они поставляются вместе с самим приложением.
Flatpak также позволяет запускать приложения в песочнице, используя Linux Containers. Есть ещё AppImage, который позволяет создавать портативные образы программ.
Эти решения позволяют создавать один пакет для любых дистрибутивов. В случае с Flatpak и AppImage установка и запуск приложения возможна даже без ведома администратора.
Основная проблема в том, что не все приложения могут работать в песочнице и без root привилегий. Некоторым нужно прямое обращение к платформе. Я уж не говорю про модули ядра, которые жёстко зависят от ядра и никак не вписываются в концепцию песочницы.
Вторая проблема – популярные в enterprise-среде дистрибутивы от Red Hat и SUSE ещё не содержат поддержку Snappy и Flatpak.
В связи с этим Veeam Agent for Linux нет ни на snapcraft.io ни на flathub.org.
В завершение вопроса о пакетных менеджерах замечу, что есть вариант отказаться вовсе от пакетных менеджеров, объединив в один пакет бинарные файлы и скрипт для их установки.
Такой bundle позволяет создать один общий пакет для разных дистрибутивов и платформ, производить интерактивный процесс установки, осуществляя необходимую кастомизацию. Я сталкивался с такими пакетами для Linux только от VMware.
Проблема обновлений
Даже если все проблемы с зависимостями решены, программа может работать по-разному на одном и том же дистрибутиве. Дело в обновлениях.
Есть 3 стратегии обновления:
Разнообразие аппаратных платформ
Различные аппаратные платформы – это проблема, в значительной степени специфичная именно для native-кода. Как минимум, приходится собирать бинарники для каждой поддерживаемой платформы.
В проекте Veeam Agent for Linux мы всё никак не можем поддержать хоть что-нибудь такое RISC-овое.
Статическая и/или динамическая линковка
А вот вопрос «Как линковаться с библиотеками — динамически или статически?» стоит обсудить.
Как правило, С/С++ приложения под Linux используют динамическую линковку. Это отлично работает в том случае, если приложение собрано специально под конкретный дистрибутив.
Если же стоит задача охватить разнообразные дистрибутивы одним бинарным файлом, то приходится ориентироваться на самый старый поддерживаемый дистрибутив. Для нас это Red Hat 6. Он содержит gcc 4.4, который даже стандарт С++11 поддерживает не полностью.
Мы собираем наш проект с помощью gcc 6.3, который полностью поддерживает C++14. Естественно, в таком случае на Red Hat 6 библиотеку libstdc++ и boost приходится тащить с собой. Проще всего линковаться с ними статически.
Но увы, не со всеми библиотеками можно линковаться статически.
Во-первых, системные библиотеки, такие как libfuse, libblkid необходимо линковать динамически, чтобы быть уверенным в совместимости их с ядром и его модулями.
Во-вторых, есть тонкость с лицензиями.
Линцензия GPL в принципе разрешает линковать библиотеки только с opensource кодом. MIT и BSD разрешают статическую линковку и позволяют включать библиотеки в проект. А вот LGPL вроде как не противоречит статической линковке, но требует предоставить в общий доступ файлы, необходимые для связывания.
В общем случае использование динамической линковки обезопасит от необходимости что-то предоставлять.
Сборка С/С++ приложений
Для сборки С/С++ приложений для разных платформ и дистрибутивов достаточно подобрать или собрать gcc подходящей версии и воспользоваться кросс-компиляторами для специфичных архитектур, собрать весь набор библиотек. Работа эта вполне реализуемая, но довольно хлопотная. И нет никаких гарантий, что выбранный компилятор и библиотеки обеспечат работоспособный вариант.
Очевидный плюс: сильно упрощается инфраструктура, так как весь процесс сборки можно выполнить на одной машине. Кроме того, достаточно собрать один набор бинарных файлов для одной архитектуры и можно паковать их в пакеты для разных дистрибутивов. Именно так собираются пакеты veeam для Veeam Agent for Linux.
В противовес этому варианту можно просто подготовить build ферму, то есть несколько машин для сборки. Каждая такая машина будет обеспечивать компиляцию приложения и сборку пакета для конкретного дистрибутива и определённой архитектуры. В таком случае компиляция производится теми средствами, которые подготовил дистрибьютер. То есть этап подготовки компилятора и подбор библиотек отпадает. Кроме того, процесс сборки может быть легко распараллелен.
Есть, правда, и минус у такого подхода: для каждого дистрибутива в рамках одной архитектуры придётся собирать свой набор бинарных файлов. Также минусом является то, что такое множество машин нужно обслуживать, выделять большое количество дискового пространства и оперативной памяти.
Таким образом собираются KMOD пакеты модуля ядра veeamsnap под дистрибутивы Red Hat.
Open Build Service
Коллеги из SUSE попробовали реализовать некоторую золотую середину в виде специального сервиса для компиляции приложений и сборки пакетов — openbuildservice.
По сути, это гипервизор, который создаёт виртуальную машину, устанавливает в ней все необходимые пакеты, выполняет компиляцию приложения и сборку пакета в этой изолированной среде, после чего такая виртуальная машина освобождается.
Реализованный в OpenBuildService планировщик сам определит, сколько виртуальных машин он может запустить для оптимальной скорости сборки пакетов. Встроенный механизм подписи сам подпишет пакеты и выложит их на встроенный репозиторий. Встроенная система версионного контроля сохранит историю изменений и сборок. Остаётся просто добавить в эту систему свои исходники. Даже сервер самому поднимать не обязательно, а можно воспользоваться открытым.
Тут, правда, есть проблема: такой комбайн трудно вписывается в существующую инфраструктуру. Например, версионный контроль не нужен, у нас уже есть свой для исходников. Механизм подписи у нас отличается: используется специальный сервер. Репозиторий тоже не нужен.
Кроме того, поддержка других дистрибутивов — к примеру, Red Hat — реализована довольно скудно, что вполне объяснимо.
Достоинством такого сервиса является быстрая поддержка очередной версии дистрибутива SUSE. До официального объявления о релизе необходимые для сборки пакеты выкладываются на публичный репозиторий. В списке доступных дистрибутивов на OpenBuildService появляется новый. Выставляем галочку, и он добавляется в план сборки. Таким образом, добавление новой версии дистрибутива выполняется практически в один клик.
В нашей инфраструктуре с использованием OpenBuildService собирается всё многообразие KMP пакетов модуля ядра veeamsnap для дистрибутивов SUSE.
Далее я хотел бы остановиться на вопросах, специфичных именно для модулей ядра.
kernel ABI
Модули ядра Linux исторически распространялись в виде исходных текстов. Дело в том, что создатели ядра не обременяют себя заботой о поддержке стабильного API для модулей ядра, а тем более на бинарном уровне, далее kABI.
Чтобы собрать модуль для ванильного ядра, обязательно нужны header-ы именно этого ядра, и работать он будет только на этом ядре.
DKMS позволяет автоматизировать процесс сборки модулей при обновлении ядра. В результате пользователи репозитория Debian (и его многочисленных родственников) используют модули ядра либо из репозитория дистрибьютера, либо собираемые из исходников с помощью DKMS.
Однако такая ситуация не особо устраивает Enterprise-сегмент. Распространители проприетарного кода хотят распространять продукт в виде собранных бинарников.
Администраторы не хотят держать средства разработки на production-серверах из соображений безопасности. Дистрибьютеры Enterprise Linux — такие, как Red Hat и SUSE — решили, что для своих пользователей стабильное kABI они смогут поддержать. В результате появились KMOD пакеты для Red Hat и KMP пакеты для SUSE.
Суть такого решения довольно проста. Для конкретной версии дистрибутива API ядра freeze-ится. Дистрибьютор заявляет, что он использует именно ядро, например, 3.10, и вносит только исправления и улучшения, которые никак не затрагивают интерфейсы ядра, а собранные для самого первого ядра модули могут быть использованы для всех последующих без перекомпиляции.
Red Hat заявляют о kABI совместимости для дистрибутива на протяжении всего жизненного цикла. То есть собранный модуль для rhel 6.0 (релиз ноября 2010) должен также работать и на версии 6.10 (релиз июня 2018). А это почти 8 лет. Естественно, задача это довольно сложная.
Мы зафиксировали несколько случаев, когда из-за проблем с kABI совместимостью модуль veeamsnap переставал работать.
После того, как модуль veeamsnap, собранный для RHEL 7.0, оказался несовместим с ядром из RHEL 7.5, но при этом загружался и гарантированно ронял сервер, мы отказались от использования kABI совместимости для RHEL 7 вообще.
В настоящий момент KMOD пакет для RHEL 7 содержит сборку для каждой версии релиза и скрипт, который обеспечивает загрузку модуля.
SUSE к задаче kABI совместимости подошли более осторожно. Они обеспечивают kABI совместимость только в рамках одного service pack.
Например, релиз SLES 12 состоялся в сентябре 2014. А SLES 12 SP1 уже в декабре 2015, то есть прошло чуть больше года. Несмотря на то, что оба релиза используют ядро 3.12, они kABI несовместимы. Очевидно, что поддерживать kABI совместимость в течение всего лишь года значительно проще. Годовой цикл обновления модуля ядра не должен вызывать проблем у создателей модулей.
В результате такой политики SUSE мы не зафиксировали ни одной проблемы с kABI совместимостью у нашего модуля veeamsnap. Правда, и число пакетов для SUSE почти на порядок больше.
Патчи и бэкпорты
Несмотря на то, что дистрибьютеры стараются обеспечить kABI совместимость и стабильность ядра, они ещё и стараются улучшить производительность и устранить дефекты этого стабильного ядра.
При этом кроме собственной «работы над ошибками» разработчики ядра enterprise linux отслеживают изменения в ванильном ядре и переносят их в своё «стабильное».
Иногда это приводит к новым ошибкам.
В последнем релизе Red Hat 6 в одном из минорных обновлений была допущена ошибка. Она приводила к тому, что модуль veeamsnap гарантированно валил систему при освобождении снапшота. Сравнив исходники ядра до и после обновления, мы выяснили, что виной всему был backport. Аналогичный фикс был произведён в ванильном ядре версии 4.19. Вот только в ванильном ядре этот фикс работал нормально, а при переносе его в «стабильное» 2.6.32 возникла проблема со спин-блокировкой.
Конечно, ошибки встречаются у всех и всегда, но стоило ли тащить код из 4.19 в 2.6.32, рискуя стабильностью. Я не уверен…
Хуже всего, когда к перетягиванию каната «стабильность» «модернизация» подключается маркетинг. Отделу маркетинга нужно, чтобы ядро обновлённого дистрибутива был стабильным, с одной стороны, и в тоже время было лучше по производительности и имело новые функции. Это приводит к странным компромиссам.
Когда я попробовал собрать модуль на ядре 4.4 от SLES 12 SP3, я с удивлением обнаружил в нём функционал из ванильного 4.8. На мой взгляд, реализация блочного ввода/вывода ядра 4.4 от SLES 12 SP3 больше походит на ядро 4.8, чем на предыдущий релиз стабильного 4.4 ядра от SLES12 SP2. Каков был процент перенесённого кода из ядра 4.8 в SLES-овский 4.4 для SP3 я судить не берусь, однако назвать ядро всё тем же стабильным 4.4 у меня язык не поворачивается.
Самое неприятное в этом то, что при написании модуля, который бы одинаково хорошо работал на разных ядрах, более нельзя опираться на версию ядра. Приходится ещё и учитывать дистрибутив. Хорошо, что иногда можно завязаться на дефайн, который появляется вместе с новым функционалом, однако такая возможность появляется не всегда.
В результате код обрастает причудливыми директивами условной компиляции.
Встречаются ещё и патчи, которые меняют задокументированное API ядра.
Наткнулся на дистрибутив KDE neon 5.16 и был очень удивлён, увидев что вызов lookup_bdev в этой версии ядра изменил перечень входных параметров.
Чтобы собраться, пришлось в makefile добавлять скрипт, который проверяет, есть ли параметр mask у функции lookup_bdev.
Подпись модулей ядра
Но вернёмся к вопросу распространения пакетов.
Одно из достоинств стабильного kABI в том, что модули ядра в виде бинарного файла можно подписать. В этом случае разработчик может быть уверен, что модуль не был случайно повреждён или намеренно изменён. Проверить это можно командой modinfo.
Дистрибутивы Red Hat и SUSE позволяют проверять подпись модуля и загружать его, только если в системе зарегистрирован соответствующий сертификат. Сертификат представляет собой публичный ключ, которым подписывается модуль. Мы распространяем его в виде отдельного пакета.
Проблема тут в том, что сертификаты могут быть либо встроенные в ядро (их используют дистрибьютеры), либо должны быть записаны в энергонезависимую память EFI с помощью утилиты mokutil. Утилита mokutil при установке сертификата требует перезагрузить систему и ещё до загрузки ядра операционной системы предлагает администратору разрешить загрузку нового сертификата.
Таким образом, добавление сертификата требует физического доступа администратора к системе. Если машина располагается где-то в облаке либо просто в удалённой серверной и доступ есть только по сети (например, по ssh), то добавить сертификат будет невозможно.
EFI на виртуальных машинах
Несмотря на то, что уже давно EFI поддерживается практически всеми создателями материнских плат, при установке системы администратор может не задуматься о необходимости EFI, и он может быть отключён.
Не все гипервизоры поддерживают EFI. VMWare vSphere поддерживает EFI, начиная с версии 5.
Microsoft Hyper-V также получил поддержку EFI, начиная с Hyper-V for Windows Server 2012R2.
Однако в дефолтной конфигурации этот функционал для Linux машин выключен, а значит, сертификат установить нельзя.
В vSphere 6.5 выставить опцию Secure Boot можно только в старой версии веб-интерфейса, который работает через Flash. Web UI на HTML-5 пока сильно отстаёт.
Экспериментальные дистрибутивы
Ну и напоследок рассмотрим вопрос экспериментальных дистрибутивов и дистрибутивов без официальной поддержки. С одной стороны, такие дистрибутивы навряд ли встретишь на серверах серьёзных организаций. Официальной поддержки у таких дистрибутивов нет. Поэтому и обеспечивать тех. поддержку продукта на таком дистрибутиве нельзя.
Однако такие дистрибутивы становятся удобной площадкой для пробы новых экспериментальных решений. Например, Fedora, OpenSUSE Tumbleweed или Unstable версии Debian. Они довольно стабильны. В них всегда новые версии программ и всегда новое ядро. Через год этот экспериментальный функционал может оказаться в обновлённом RHEL, SLES или Ubuntu.
Так что если что-то не работает на экспериментальном дистрибутиве — это повод разобраться в проблеме и решить её. Нужно быть готовым к тому, что этот функционал скоро появится на production-серверах пользователей.
Существующий на текущий момент список официально поддерживаемых дистрибутивов для версии 3.0 вы можете изучить здесь. Но реальный список дистрибутивов, на которых наш продукт способен работать, намного шире.
Лично мне был интересен эксперимент с ОС «Эльбрус». После доработки пакета veeam наш продукт установился и заработал. Про этот эксперимент я писал на Хабре в статье.
Ну а поддержка новых дистрибутивов продолжается. Ожидаем появления на свет версии 4.0. Вот-вот должна появиться бэта, так что следите за whats-new!