Пакет Debian является не только архивом файлов, предназначенных для установки. Он является частью системы, и в нём описаны взаимоотношения с другими пакетами Debian (зависимости, конфликты, предложения). Он также содержит сценарии, которые выполняются на различных этапах жизненного цикла пакета (при установке, удалении, обновлении). Эти данные, используемые инструментами управления пакетами, не являются частью упакованного программного обеспечения, но содержатся внутри пакета и называются «метаинформацией» (информацией о другой информации).
5.2.1. Описание: файл control
Структура этого файла похожа на заголовки e-mail (как они определены в RFC 2822). Например, для apt файл control
выглядит следующим образом:
$
apt-cache show apt
Package: apt
Version: 1.4.8
Installed-Size: 3539
Maintainer: APT Development Team <deity@lists.debian.org>
Architecture: amd64
Replaces: apt-utils (<< 1.3~exp2~)
Depends: adduser, gpgv | gpgv2 | gpgv1, debian-archive-keyring, init-system-helpers (>= 1.18~), libapt-pkg5.0 (>= 1.3~rc2), libc6 (>= 2.15), libgcc1 (>= 1:3.0), libstdc++6 (>= 5.2)
Recommends: gnupg | gnupg2 | gnupg1
Suggests: apt-doc, aptitude | synaptic | wajig, dpkg-dev (>= 1.17.2), powermgmt-base, python-apt
Breaks: apt-utils (<< 1.3~exp2~)
Description-en: commandline package manager
This package provides commandline tools for searching and
managing as well as querying information about packages
as a low-level access to all features of the libapt-pkg library.
.
These include:
* apt-get for retrieval of packages and information about them
from authenticated sources and for installation, upgrade and
removal of packages together with their dependencies
* apt-cache for querying available information about installed
as well as installable packages
* apt-cdrom to use removable media as a source for packages
* apt-config as an interface to the configuration settings
* apt-key as an interface to manage authentication keys
Description-md5: 9fb97a88cb7383934ef963352b53b4a7
Tag: admin::package-management, devel::lang:ruby, hardware::storage,
hardware::storage:cd, implemented-in::c++, implemented-in::perl,
implemented-in::ruby, interface::commandline, network::client,
protocol::ftp, protocol::http, protocol::ipv6, role::program,
scope::application, scope::utility, sound::player, suite::debian,
use::downloading, use::organizing, use::searching, works-with::audio,
works-with::software:package, works-with::text
Section: admin
Priority: important
Filename: pool/main/a/apt/apt_1.4.8_amd64.deb
Size: 1231676
MD5sum: 4963240f23156b2dda3affc9c0d416a3
SHA256: bc319a3abaf98d76e7e13ac97ab0ee7c238a48e2d4ab85524be8b10cfd23d50d
5.2.1.1. Зависимости: поле Depends
Зависимости определяются в поле Depends
в заголовке пакета. Это список условий, выполнение которых необходимо для корректной работы пакета. Данная информация используется такими инструментами, как apt
, чтобы установить правильные версии необходимых библиотек, которые удовлетворяют зависимости устанавливаемого пакета. Для каждой зависимости диапазон версий, соответствующих этому условию, может быть ограничен. Другими словами, можно сказать, что нам требуется пакет libc6 версии не ниже чем «2.15» (пишется «libc6 (>= 2.15)
»). Операторы сравнения версий следующие:
In a list of conditions to be met, the comma serves as a separator. It must be interpreted as a logical “and”. In conditions, the vertical bar (“|”) expresses a logical “or” (it is an inclusive “or”, not an exclusive “either/or”). Carrying greater priority than “and”, it can be used as many times as necessary. Thus, the dependency “(A or B) and C” is written
A | B, C
. In contrast, the expression “A or (B and C)” should be written as “(A or B) and (A or C)”, since the
Depends
field does not tolerate parentheses that change the order of priorities between the logical operators “or” and “and”. It would thus be written
A | B, A | C
.
Система зависимостей — хороший механизм для обеспечения работоспособности программ, но у него есть и другое применение — «метапакеты». Это пустые пакеты, в которых описаны только зависимости. Они обеспечивают установку группы взаимосвязанных программ, выбранных сопровождающим метапакета; соответственно, apt install метапакет
автоматически установит все эти программы, используя зависимости метапакета. Пакеты gnome, kde-full и linux-image-amd64 являются примерами метапакетов.
5.2.1.2. Конфликты: поле Conflicts
Поле Conflicts
указывает на то, что пакет не может быть установлен, если уже установлен другой пакет. Наиболее распространенными причинами для этого является включение обоими пакетами файлов с одинаковыми именами, или предоставление сервисов на одном и том же порту TCP, или мешающих работе друг друга.
dpkg
откажется установить пакет, если он вызовет конфликт с уже установленным пакетом, за исключением тех случаев, когда новый пакет указывает, что он будет «заменять» установленный пакет, — тогда dpkg
заменит старый пакет на новый. apt
всегда следует вашим указаниям: если вы выберете установку нового пакета, он автоматически предложит удалить проблемный пакет.
5.2.1.3. Несовместимость: поле Breaks
По своему действию поля Breaks
похоже на поле Conflicts
, но оно несёт особый смысл. Оно сообщает, что установка пакета «поломает» другой пакет (или конкретные его версии). Как правило, такая несовместимость между пакетами имеет временный характер, и Breaks
указывает на конкретные несовместимые версии.
dpkg
откажется установить пакет, который поломает уже установленный пакет, и apt
попытается решить проблему путём обновления пакета, который оказался бы сломанным, до более новой версии (которая, как предполагается, будет исправленной и, таким образом, снова совместимой).
Подобные ситуации могут возникнуть в случае обновления без обратной совместимости: это происходит, если новая версия работает не так, как старая, что приводит к сбою в другой программе, если не принять должных мер. Поле Breaks
помогает пользователю не сталкиваться с такими проблемами.
5.2.1.4. Предоставляемое пакетом: поле Provides
Это поле вводит очень интересную концепцию «виртуального пакета». Она имеет много применений, два из которых особенно важны. Первое состоит в использовании виртуального пакета, чтобы привязать к нему общее название сервиса (пакет «предоставляет» сервис). Вторая показывает, что пакет полностью заменяет другой, и что при этом он может удовлетворять зависимости, которые удовлетворил бы другой. Таким образом, можно создать замену пакета без необходимости использовать то же самое имя пакета.
5.2.1.4.1. Предоставление «сервиса»
Давайте рассмотрим первый случай более подробно на примере: все почтовые серверы, такие как postfix или sendmail, «предоставляют» виртуальный пакет mail-transport-agent. Поэтому в любом пакете, для работы которого нужен этот сервис (например менеджере списков рассылки вроде smartlist или sympa), просто указывается зависимость от mail-transport-agent вместо того, чтобы указывать большой, и при этом всё равно неполный список возможных решений (то есть postfix | sendmail | exim4 | …
). Кроме того, бесполезно устанавливать два почтовых сервера на одной машине, поэтому каждый из этих пакетов сообщит о конфликте с виртуальным пакетом mail-transport-agent. Конфликт пакета с самим собой игнорируется системой, но данная технология не допустит установки двух почтовых серверов одновременно.
5.2.1.4.2. Взаимозаменяемость другим пакетом
The Provides
field is also interesting when the content of a package is included in a larger package. For example, the libdigest-md5-perl Perl module was an optional module in Perl 5.6, and has been integrated as standard in Perl 5.8 (and later versions, such as 5.24 present in Stretch). As such, the package perl has since version 5.8 declared Provides: libdigest-md5-perl
so that the dependencies on this package are met if the user has Perl 5.8 (or newer). The libdigest-md5-perl package itself has eventually been deleted, since it no longer had any purpose when old Perl versions were removed.
Эта функция очень полезна, поскольку никогда нельзя предвидеть превратности процесса разработки, и важно иметь возможность подстроиться к переименованию устаревшего ПО или другим автоматическим заменам.
5.2.1.4.3. Прошлые ограничения
Виртуальные пакеты имеют некоторые ограничения, cамым значительным из которых является отсутствие номера версии. Вернемся к предыдущему примеру: зависимость, такая как Depends: libdigest-md5-perl (>= 1.6)
, несмотря на наличие Perl 5.10, никогда не будет считаться удовлетворённой системой управления пакетами — в то время как на самом деле она скорее всего удовлетворена. Не зная этого, пакетная система выбирает наименее опасный путь, предполагая, что версии не соответствуют.
This limitation has been lifted in dpkg 1.17.11, and is no longer relevant in Stretch. Packages can assign a version to the virtual packages they provide with a dependency such as Provides: libdigest-md5-perl (= 1.8)
.
5.2.1.5. Замена файлов: поле Replaces
Поле Replaces
указывает, что пакет содержит файлы, которые также присутствуют в другом пакете, но при этом пакет имеет право заменить их. Без этого поля dpkg
завершится с ошибкой, сообщив, что не может перезаписать файлы другого пакета (формально, можно заставить его сделать это с помощью опции --force-overwrite
, но это не является обоснованной стандартной операцией). Это позволяет выявить потенциальные проблемы и вынуждает сопровождающего изучить вопрос прежде чем добавлять такое поле.
Это поле используется при изменении имени пакета, или когда один пакет включается в состав другого. Это также происходит в случае, если сопровождающий решает распределить файлы по-другому между двоичными пакетами, полученными из одного и того же исходного: заменённый файл больше не принадлежит старому пакету, а только новому.
Если все файлы в установленном пакете были заменены, принимается решение об удалении пакета. Наконец, это поле также указывает dpkg
удалить заменённый пакет в случае конфликта.
5.2.2. Сценарии настройки
Кроме файла control
архив control.tar.gz
в каждом пакете Debian может содержать несколько сценариев, вызываемых dpkg
на разных этапах обработки пакета. В Политике Debian подробно описаны все возможные случаи, в которых вызываются сценарии, и какие аргументы они при этом получают. Эти последовательности могут быть довольно сложными, поскольку если один из сценариев завершается с ошибкой, dpkg
будет пытаться вернуться к нормальному состоянию (насколько это возможно) путём отмены текущей установки или удаления.
Если вкратце, сценарий preinst
вызывается перед установкой пакета, а postinst
после неё. Аналогично, prerm
запускается перед удалением пакета, а postrm
— после. Обновление пакета эквивалентно удалению предыдущей версии и установке более новой. Все возможные ситуации описать здесь не получится, но мы рассмотрим две, встречающиеся чаще всего: установку/обновление и удаление.
5.2.2.1. Установка и обновление
Вот что происходит во время установки пакета (или его обновления):
Для обновления dpkg
запускает old-prerm upgrade новая-версия
.
Также для обновления dpkg
запускает new-preinst upgrade старая-версия
; при установке запускается new-preinst install
. Последним параметром может быть добавлена старая версия, если пакет уже устанавливался раньше, но был удалён (но не вычищен, то есть конфигурационные файлы сохранились).
После этого распаковываются файлы нового пакета. Если файл уже существует, он заменяется, но создаётся временная резервная копия.
При обновлении dpkg
вызывает old-postrm upgrade новая-версия
.
dpkg
обновляет все внутренние данные (список файлов, сценарии настройки и т. п.) и удаляет резервные копии заменённых файлов. Теперь обратного пути нет: dpkg
более недоступны все элементы, необходимые для отката к предыдущему состоянию.
Наконец, dpkg
настраивает пакет, запуская new-postinst configure последняя-настроенная-версия
.
Вот что происходит во время удаления пакета:
dpkg
запускает prerm remove
.
dpkg
удаляет все файлы пакета за исключением конфигурационных файлов и сценариев настройки.
dpkg
запускает postrm remove
. Все сценарии настройки, за исключением postrm
, удаляются. Если пользователь не использует опцию «purge», процесс удаления заканчивается на этом шаге.
Для полного удаления пакета (в случае использования команды dpkg --purge
или dpkg -P
) также удаляются конфигурационные файлы и их копии (*.dpkg-tmp
, *.dpkg-old
, *.dpkg-new
) и временные файлы; после этого dpkg
запускает postrm purge
.
Четыре сценария, описанные выше, дополняются сценарием config
, предоставляемым пакетами, которые используют debconf
для запроса у пользователя информации для настройки. Этот сценарий определяет вопросы, которые будут заданы debconf
во время установки. Ответы заносятся в базу данных debconf
для дальнейшего использования. Эти сценарии обычно выполняются apt
до установки пакетов, последовательно, чтобы сгруппировать вопросы и задать их пользователю в начале процесса. Пред- и послеустановочные сценарии могут впоследствии использовать эту информацию, чтобы действовать в соответствии с пожеланиями пользователей.
5.2.3. Контрольные суммы, список конфигурационных файлов
В дополнение к сценариям сопровождающего и контрольным данным, уже рассмотренным в предыдущих разделах, архив
control.tar.gz
пакета Debian может содержать другие интересные файлы. Первый,
md5sums
, содержит контрольные суммы MD5 для всех файлов пакета. Благодаря ему можно с помощью команды
dpkg --verify
(которая будет изучаться в
Раздел 14.3.3.1, «Auditing Packages with dpkg --verify
») проверить, изменялись ли эти файлы с момента установки. Обратите внимание, что при отсутствии этого файла
dpkg
создаст его динамически во время установки (и сохранит его в базе данных dpkg, как и другие контрольные файлы).
В conffiles
содержится список файлов, которые должны быть обработаны как конфигурационные файлы. Конфигурационные файлы могут быть изменены администратором, и dpkg
постарается сохранить эти изменения во время обновления пакета.
Действительно, в этой ситуации dpkg
ведёт себя настолько интеллектуально, насколько это возможно: если стандартный конфигурационный файл не изменился между двумя версиями, она ничего не делает. Если, однако, файл был изменен, она будет пытаться обновить его. Возможны два варианта развития событий: если администратор не трогал конфигурационный файл, dpkg
автоматически установит новую версию; если же файл был изменен, dpkg
спросит администратора, какую версию он хочет использовать (старую с изменениями или новую из пакета). Для помощи в принятии решения dpkg
показывает «diff
», то есть различия между двумя версиями. Если пользователь предпочтёт оставить старую версию, новая будет храниться в том же месте, в файле с суффиксом .dpkg-dist
. Если же пользователь выбирает новую версию, старая сохраняется в файле с суффиксом .dpkg-old
. Другой вариант заключается в том, чтобы немедленно прервать dpkg
и отредактировать файл, попытавшись внести нужные изменения (ранее обнаруженные с помощью diff
).