How to build rpm package
How to build rpm package
How to create a Linux RPM package
Posted: November 27, 2020 |
Photo by Ketut Subiyanto from Pexels
This article shows you how to package a script into an RPM file for easy installation, updating, and removal from your Linux systems. Before I jump into the details, I’ll explain what an RPM package is, and how you can install, query, remove, and, most importantly, create one yourself.
This article covers:
More about automation
What is an RPM package?
RPM stands for Red Hat Package Manager. It was developed by Red Hat and is primarily used on Red Hat-based Linux operating systems (Fedora, CentOS, RHEL, etc.).
The name of an RPM package follows this format:
Some packages also include a shorthand version of the distribution they were built for, such as:
How to create an RPM package
You’ll need the following components to build an RPM package:
Installing the required software
The following packages need to be installed to build the RPM package:
You build RPM packages as a normal (not root) user, so your build environment is placed into your home directory. It contains this directory structure:
You’re now familiar with what each directory holds, so now create a simple script to distribute:
Place the script in the designated directory
To build a package for your script, you must put your script in the directory that the RPM build system expects it to be in. Create a directory for it, using semantic versioning as most projects do, and then move hello.sh into it:
Most source code is distributed as an archive, so use the tar command to create an archive file:
Then move the tarball you’ve just created into the SOURCES directory:
/rpmbuild to see what the directory structure looks like:
You’re packaging a Bash script, so there’s some simplification you can do. For instance, there’s no Build process because there’s no code to compile. I’ve added BuildArch: noarch because this package is valid for 32-bit, 64-bit, Arm, and any other CPU architecture that runs Bash.
I’ve also added Requires: bash so that the package ensures that Bash is installed. This simple «hello world» script runs on any shell, of course, but that’s not true for all scripts, so this is a good way to demonstrate dependencies.
For example, it’s required that you specify exactly which files are installed under the %files section. Here I’ve explicitly put the following line:
This works because I want the script to go to % (which is a macro that translates to /usr/bin by default, but is configurable when users want to install to a different location, such as /usr/local/bin ). You can verify macro values by running:
Other useful macros:
There are 2 errors reported, but they’re both acceptable. There’s no code to build, so there’s no need for a %build section, and the source archive is a local file and has no network URL.
Everything looks good.
Building the package (rpmbuild)
After the build process is finished, you have the following directory structure:
Installing the RPM package
After a successful build of the package, you can install the RPM package using the dnf command:
It can alternately be installed with the rpm command directly:
Verify the package has been installed
To verify the package has correctly been installed, run the following command:
The %changelog entry of a package can be viewed, too:
See what’s in the RPM package
It’s easy to see which files an RPM package contains:
Removing the RPM package
Removing the package from the system is just as easy as installing it. You can use the dnf command:
Создание RPM-пакетов с нуля на примерах
В данной инструкции мы научимся готовить Linux-среду для работы и рассмотрим примеры по созданию своих пакетов RPM. Мы будем работать в системе CentOS (Red Hat / Fedora).
Подготовка системы
Для работы по сборке пакетов лучше использовать отдельный компьютер, виртуальную машину или контейнер Docker.
1. Установим пакеты:
yum install rpmdevtools rpmlint
yum group install «Development Tools»
* данная группа пакетов включает все необходимое для сборки. Ее не рекомендуется ставить на рабочий компьютер, так как устанавливается много ненужного для стандартной системы мусора.
2. Создаем пользователя.
Делать готовые установочные сборки пакетов очень опасно от пользователя root. Если мы допустим ошибку с путями, файлы могут перетереть или удалить важные для работы директории. Стоит создать отдельного пользователя и работать под ним. Однако, если мы работаем в виртуальной среде или контейнере Docker, нам это не страшно. Тогда данный пункт можно пропустить и работать из под root.
* в данном примере мы создадим пользователя builder. Опция -m сразу создаст домашний каталог для пользователя.
Теперь заходим под данным пользователем — последующие команды мы будем выполнять от него:
3. Создадим структуру каталогов для сборки:
В нашей текущем каталоге должна появиться папка rpmbuild — а в ней:
Мы готовы к сборке.
Сборка из исходников
Рассмотрим пример создания RPM из пакета, который нужно собирать из исходников с помощью команды make. Например, возьмем данную программу: github.com/brettlaforge/pg_redis_pubsub.
Создадим файл spec:
Теперь откроем его и приведем к виду:
Name: pg_redis_pubsub
Version: 1.0.2
Release: 1%
Summary: Redis Publish from PostgreSQL
License: X11 License
URL: https://github.com/brettlaforge/pg_redis_pubsub
Source0: %
BuildRequires: postgresql-devel postgresql-server-devel
BuildRequires: hiredis-devel
Requires: postgresql
%if 0% = 0.13.3-1
%else
Requires: hiredis = 0.15
%endif
%define _build_id_links none
%description
Redis Publish from PostgreSQL
%files
%defattr(-,root,root)
%<_libdir>/pgsql/redis.so
%<_datadir>/pgsql/extension/redis.control
%<_datadir>/pgsql/extension/redis—0.0.1.sql
%doc %<_datadir>/doc/extension/redis.mmd
%changelog
* Fri Jul 9 2021 root
—
* чтобы понять, как заполнить spec-файл, рекомендуется для начала собрать и установить приложение вручную с помощью make и make install. Также необходимо изучить документацию устанавливаемого пакета или (при наличие возможности) поговорить с разработчиками программного обеспечения.
Установим зависимости, которые необходимы для сборки (BuildRequires):
* утилита yum-builddep сама читает зависимости, необходимые для сборки и устанавливает недостающие пакеты.
Можно это сделать и вручную. В данном примере это:
yum install epel-release
yum install postgresql-devel postgresql-server-devel hiredis-devel
* конкретно, в моем примере для установки hiredis-devel необходимо поставить репозиторий epel-release. Список пакетов, необходимый для сборки конкретного пакета необходимо уточнить в документации.
Теперь копируем исходник на свой компьютер. В моем примере клонируем репозиторий:
git clone https://github.com/brettlaforge/pg_redis_pubsub.git
Готовим архив и помещаем его в каталог rpmbuild/SOURCES:
Если бы в качестве Source мы указали внешний URL, можно было бы предварительно загрузить исходники командой:
Данная команда разместит загруженные файлы в каталоге rpmbuild/SOURCES/.
Проверяем корректность SPEC-файла:
В моем примере команда вернула ответ:
rpmbuild/SPECS/pg_redis_pubsub.spec: W: invalid-url Source0: pg_redis_pubsub-1.0.2.tar.gz
0 packages and 1 specfiles checked; 0 errors, 1 warnings.
Данное предупреждение можно проигнорировать.
Если она пройдет без ошибок, мы должны найти RPM-пакет в каталоге rpmbuild/RPMS/x86_64, где x86_64 — архитектура пакета.
Описание файла SPEC
Данный файл является инструкцией по сборке пакета. В нем мы описываем сам пакет, задаем метаданные и указываем, как извлекать файлы и куда их копировать при установке пакета. Синтаксис файла включает такие элементы, как разделы, макросы, операторы, опции. Рассмотрим их отдельно.
Опции заголовка
Определяют описание пакета, а также некоторые важные для сборки параметры.
Сценарии
Мы можем описать команды, которые будут выполняться на конечном компьютере при установке или удалении пакета:
Сценарий | Описание |
---|---|
%pre | Выполняется перед установкой пакета в систему |
%post | Выполняется после установки пакета в систему |
%preun | Выполняется перед удалением пакета из системы |
%postun | Выполняется после удаления пакета из системы |
Пример для %post
%post
case «$1» in
1)
post_install.sh
;;
*)
echo «postinst called with unknown argument \`$1′» >&2
exit 1
;;
esac
exit 0
* макрос %post принимает аргумент $1, который говорит нам как был установлен пакет — новая установка (1) или обновление (2). Это важно, так как действия, как правило, отличаются, в зависимости от того, чистая это установка или обновление.
Макросы для сценариев
Внутри сценариев могут быть запущены свои макросы:
Макросы для команд
Некоторые системные команды лучше писать не напрямую, а через макросы. Это позволит добиться большей стабильности при сборке на различных системах. Приведем в пример данные команды:
Макросы для каталогов
Каталоги лучше писать не буквально, а через макросы:
Макрос | Путь | Итоговый путь |
---|---|---|
% | /usr | /usr |
% | /usr | /usr |
% | %<_prefix>/lib64 | /usr/lib64 |
% | %<_prefix>/share | /usr/share |
% | % | /usr/share |
% | /etc | /etc |
% | /var | /var |
% | /var | /var |
% | /var/lib | /var/lib |
% | %<_datadir>/doc | /usr/share/doc |
% | /usr/lib/systemd/system | /usr/lib/systemd/system |
% | % | /usr |
% | %<_exec_prefix>/bin | /usr/bin |
Служебные переменные
Ранее мы рассмотрели возможность определения переменных в файле spec с помощью директив %define или %global. Переменные могут нами использовать для подстановки значений в определенные блоки сценария. Но также, мы можем определять некоторую логику с помощью специальных переменных. Рассмотрим это на конкретных примерах:
Переменная | Описание | Варианты |
---|---|---|
debug_package | Определяем необходимость создания пакета debuginfo (с отладочной информацией). | По умолчанию значение 1 и при сборке пакета также собирается пакет с суффиксом debuginfo. При значении % |
Операторы сравнения
SPEC файл позволяет задавать логику с помощью операторов сравнения. Приведем примеры их использования:
Пример | Описание |
---|---|
%if 0% = 0.13.3-1 %else Requires: hiredis %endif | В данном примере мы проверяем версию системы, на которой идет сборка. Если rhel (релиз системы) меньше 8, то мы указываем в качестве требования hiredis-last. В данном примере это имеет смысл, так как в CentOS 8 пакет hiredis-last переименовали в hiredis. |
%if 0% == 8 . %endif | В данном условии мы проверяем, является ли версия релиза 8. |
%if % != «el» . %endif | Проверяем значение переменной osname. Если она не равна «el», выполняем действие. |
Возможные ошибки
Рассмотрим примеры ошибко, с которыми мы можем столкнуться.
Installed (but unpackaged) file(s) found
Ошибка появляется в конце процесса сборки пакета.
Причина: обнаружены файлы, которые были установлены с помощью make install, но которые не были перечислены в %files. Таким образом, сборщик пакета не знает, что с ними делать.
Решение: секция %files должна содержать все файлы, необходимые для работы приложения. Их нужно перечислить.
Но если у нас есть полная уверенность, что мы перечислили все необходимое, а оставшиеся файлы нам ни к чему, то добавляем в файл spec:
%define _unpackaged_files_terminate_build 0
7 Steps to Build a RPM Package from Source on CentOS / RedHat
Sometimes you might have access to an open source application source code but might not have the RPM file to install it on your system.
In that situation, you can either compile the source code and install the application from source code, or build a RPM file from source code yourself, and use the RPM file to install the application.
There might also be a situation where you want to build a custom RPM package for the application that you developed.
This tutorial explains how to build a RPM package from the source code.
In order to build RPMs, you will need source code, which usually means a compressed tar file that also includes the SPEC file.
The SPEC file typically contains instructions on how to build RPM, what files are part of package and where it should be installed.
The RPM performs the following tasks during the build process.
Once the RPM executes the above steps, it creates the binary package file and source package file.
The binary package file consists of all source files along with any additional information to install or uninstall the package.
It is usually enabled with all the options for installing the package that are platform specific. Binary package file contain complete applications or libraries of functions compiled for a particular architecture. The source package usually consists of the original compressed tar file, spec file and the patches which are required to create the binary package file.
Let us see how to create a simple source and BIN RPM packages using a tar file.
If you are new to rpm package, you may first want to understand how to use rpm command to install, upgrade and remove packages on CentOS or RedHat.
1. Install rpm-build Package
To build an rpm file based on the spec file that we just created, we need to use rpmbuild command.
rpmbuild command is part of rpm-build package. Install it as shown show below.
rpm-build is dependent on the following package. If you don’t have these installed already, yum will automatically install these dependencies for you.
2. RPM Build Directories
rpm-build will automatically create the following directory structures that will be used during the RPM build.
Note: The above directory structure is for both CentOS and RedHat when using rpmbuild package. You can also use /usr/src/redhat directory, but you need to change the topdir parameter accordingly during the rpm build. If you are doing this on SuSE Enterprise Linux, use /usr/src/packages directory.
If you want to use your own directory structure instead of the /root/rpmbuild, you can use one of the following option:
3. Download Source Tar File
Next, download the source tar file for the package that you want to build and save it under SOURCES directory.
For this example, I’ve used the source code of icecase open source application, which is a server software for streaming multi-media. But, the steps are exactly the same for building RPM for any other application. You just have to download the corresponding source code for the RPM that you are trying to build.
4. Create the SPEC File
In this step, we direct RPM in the build process by creating a spec file. The spec file usually consists of the following eight different sections:
Here is the SPEC file that I created for the icecast application to build an RPM file.
Below that line, you will see the make utility which determines the list of files needs to be compiled and compiles them appropriately.
In % install section, the line below the %install that says “make install” is used to take the binaries compiled from the previous step and installs or copies them to the appropriate locations so they can be accessed.
5. Create the RPM File using rpmbuild
Once the SPEC file is ready, you can start building your rpm with rpm –b command. The –b option is used to perform all the phases of the build process. If you see any errors during this phase, then you need to resolve it before re-attempting again. The errors will be usually of library dependencies and you can download and install it as necessary.
During the above rpmbuild install, you might notice the following error messages:
Error 1: XSLT configuration could not be found
Solution 1: Install libxstl-devel
For the xslt-config, you need to install libxstl-devel package as shown below.
This will also install the following dependencies:
Error 2: libvorbis Error
Solution 2: Install libvorbis-devel
For the Ogg Vorbis v1.0, install the libvorbis-devel package as shown below:
This will also install the following dependencies:
6. Verify the Source and Binary RPM Files
Once the rpmbuild is completed, you can verify the source rpm and binary rpm is created in the below directories.
7. Install the RPM File to Verify
As a final step, you can install the binary rpm to verify that it installs successfully and all the dependencies are resolved.
After the above installation, you can verify that your custom created rpm file was installed successfully as shown below.
Сборка rpm пакетов и настройка своего репозитория
В данной статье будет подробно описан процесс создание rpm пакетов и организация репозитория. Прошу всех, кому интересна данная тема, пройти под кат.
Я взялся писать крайне подробно, так что Вы можете пролистать очевидные для Вас вещи.
Оглавление
Установка системы
Наш сервис начинается с момента установки на него операционной системы. Естественно, что для сборки rpm пакетов мы выбираем rhel дистрибутив. В данном случае, был выбран CentOS 7.
Скачать CentOS
Создадим директорию, где будет лежать образ и перейдем в нее:
Далее можно непосредственно скачать образ и необходимые для проверки файлы:
или посредством torrent`а с помощью программы aria2, которую для начала установим:
Проверить образ
Скачать образ мало, нужно проверить его целостность и достоверность, что мы и сделаем.
Скачаем ключ для CentOS 7:
Посмотрим на ключ и импортируем его:
Проверим подпись файла, с контрольной суммой образа:
Как мы видим — все отлично и теперь можем проверить сам образ на целостность:
Запись образа на носитель
После того как мы убедились в целостности образа и его достоверности, неплохо было бы его уже записать и установить! Так сделаем это, но вначале определимся, на что записывать будем.
Запись образа на диск
Для записи данного образа, нам понадобится двухсторонний DVD. Допустим мы его нашли и записываем, установив предварительно wodim:
Запись образа на флешку
Двухсторонний DVD это как то архаично, так что возьмем флешку на 16 гб и запишем образ на нее, но прежде /dev/sda тут — это флешка, а у Вас она может быть другой. Смотри команду fdisk:
Если status=progress не поддерживается, то по старинке:
а можно воспользоваться pv:
Установка
Как поставить Centos 7, решать Вам, тут и за RAID подумать можно и за LVM и много чего еще,
я ставил минимальный пакет.
Процесс установки можно посмотреть в этом ролике.
Преднастройка
После установки системы, нам необходимо настроить наш сервер.
Обновление и установка пакетов
В начале мы обновим все установленные пакеты, далее установим репозиторий epel, в котором есть много что полезного для нас:
Следующим шагом установим группу пакетов, которые понадобятся нам для сборки, а так же ряд пакетов необходимые для развёртывания репозитория.
Для того чтобы комфортно и безопасно управлять сервером настроим SSH.
Безопаснее пользоваться ключами, по этому мы и создадим себе ключи для доступа к серверу на своем рабочем компьютере:
и добавим ключ на сервер:
Необходимо еще закрутить гайки в самой службе. Создадим копию файла конфигурации и приступим к редактированию:
В файле стоит добавить/изменить/раскомментировать следующие строки:
Межсетевой экран
Важно ограничить доступ к нашему серверу. По этой причине настроим межсетевой экран:
Тут мы добавили наши службы http https ftp для доступности извне и ssh, но только для сети 192.168.0.0/28.
Подготовка площадки сборки
Подготовим саму площадку для сборки. Стоит отметить, что вернее всего сборку производить на отдельном виртуальном хосте, активно используя технологию snapshot’ов, но тут я опишу все в едином целом. Так же для сборки нужно выделить отдельного пользователя, не являющемся администратором (т.е. sudo ему недоступно).
Создание директорий
Создаем необходимые директории:
Настройка PGP подписи
Наши пакеты, которые мы соберем, необходимо подписать, что будет обеспечивать целостность и достоверность.
Ключ будем использовать свой или если его нет, то создадим. Создавать ключ стоит на своем рабочем компьютере.
Создадим ключ, если его у нас нет:
Нас попросят ответить на ряд вопросов:
тип ключа, выбираем (1) RSA and RSA (default), размер ключа: 4096, срок действия: 6m, наше имя: Alexander F. Mikhaylov, Email: chelaxe@gmail.com, комментарий, тут можно указать для чего нам ключ: repo и ждем.
Сохраняем наш приватный ключ:
Создадим ключ для отзыва:
Экспорт открытого ключа на keyserver:
Теперь ключ можно и импортировать на наш сервер:
Смотрим где находится gpg утилита:
и настроем файл для подписи пакетов:
Создаем репозиторий
Теперь организуем сам репозиторий.
Создадим директорию, где будем хранить пакеты:
Экспортируем ключ в репозиторий:
Создаем сам репозиторий и подписываем метаданные:
Пакет для репозитория
Собираем пакет для автоматической установки репозитория в систему.
Файл репозитория для yum:
Экспортируем ключ для пакета:
Собираем все в архив:
Создаем SPECS файл для пакета:
На этом этапе нас спросят пароль от нашего PGP ключа.
Копируем созданный пакет в репозиторий и обновляем его:
Не забываем подписать метаданные:
Теперь установим наш репозиторий в систему:
После установки должен появиться репозиторий chelaxe и PGP ключ:
Самое важное тут это SPEC файлы, расписывать о них не стану, но предоставлю ряд ссылок:
и одна полезная команда:
она отобразит готовые макросы для сборки.
Собираем Tmux
Теперь соберем, для примера, что нибудь полезное. Собирать будем tmux — терминальный мультиплексор, без которого работать мне не комфортно. Стоит отметить tmux есть в base репозитории CentOS 7, но версия там 1.8, а мы соберем 2.7. Так же у пакета из base репозитория есть зависимость libevent, мы же соберем tmux со статическими библиотеками последних версий.
Готовим исходники
Скачиваем исходники tmux и необходимых библиотек:
Экспортируем GPG ключи для проверки исходников:
Подготовим файл конфигурации tmux:
Готовим SPEC файл
Этот файл будет интереснее предыдущего SPEC файла:
Сборка
Собираем пакет и добавляем его в репозиторий:
Не забываем подписать метаданные:
Смотри что и как получилось:
Установка и запуск
Устанавливаем наш пакет:
Запускаем tmux и радуемся:
Собираем fbida
Собирать будем fbida — комплект приложений для просмотра изображений в консоли. Данный пакет не нашел под Centos 7.
Готовим исходники
Скачиваем исходники fbida:
Экспортируем GPG ключи для проверки исходников:
Готовим SPEC файл
В этом SPEC файле будет больше зависимостей:
Сборка
Собираем пакет и добавляем его в репозиторий:
Не забываем подписать метаданные:
Установка и запуск
Устанавливаем наш пакет:
Настройка доступа по http/https
Теперь обеспечим доступ к нашему репозиторию по http/https.
Настройка
Первым делом настроем наш Apache:
Далее необходимо добавить/изменить/раскомментировать следующие строки:
Запускаем службу и прописываем ее в автозапуск:
Настраиваем наш репозиторий:
Т.к. в Centos 7 у нас Apache 2.4.6, а не 2.4.8, то параметры Диффи-Хеллмана необходимо вшить в сертификат:
По этой же причине с HTTP/2 у нас ничего не получится, но теперь вы можете собрать сами свежий Apache и воспользоваться HTTP/2.
Проверим конфигурацию и перечитаем конфигурацию:
Сертификат от Let’s Encrypt
Пока у нас свой сертификат и это не красиво, так что получим сертификат от Let’s Encrypt:
При ответе на вопросы, выбираем использование rewrite для перенаправления всех на https. В результате в файле изменяться строки у VirtualHost для http:
и у VirtualHost для https:
Строку Include /etc/letsencrypt/options-ssl-apache.conf закомментируем.
Тут стоит напомнить о необходимости добавить файл с параметрами Диффи-Хеллмана в конец сертификата:
И изменить заголовок HKPK (HTTP Public Key Pinning):
И изменим соответственно строку в конфигурации:
Проверим конфигурацию и перечитаем конфигурацию:
Есть еще одна проблема. Для обновления сертификата добавим запись в крон:
Но этого не достаточно, нужно еще дописать автоматическое добавление файла с параметрами Диффи-Хеллмана и параметры HKPK (HTTP Public Key Pinning).
для исключения в отображении на сайте.
Для vsftpd можно использовать опции:
Тут можно используя модуль mod_autoindex Apache настроить внешний вид. Завернуть в noscript тег и используя html5, css3, javascript, jquery, bootstrap, backbone, awesome сделать конфетку, как это сделал я:
Вот что будет при использовании в браузере без поддержки javascript или с отключенным:
Настроить внешний вид листинга через mod_autoindex или в nginx:
Настройка доступа по ftp
Запускаем службу и прописываем ее в автозапуск:
Заключение
Собственно на этом все. Надеюсь, данный мануал будет Вам полезен.
How to build rpm packages
I have used rpm-based package managers to install software on Red Hat and Fedora Linux since I started using Linux more than 20 years ago. I have used the rpm program itself, yum, and DNF, which is a close descendant of yum, to install and update packages on my Linux hosts. The yum and DNF tools are wrappers around the rpm utility that provide additional functionality, such as the ability to find and install package dependencies.
More Linux resources
Over the years I have created a number of Bash scripts, some of which have separate configuration files, that I like to install on most of my new computers and virtual machines. It reached the point that it took a great deal of time to install all of these packages, so I decided to automate that process by creating an rpm package that I could copy to the target hosts and install all of these files in their proper locations. Although the rpm tool was formerly used to build rpm packages, that function was removed and a new tool, rpmbuild, was created to build new rpms.
When I started this project, I found very little information about creating rpm packages, but I managed to find a book, Maximum RPM, that helped me figure it out. That book is now somewhat out of date, as is the vast majority of information I have found. It is also out of print, and used copies go for hundreds of dollars. The online version of Maximum RPM is available at no charge and is kept up to date. The RPM website also has links to other websites that have a lot of documentation about rpm. What other information there is tends to be brief and apparently assumes that you already have a good deal of knowledge about the process.
In addition, every one of the documents I found assumes that the code needs to be compiled from sources as in a development environment. I am not a developer. I am a sysadmin, and we sysadmins have different needs because we don’t—or we shouldn’t—compile code to use for administrative tasks; we should use shell scripts. So we have no source code in the sense that it is something that needs to be compiled into binary executables. What we have is a source that is also the executable.
For the most part, this project should be performed as the non-root user student. Rpms should never be built by root, but only by non-privileged users. I will indicate which parts should be performed as root and which by a non-root, unprivileged user.
Preparation
Create a student user that can be used for this project and set a password for that user.
Building rpm packages requires the rpm-build package, which is likely not already installed. Install it now as root. Note that this command will also install several dependencies. The number may vary, depending upon the packages already installed on your host; it installed a total of 17 packages on my test VM, which is pretty minimal.
The rest of this project should be performed as the user student unless otherwise explicitly directed. Open another terminal session and use su to switch to that user to perform the rest of these steps. Download a tarball that I have prepared of a development directory structure, utils.tar, from GitHub using the following command:
This tarball includes all of the files and Bash scripts that will be installed by the final rpm. There is also a complete spec file, which you can use to build the rpm. We will go into detail about each section of the spec file.
As user student, using your home directory as your present working directory (pwd), untar the tarball.
Use the tree command to verify that the directory structure of
/development and the contained files looks like the following output:
The mymotd script creates a “Message Of The Day” data stream that is sent to stdout. The create_motd script runs the mymotd scripts and redirects the output to the /etc/motd file. This file is used to display a daily message to users who log in remotely using SSH.
The sysdata script can spew tens of thousands of lines of data about your computer hardware, the installed version of Linux, all installed packages, and the metadata of your hard drives. I use it to document the state of a host at a point in time. I can later use it for reference. I used to do this to maintain a record of hosts that I installed for customers.
You may need to change ownership of these files and directories to student.student. Do this, if necessary, using the following command:
Most of the files and directories in this tree will be installed on Fedora systems by the rpm you create during this project.
Creating the build directory structure
The rpmbuild command requires a very specific directory structure. You must create this directory structure yourself because no automated way is provided. Create the following directory structure in your home directory:
We will not create the rpmbuild/RPMS/X86_64 directory because that would be architecture-specific for 64-bit compiled binaries. We have shell scripts that are not architecture-specific. In reality, we won’t be using the SRPMS directory either, which would contain source files for the compiler.
Examining the spec file
Each spec file has a number of sections, some of which may be ignored or omitted, depending upon the specific circumstances of the rpm build. This particular spec file is not an example of a minimal file required to work, but it is a good example of a moderately complex spec file that packages files that do not need to be compiled. If a compile were required, it would be performed in the %build section, which is omitted from this spec file because it is not required.
Preamble
Comment lines are ignored by the rpmbuild program. I always like to add a comment to this section that contains the exact syntax of the rpmbuild command required to create the package. The Summary tag is a short description of the package. The Name, Version, and Release tags are used to create the name of the rpm file, as in utils-1.00-1.rpm. Incrementing the release and version numbers lets you create rpms that can be used to update older ones.
The License tag defines the license under which the package is released. I always use a variation of the GPL. Specifying the license is important to clarify the fact that the software contained in the package is open source. This is also why I included the license and GPL statement in the files that will be installed.
The URL is usually the web page of the project or project owner. In this case, it is my personal web page.
The Group tag is interesting and is usually used for GUI applications. The value of the Group tag determines which group of icons in the applications menu will contain the icon for the executable in this package. Used in conjunction with the Icon tag (which we are not using here), the Group tag allows adding the icon and the required information to launch a program into the applications menu structure.
The Packager tag is used to specify the person or organization responsible for maintaining and creating the package.
The Requires statements define the dependencies for this rpm. Each is a package name. If one of the specified packages is not present, the DNF installation utility will try to locate it in one of the defined repositories defined in /etc/yum.repos.d and install it if it exists. If DNF cannot find one or more of the required packages, it will throw an error indicating which packages are missing and terminate.
Change the packager name to yours and the URL to your own website if you have one.
%description
The %description section of the spec file contains a description of the rpm package. It can be very short or can contain many lines of information. Our %description section is rather terse.
The %prep section is the first script that is executed during the build process. This script is not executed during the installation of the package.
This script is just a Bash shell script. It prepares the build directory, creating directories used for the build as required and copying the appropriate files into their respective directories. This would include the sources required for a complete compile as part of the build.
In the case of our package, we have no pre-compile sources as all of our programs are Bash scripts. So we simply copy those scripts and other files into the directories where they belong in the installed system.
Note that the exit statement at the end of this section is required.
%files
This section of the spec file defines the files to be installed and their locations in the directory tree. It also specifies the file attributes and the owner and group owner for each file to be installed. The file permissions and ownerships are optional, but I recommend that they be explicitly set to eliminate any chance for those attributes to be incorrect or ambiguous when installed. Directories are created as required during the installation if they do not already exist.
This section is empty in our lab project’s spec file. This would be the place to put any scripts that are required to run during installation of the rpm but prior to the installation of the files.
This section of the spec file is another Bash script. This one runs after the installation of files. This section can be pretty much anything you need or want it to be, including creating files, running system commands, and restarting services to reinitialize them after making configuration changes. The %post script for our rpm package performs some of those tasks.
The comments included in this script should make its purpose clear.
%postun
This section contains a script that would be run after the rpm package is uninstalled. Using rpm or DNF to remove a package removes all of the files listed in the %files section, but it does not remove files or links created by the %post section, so we need to handle that in this section.
This script usually consists of cleanup tasks that simply erasing the files previously installed by the rpm cannot accomplish. In the case of our package, it includes removing the link created by the %post script and restoring the saved original of the motd file.
%clean
This Bash script performs cleanup after the rpm build process. The two lines in the %clean section below remove the build directories created by the rpm-build command. In many cases, additional cleanup may also be required.
%changelog
This optional text section contains a list of changes to the rpm and files it contains. The newest changes are recorded at the top of this section.
Replace the data in the header line with your own name and email address.
Building the rpm
The spec file must be in the SPECS directory of the rpmbuild tree. I find it easiest to create a link to the actual spec file in that directory so that it can be edited in the development directory and there is no need to copy it to the SPECS directory. Make the SPECS directory your pwd, then create the link.
Run the following command to build the rpm. It should only take a moment to create the rpm if no errors occur.
/rpmbuild/RPMS/noarch directory to verify that the new rpm exists there.
Testing the rpm
As root, install the rpm to verify that it installs correctly and that the files are installed in the correct directories. The exact name of the rpm will depend upon the values you used for the tags in the Preamble section, but if you used the ones in the sample, the rpm name will be as shown in the sample command below:
Check /usr/local/bin to ensure that the new files are there. You should also verify that the create_motd link in /etc/cron.daily has been created.
Remove the package.
Experimenting
Now you will change the spec file to require a package that does not exist. This will simulate a dependency that cannot be met. Add the following line immediately under the existing Requires line:
Build the package and attempt to install it. What message is displayed?
We used the rpm command to install and delete the utils package. Try installing the package with yum or DNF. You must be in the same directory as the package or specify the full path to the package for this to work.
Conclusion
There are many tags and a couple sections that we did not cover in this look at the basics of creating an rpm package. The resources listed below can provide more information. Building rpm packages is not difficult; you just need the right information. I hope this helps you—it took me months to figure things out on my own.
We did not cover building from source code, but if you are a developer, that should be a simple step from this point.
Creating rpm packages is another good way to be a lazy sysadmin and save time and effort. It provides an easy method for distributing and installing the scripts and other files that we as sysadmins need to install on many hosts.
Resources
Edward C. Baily, Maximum RPM, Sams Publishing, 2000, ISBN 0-672-31105-4
Edward C. Baily, Maximum RPM, updated online version
RPM Documentation: This web page lists most of the available online documentation for rpm. It includes many links to other websites and information about rpm.