Product SiteDocumentation Site

5.2. Метаинформация пакета

Пакет 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)»). Операторы сравнения версий следующие:
  • <<: меньше;
  • <=: меньше или равна;
  • =: равна (однако «2.6.1» — не то же самое, что и «2.6.1-1»);
  • >=: больше или равна;
  • >>: больше.
В списке условий запятая играет роль разделителя. Её следует интерпретировать как логическое «и». Внутри условий вертикальная черта («|») означает логическое «или» (включающее «или», а не исключающее «строго одно из»). Поскольку оно имеет более высокий приоритет, чем «и», его можно использовать столько раз, сколько потребуется. Так, зависимость «(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 в нём не стало смысла.
Использование поля Provides для того, чтобы не нарушать зависимости

Рисунок 5.1. Использование поля Provides для того, чтобы не нарушать зависимости

Эта функция очень полезна, поскольку никогда нельзя предвидеть превратности процесса разработки, и важно иметь возможность подстроиться к переименованию устаревшего ПО или другим автоматическим заменам.
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. Установка и обновление

Вот что происходит во время установки пакета (или его обновления):
  1. Для обновления dpkg запускает old-prerm upgrade новая-версия.
  2. Также для обновления dpkg запускает new-preinst upgrade старая-версия; при установке запускается new-preinst install. Последним параметром может быть добавлена старая версия, если пакет уже устанавливался раньше, но был удалён (но не вычищен, то есть конфигурационные файлы сохранились).
  3. После этого распаковываются файлы нового пакета. Если файл уже существует, он заменяется, но создаётся временная резервная копия.
  4. При обновлении dpkg вызывает old-postrm upgrade новая-версия.
  5. dpkg обновляет все внутренние данные (список файлов, сценарии настройки и т. п.) и удаляет резервные копии заменённых файлов. Теперь обратного пути нет: dpkg более недоступны все элементы, необходимые для отката к предыдущему состоянию.
  6. dpkg обновит все конфигурационные файлы, выводя запрос пользователю, если это невозможно сделать автоматически. Подробности этой процедуры рассмотрены в Раздел 5.2.3, «Контрольные суммы, список конфигурационных файлов».
  7. Наконец, dpkg настраивает пакет, запуская new-postinst configure последняя-настроенная-версия.

5.2.2.2. Удаление пакета

Вот что происходит во время удаления пакета:
  1. dpkg запускает prerm remove.
  2. dpkg удаляет все файлы пакета за исключением конфигурационных файлов и сценариев настройки.
  3. dpkg запускает postrm remove. Все сценарии настройки, за исключением postrm, удаляются. Если пользователь не использует опцию «purge», процесс удаления заканчивается на этом шаге.
  4. Для полного удаления пакета (в случае использования команды 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).