itmo_conspects

Extra 3. Установка ПО, пакетные менеджеры

Данный конспект был основан на записи лекций №10 (*тык*), №11 (*тык*), №12 (*тык*) с канала А. В. Маятина

Скомпилированное ядро поставляется в виде сжатого образа vmlinuz, который содержит ПО, нужные модули для управления аппаратным обеспечением и интерфейс системных вызов для взаимодействия с ядром. Ядро не содержит:

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

Из-за этого установка ПО совершается кодом из пользовательского пространства системы. Ключевые проблемы появления программ, которые устанавливают ПО, это:


Всего есть 3 способа:

  1. Установка из исходного кода - пользователь скачивает архив с исходным кодом, далее пользователь сам находит нужные зависимости и компилирует программу
  2. Установка из локального пакета

    Пакет отличается от архива с исходным кодом тем, что содержит вместо кода готовый исполняемый файл и информацию о программе (версия, автор, зависимости). Также пакет содержит нужные скрипты, которые сами устанавливают нужные зависимости, решают конфликты других пакетов и их версий, а также добавляют программу в /usr/bin

    Пользователю нужно лишь найти и скачать нужный пакет, вместо того, чтобы мучиться с установкой зависимостей

    Эволюцией таких скриптов стал пакетный менеджер - специальная программа, которая хранит базу данных установленных пакетов, из-за чего может управлять зависимостями. Тогда пакету достаточно хранить всего лишь список нужных библиотек. Например, при удалении одного пакета менеджер может удалять его зависимости, но только те, которые не нужны другим установленным пакетам

  3. Установка из удаленного репозитория

    Современные пакетные менеджеры умеют скачивать пакеты из удаленных репозиториев. Удаленные репозитории представляют базы данных, которые хранят все версии пакетов, загруженных разработчиком, и полный список зависимостей. Также репозиторий гарантирует, что в нем окажутся все зависимости любого пакета

    Удаленные репозитории также отвечают за безопасность предоставляемого ПО. Разработчик может криптографически подписать пакет своим приватным ключом. Далее при отправки репозиторий проверяет, что этот пакет действительно от этого разработчика

    Современные дистрибутивы поставляют свои пакетные менеджеры:

    • С дистрибутивами Ubuntu и Debian идет пакетный менеджер dpkg (от Debian Package), который управляется через apt (Advanced Package Tool)
    • С дистрибутивами Fedora и Red Hat Enterprise Linux идет rpm (RPM Package Manager, ранее Red Hat Package Manager), который управляется через утилиту dnf (от Dandified YUM, буквально “изысканная вкуснятина”). Ранее вместо dnf использовалась утилита yum (от Yellowdog Updater, Modified)
    • С дистрибутивом Arch Linux идет пакетный менеджер pacman (сокращение от package manager)

Как правило последний способ самый удобный, так как, введя всего лишь одну команду (например, apt install fastfetch), можно установить программу и пользоваться. Но, чтобы пакет попал в удаленный репозиторий, он должен пройти нужные проверки, в том числе проверку на востребованность - затратно поддерживать пакет, который почти не востребован и к тому же усложняет граф зависимостей

Помимо этого дистрибутивов Linux очень много, поэтому делать пакеты для каждого дистрибутива осмелиться не каждый разработчик

По этой причине в Linux существуют все 3 способа


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

Установка ПО из исходного кода

Как правило, исходный код хранится в архиве с расширением .tar.gz. Сначала каталог с файлами:

Этот архив распаковывается в каталог. В каталоге есть скрипт, который указывает, как эту программу нужно собрать

В случае проектов на языке C используется утилита Make. Тогда в каталоге будет файл Makefile, в нем, как правило, указаны действия для 4 целей:

Также как правило архив содержит скрипт configure - этот скрипт создает конфигурацию и Makefile под эту систему. Дело в том, что установленный в системе библиотеки могут располагаться в разных местах. configure распознает, где установлены библиотеки, и создает нужный Makefile. Также configure позволяет управлять установкой, например, выбрать место установленной программы

Поэтому установка такой программы может быть выполнена тремя командами:

./configure   # создание конфигурации
make          # компиляция
make install  # установка

Установка ПО из пакета

Если для выбранного ПО существует пакет под нужный дистрибутив, то можно установить его вместо сборки исходного кода

Исторически сложилось так, что разные дистрибутивы имеют разный формат пакетов, которые несовместимы между собой. Разница форматов появилась из-за различия архитектурных особенностей

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

Рассмотрим два распространенных формата

Пакет формата deb

Такой формат используется в дистрибутивах Ubuntu, Debian, Linux Mint и других производных

Пакет формата deb представляет архив с расширением .deb (архивация происходит через утилиту ar). В этом архиве есть 3 файла в таком порядке:

В архиве control.tar.gz находятся файлы, которые не устанавливаются в систему напрямую, а используются пакетным менеджером dpkg для управления установкой. Ключевые файлы в нем:

В другом архиве data.tar.gz содержатся файлы, которые будут скопированы в файловую систему: исполняемые файлы, библиотеки, документация и так далее. Пути к файлам внутри архива указываются относительно корня файловой системы. Содержимое архива может выглядеть так:

usr
├── bin
│   └── flashfetch
└── share
    ├── fastfetch
    │   └── presets
    │       └── ...
    ├── man
    │   └── man1
    │       └── fastfetch.1
    └── ...

Таким образом, программа dpkg:

Источник: https://manpages.debian.org/unstable/dpkg-dev/deb.5.en.html


Помимо создания пакетов с готовыми программами, формат предполагает создание пакетов с исходным кодом. Такой пакет состоит из 3 частей:

Дальше из этих двух архивов с помощью утилиты dpkg-buildpackage собирает готовый пакет .deb

Пакет формата rpm

Такой формат используется в дистрибутивах Red Hat Enterprise Linux, Fedora, CentOS, AlmaLinux, openSUSE, Oracle Linux и других

Пакет формата rpm - не просто архив ar, а архив с расширением .rpm со своими полями:

Сама полезная нагрузка содержит файлы, которые будут скопированы в файловую систему, наподобие как сделано в пакетах формата deb, например:

usr
├───bin
│       fastfetch
├───lib
│   └───...
└───share
    ├───doc
    │   └───fastfetch
    │           README.md
    ├───fastfetch
    ├───man
    │   └───man1
    │           fastfetch.1.gz
    └───...

Исходный пакет, который содержит исходный код программы и имеет расширение .src.rpm, устроен иначе, в нем вместо одного архива в полезной нагрузки есть:

Здесь проявляется ключевое отличие пакета rpm от пакета deb: вместо множества файлов в пакете rpm вся информация хранится в файле <пакет>.spec. Этот файл может выглядеть так:

Name:           fastfetch
Version:        2.61.0
Release:        1%{?dist}
Summary:        Fast neofetch-like system information tool

License:        MIT
URL:            https://github.com/fastfetch-cli/fastfetch
Source0:        %{url}/archive/%{version}/%{name}-%{version}.tar.gz

BuildRequires:  cmake
...
BuildRequires:  yyjson-devel

Recommends:     hwdata
Suggests:       libXrandr
...
Suggests:       elfutils-libelf

ExcludeArch:    %{ix86}

%description
fastfetch is a neofetch-like tool for fetching system information and
displaying them in a pretty way. It is written in c to achieve much better
performance, in return only Linux and Android are supported. It also uses
mechanisms like multithreading and caching to finish as fast as possible.


%prep
%autosetup -p1


%build
%cmake -DBUILD_TESTS=ON -DENABLE_SYSTEM_YYJSON=ON -DBUILD_FLASHFETCH=OFF
%cmake_build


%check
%ctest


%install
%cmake_install


%files
%license LICENSE
%doc README.md
%{_bindir}/%{name}
%{_datadir}/%{name}/
%{_mandir}/man1/fastfetch.1*
%{_datadir}/bash-completion/completions/%{name}
%{_datadir}/fish/vendor_completions.d/%{name}.fish
%{_datadir}/zsh/site-functions/_%{name}


%changelog
<журнал изменений>

Сначала идет преамбула. Она содержит метаданные самого пакета:

На основе этих тегов формируется стандартное имя пакета: Name-Version-Release.Architecture.rpm

Потом идет тело файла, которое состоит из серии секций, каждая из которых отвечает за свой этап сборки. Основные из них это:


Сам пакет формата rpm устанавливается утилитой rpm. Эта утилита умеет только устанавливать пакет из уже скачанного файла. Чтобы загружать зависимости и пакеты из удаленного репозитория, существуют другие утилиты:

Сейчас из-за проблем с совместимостью yum все еще поставляется с дистрибутивами