Пакет Debian является не только архивом файлов, предназначенных для установки. Он является частью системы, и в нём описаны взаимоотношения с другими пакетами Debian (зависимости, конфликты, предложения). Он также содержит сценарии, которые выполняются на различных этапах жизненного цикла пакета (при установке, удалении, обновлении). Эти данные, используемые инструментами управления пакетами, не являются частью упакованного программного обеспечения, но содержатся внутри пакета и называются «метаинформацией» (информацией о другой информации).
5.2.1. Описание: файл control
Структура этого файла похожа на заголовки e-mail (как они определены в RFC 2822). Например, для apt файл control
выглядит следующим образом:
$
apt-cache show apt
Package: apt
Version: 0.9.7.9+deb7u1
Installed-Size: 3271
Maintainer: APT Development Team <deity@lists.debian.org>
Architecture: amd64
Replaces: manpages-pl (<< 20060617-3~)
Depends: libapt-pkg4.12 (>= 0.9.7.9), libc6 (>= 2.4), libgcc1 (>= 1:4.1.1), libstdc++6 (>= 4.6), debian-archive-keyring, gnupg
Suggests: aptitude | synaptic | wajig, dpkg-dev, apt-doc, xz-utils, python-apt
Conflicts: python-apt (<< 0.7.93.2~)
Description-ru: менеджер пакетов с интерфейсом командной строки
Этот пакет содержит инструменты командной строки для поиска и
управления пакетами, а также запроса информации о пакетах путём
низкоуровневого доступа ко всем возможностям библиотеки
libapt-pkg.
.
Включены следующие инструменты:
* apt-get для получения пакетов и информации о них из
достоверных источников и для установки, обновления и удаления
пакетов вместе с их зависимостями
* apt-cache для запроса доступной информации об установленных и
доступных для установки пакетов
* apt-cdrom для использования внешних носителей информации в
качестве источников пакетов
* apt-config в качестве интерфейса для настройки параметров
* apt-key в качестве интерфейса для управления ключами для
проверки ключей аутентификации
Description-md5: 9fb97a88cb7383934ef963352b53b4a7
Tag: admin::package-management, hardware::storage, hardware::storage:cd,
implemented-in::c++, interface::commandline, network::client,
protocol::ftp, protocol::http, protocol::ipv6, role::program,
suite::debian, use::downloading, use::searching,
works-with::software:package
Section: admin
Priority: important
Filename: pool/main/a/apt/apt_0.9.7.9+deb7u1_amd64.deb
Size: 1258056
MD5sum: f403a84515c37e3232b7fcf9664c3e30
SHA1: abe3610c4c619eccacc8bc985369c780189e9958
SHA256: 8f2ada8ed29831ae97264d5ce51410755b25f940c277eacacfe6803cc3ae7540
5.2.1.1. Зависимости: поле Depends
Зависимости определяются в поле Depends
в заголовке пакета. Это список условий, выполнение которых необходимо для корректной работы пакета. Данная информация используется такими инструментами, как apt
, чтобы установить правильные версии необходимых библиотек, которые удовлетворяют зависимости устанавливаемого пакета. Для каждой зависимости диапазон версий, соответствующих этому условию, может быть ограничен. Другими словами, можно сказать, что нам требуется пакет libc6 версии не ниже чем «2.15» (пишется «libc6 (>= 2.15)
»). Операторы сравнения версий следующие:
В списке условий запятая играет роль разделителя. Её следует интерпретировать как логическое «и». Внутри условий вертикальная черта («|») означает логическое «или» (включающее «или», а не исключающее «строго одно из»). Поскольку оно имеет более высокий приоритет, чем «и», его можно использовать столько раз, сколько потребуется. Так, зависимость «(A или B) и C» записывается в виде
A | B, C
. Напротив, выражение «A или (B и C)» следует записывать как «(A или B) и (A или C)», поскольку поле
Depends
не допускает использования скобок, меняющих порядок приоритетов между логическими операторами «или» и «и». То есть должно писаться
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. Взаимозаменяемость другим пакетом
Поле Provides
также полезно в случаях, когда содержание пакета включается в состав другого, более крупного пакета. Например модуль Perl libdigest-md5-perl был необязательным в Perl 5.6, но стал стандартным в Perl 5.8 (и более поздних версиях, в частности 5.20, входящей в Jessie). Поэтому в пакете perl, начиная с версии 5.8, указывается Provides: libdigest-md5-perl
, чтобы зависимости от этого пакета были удовлетворены при установке Perl версии 5.8 (или новее). Сам пакет libdigest-md5-perl в конечном итоге был удален, поскольку после удаления старых версий Perl в нём не стало смысла.
Эта функция очень полезна, поскольку никогда нельзя предвидеть превратности процесса разработки, и важно иметь возможность подстроиться к переименованию устаревшего ПО или другим автоматическим заменам.
5.2.1.4.3. Прошлые ограничения
Виртуальные пакеты имеют некоторые ограничения, cамым значительным из которых является отсутствие номера версии. Вернемся к предыдущему примеру: зависимость, такая как Depends: libdigest-md5-perl (>= 1.6)
, несмотря на наличие Perl 5.10, никогда не будет считаться удовлетворённой системой управления пакетами — в то время как на самом деле она скорее всего удовлетворена. Не зная этого, пакетная система выбирает наименее опасный путь, предполагая, что версии не соответствуют.
Это ограничение было снято в dpkg версии 1.17.11 и более не актуально для Jessie. Пакеты могут назначать версию предоставляемым ими виртуальным пакетам при помощи зависимости, например: 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
).