Package Tools

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

Package Management

Для создания средств управления пакетами многие разработчики дистрибутивов выбирают мощные интерпретаторы, такие как Python, или даже языки программипрования высокого уровня, требующие применения компиляторов. В качестве графических оболочек для управления пакетами создают программы, использующие такие библиотеки как GTK+ или Qt.

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

Однако если мы хотим предоставить возможность составления дистрибутива, в том числе, для самых простых устройств на микроконтроллерах, мы должны обеспечить лишь необходимый набор средств. Избыточность здесь недопустима. Более того, все средства должны быть применимы, в равной степени как на целевом устройстве, так и в среде cross-разработки, то есть все средства управления пакетами должны быть доступны системе сборки, используя которую можно создавать дистрибутивы с помощью простых Маке-файлов.

Исходя из минимального набора утилит, которые присустствуют в любой системе, основанной на ядре Linux, а именно: coreutils, ncurses, bash, sed, tar, gzip, ... , мы в качестве средств создания системы управления пакетами выбираем bash и dialog.

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

Creating Packages

Утилита make-package предназначена для создания пакетов программ. Перед использованием данной утилиты надо создать временный каталог, разместить в нем все необходимые файлы так, как они будут располагаться в целевой файловой системе. Создать в этом временном каталоге скрытые служебные файлы .PKGINFO, .DESCRIPTION, .INSTALL и, если данный пакет имеет зависимости от других пакетов в целевой системе, файл .REQUIRES.

Затем перейти в этот временный каталог и выполнить команду:

$ make-package [options] DESTDIR

Здесь DESTDIR – обязательный параметр, определяющий целевой каталог, в котором будет размещен созданный пакет.

Так, например, если мы разместили все необходимые файлы в каталоге /tmp/pkgtool-package и хотим получить готовый пакет в каталоге /tmp, то наши действия должны быть такими:

$ cd /tmp/pkgtool-package
$ make-package ..

или

$ cd /tmp/pkgtool-package
$ make-package /tmp

Заметим, здесь мы показали, что DESTDIR может быть как абсолютным, так и относительным путем для размещения результирующего пакета. Главное то, что целевым каталогом не должен быть каталог, в котором размещены исходные файлы.

Рассмотрим теперь управления утилиты make-package.

Options

Разумеется, утилита make-package принимает стандартные для всех утилит управления, такие как '-h | --help' и '-v | --version', служащие для получения краткой справки и номера версии, соответственно.

Однако ключевыми, при создании пакетов, являются управления, отвечающие за упаковку символических ссылок на файлы, если таковые присутствуют, и за размещение созданных пакетов в целевом каталоге.

Restore Links

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

Разумеется не все пользователи захотят следовать этому правилу. Поэтому утилита make-package предусматривает возможность различного поведения по отношению к символическим ссылкам посредством управления --linkadd. На следующем листинге показаны возможные комбинации применения управления --linkadd:

$ make-package -l yes ..
$ make-package -l y ..
$ make-package -l no ..
$ make-package -l n ..

$ make-package --linkadd yes ..
$ make-package --linkadd y ..
$ make-package --linkadd no ..
$ make-package --linkadd n ..

$ make-package --linkadd=yes ..
$ make-package --linkadd=y ..
$ make-package --linkadd=no ..
$ make-package --linkadd=n ..

Если в исходном каталоге пакета присутствуют символические ссылки, а управление --linkadd не задано, то утилита make-package задаст вопрос, подобный следующему:

$ make-package ..

Package maker, version 1.0.

Search for symbolic links: 

sbin/pkgtool/install -> install-package

Restore symbolic links script:
( cd sbin/pkgtool ; rm -rf install )
( cd sbin/pkgtool ; ln -sf install-package install )

It is recommended to remove symbolic links and create the '.RESTORELINKS'
script.

Do you want create the '.RESTORELINKS' script for this package
and remove symbolic links from the package archive ([y]es, [n]o)?

Ответ 'y' будет означать то, что символические ссылки в пакете будут удалены и, к набору скрытых служебных файлов пакета будет добавлен файл .RESTORELINKS, в котором будет размещен скрипт восстановления символических ссылок. За восстановление символических ссылок после инсталляции пакета на целевую систему будет отвечать утилита install-package, работу поторой мы рассмотрим чуть позже.

Для того чтобы утилита make-package не задавала лишних вопросов, мы рекомендуем всегда задавать управление --linkadd={yes|no}.

FLAVOUR

При формировании дистрибутивов пакеты обычно распределяют по группам. Кроме того, при создании репозиториев готовых пакетов удобно хранить пакеты в соответствующих каталогах для облегчения поиска.

Утилита make-package поддерживает управление такими каталогами групп. Если в файле .PKGINFO задать переменную group, то результирующий пакет будет помещен в каталог ${group}, который, в свою очередь, будет создан в целевом каталоге DESTDIR.

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

$ make-package -fl FLAVOUR ..

$ make-package --flavour FLAVOUR ..

$ make-package --flavour=FLAVOUR ..

где FLAVOUR задает имя подкаталога в каталоге ${group}.

Таким образом, если мы задали значение переменной group равным group=libs и воспользовались управлением '--flavour=512M', например для того, чтобы создать модификацию некоторой библиотеки для устройства с 512-ю мегабайтами оперативной памяти, то после создания пакета:

$ make-package --linkadd=yes --flavour=512M ..

он будет помещен в каталог ../libs/512M, относительно исходного каталога пакета.

.PKGINFO

Для создания пакета, прежде всего, надо приготовить файл описания пакета. Это простой текстовый файл с именем .PKGINFO. Данный файл следует рассматривать как часть скрипта, написанного на языке командного интерпретатора shell. Поскольку самым популярным в среде Linux является Bourne Again Shell, мы используем именно этот интерпретатор.

Существует минимальный набор переменных, задание которых обязательно для нормальной работы:

pkgname
имя пакета. Например, pkgtool ;
pkgver
версия пакета. Hапример, 0.0.1 ;
arch
архитектура. Например, rk3288-glibc ;
distroname
имя дистрибутива. Например, radix ;
distrover
версия дистрибутива. Например, 1.0 ;

Поскольку файл .PKGINFO, по сути, является частью скрипта на языке bash, пробелы до и после знака равенства не допускаются.

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

pkgname=pkgtool
pkgver=0.0.1
arch=rk328x-glibc
distroname=radix
distrover=1.0

в текущую среду с помошью команды

$ . ./.PKGINFO

мы сможем однозначно определить имя файла, содержащего данный пакет программ:

$ echo "PACKAGE_TARBALL=$pkgname-$pkgver-$arch-$distroname-$distrover.txz"
PACKAGE_TARBALL=pkgtool-0.0.1-rk328x-glibc-radix-1.0.txz

$

Архитектура, для которой собран данный пает, носит условный характер. Пользователь может выбирать самостоятельно принципы именования целевых архитектур собственного дистрибутива. Мы придержиаемся упрощеннй схемы, которая достаточна для того, чтобы определить целевую платформу. Здесь, например, используется название линейки процессоров RK328X и название библиотеки языка C. Первое название практически однозначно определяет используемый toolchain, а второе – целевую операционную систему, базирующуюся на ядре Linux.

В качестве имени и версии дистрибутива обычно используются значения переменных $(DISTRO_NAME) и $(DISTRO_VERSION), соответственно, определенных в файле constants.mk системы сборки.

Recommended Variables

Мы настоятельно рекомендуем, при создании файла .PKGINFO, задавать еще четыре переменные:

group
имя группы, которой принадлежит данный пакет. Например, base ;
short_description
короткое описание пакета. Hапример, "Package Tools";
url
сайт создателя пакета. Например, 'https://www.radix.pro';
license
тип лицензии.

Рассмотрим эти переменные подробно.

Group Name

Значение переменной group задается без кавычек и фактически представляет собой имя каталога (относительно целевого каталога ${DESTDIR}), в который будет помещен пакет, после его создания.

Мы придерживаемся следующих правил определения групп пакетов.

app
консольные приложения без графического интерфейса или приложения использующие ncurses;
base
базовые системные пакеты, такие, например, как pkgtool или start/stop скрипты;
dev
приложения, необходимые для разработки программ. Это всевозможные языки программирования, системные заголовочные файлы, autotools, cmake и т.д.;
dict
словари;
doc
средства автоматизации документирования;
libs
библиотеки;
net
сетевые утилиты и библиотеки;
xorg
пакеты, входящие в состав X.org и, использующие протокол X11;
wayland
пакеты, использующие протокол Wayland;

Относительно групп xorg и wayland подразумевается, что исходное дерево каталогов имеет иерархию вида: протокол/версия/реализация. Так, например, X.org проект предоставляет реализацию X Window и, в идеале, иерархия исходного дерева для создания пакетов может быть представлена формулой X/11R7.7/xorg/group/package. Однако поскольку фактически уже трудно выделить те версии пакетов, которые однозначно принадлежат той или иной версии X, мы сокращаем формулу до: X11/xorg/group/package, оставляя пакеты, не входящие в классическую поставку X Windows, например, созданные в рамках проекта Freedesktop, в каталогах X11/group (формула: X11/group/package). При этом имя каталога group не должно обязательно совпадать с именем группы пакетов group. Так например в каталоге X11/X.org все пакеты имеют группу group=xorg независимо от подкаталога, в котором расположены Make-файлы сборки пакета. В свою очередь, для пакетов, не входящих в состав X.org, мы, как правило, используем имя каталога group, равное имени группы, но без префикса 'x'. Например, в каталоге X11/libs расположены пакеты с именем группы, равным group=xlibs.

xapp
приложения, использующие протокол X11, но не входящие напрямую в поставку X Window от X.org (X11R7.7);
xfont
шрифты сторонних производителей для X Window;
xlibs
библиотеки использующие протокол X11.

Протокол Wayland также подразумевает различные реализации и мы, когда Wayland получит распространение, будем придерживаться такого же принципа структуризации наборов программ. И, наверное, стоит ожидать наборов wapp, wlibs, и так далее.

Short Description

Короткое описание пакета short_description задается одной строкой в двойных кавычках. Длина не должна превышать 45 символов.

В Make-файлах, короткое описание пакета задается, например, следующим образом

###                         |---handy-ruler-------------------------------|
BIN_PKG_SHORT_DESCRIPTION  = Package Tools

и используется при автоматическом формировании файла .PKGINFO. Поскольку лексика Make-файлов имеет ограничения на допустимые символы в значениях переменных, при задании коротких описаний в теле Make-файла используется маскирование запрещенных символов с помощью специального символа backslash ('\').

Маскированию подлежат такие символы, как '&', '*', '(', ')'. В Make-файлах такое маскирование будет выглядеть примерно следующим образом:

###                          |---handy-ruler-------------------------------|
KSBA_PKG_SHORT_DESCRIPTION  = X.509 \& CMS library for S/MIME and TLS

При формировании .PKGINFO файла вручную, маскировать такие символы не обязательно но допустимо. В любом случае, утилита make-package удалит маскирующие символы '\' из описания.

Хотя короткое описание пакета не обязательно, мы настоятельно рекомендуем задавать переменную short_description в .PKGINFO файлах. Короткое описание пакета используется при построении деревьев межпакетных зависимостей для показа информации о пакете.

WEB Address

Адрес разработчика пакета пердоставляется для получения обратной связи. Зная адрес разработчика, пользователи всегда могут обратится за помощью или просто указать на какие-либо недостатки. В файле constants.mk системы сборки данный адрес представлен переменной BUG_URL, значение которой всегда доступно в пользовательских Make-файлах, например, следующим образом.

SQLITE_PKG_URL = $(BUG_URL)
               .
               .
               .
        echo "url=$(SQLITE_PKG_URL)" >> $(SQLITE_PKG)/.PKGINFO ; \
               .
               .

Мы рекомендуем не забывать о пользователях и всегда задавать переменную url при формировании пакетов программ.

License Type

Тип лицензии license задается без кавычек, одним словом, например GPLv3, LGPLv2, BSD, MIT.

В качестве примера полного описания пакета в файле .PKGINFO приведем следующий текст:

pkgname=pkgtool
pkgver=0.0.1
arch=rk328x-glibc
distroname=radix
distrover=1.0
group=base
short_description="Package Tools"
url=https://www.radix.pro
license=GPLv2

Здесь имеется вся необходимая информация о пакете. Однако это еще не все. Следующим обязательным файлом является развернутое описание пакета .DESCRIPTION.

.DESCRIPTION

Утилита make-package использует только строки, начинающиеся с имени пакета, за которым следует символ двоеточие ':'. Поскольку все остальные строки игнорируются, можно использовать следующий шаблон, в котором описаны все правила создания длинного описания пакета:

# HOW TO EDIT THIS FILE:
# The "handy ruler" below makes it easier to edit a package description.  Line
# up the first '|' above the ':' following the base package name, and the '|'
# on the right side marks the last column you can put a character in. You must
# make exactly 11 lines for the formatting to be correct.  It's also
# customary to leave one space after the ':'.

        |-----handy-ruler------------------------------------------------------|
pkgtool: pkgtool 0.0.1 (Package Tools)
pkgtool:
pkgtool: This is a set of scripts used for package creation, installing, etc.
pkgtool:
pkgtool:
pkgtool:
pkgtool:
pkgtool:
pkgtool:
pkgtool:
pkgtool:

Еще раз подчеркнем, что описание должно насчитывать ровно 11 строк, причем последнюю лучше оставить пустой, так как утилита make-package добавит к этому описанию еще две строки и будет лучше, если между полным описанием пакета и дополнительной информацией останется некий разделитель.

Длина строк не должна превышать 70 символов, включая пробел в начале строки.

Теперь несколько слов о дополнительной информации, которую предоставляет утилита make-package.

При создании пакета в файл .PKGINFO будут добавлены еще две переменные:

uncompressed_size=144K
total_files=11

Первая определяет объем, занимаемый пакетом в целевой файловой системе, а вторая – полное количество файлов, составляющих пакет.

Во время инсталляции пакета пользователю в конце полного описания пакета, будет представлен объем, занимаемый пакетом:

 Uncompressed Size: 144K
   Compressed Sise: 20K

А при удалении пакета вместо объема в сжатом виде будет выведено полное количество файлов, составляющих пакет:

 Uncompressed Size: 144K
       Total Files: 11

Если инсталляция пакета будет производиться в текстовом режиме (без использования библиотеки dialog), то в терминале пользователя будет отображена следующая информация.

bash-4.2$ install-package --root /opt/rootfs base/pkgtool-0.0.1-rk328x-glibc-radix-1.0.txz

 Installing package pkgtool... 
|======================================================================|
 
 pkgtool 0.0.1 (Package Tools)
 
 This is a set of scripts used for package creation, installing, etc.
 
 
 
 
 
 
 
 
 Uncompressed Size: 144K
   Compressed Sise: 20K
|======================================================================|

bash-4.2$

.INSTALL

Данный файл представляет собой скрипт командного интерпретатора, состоящий из шести функций. Функции описывают действия, которые необходимо произвести в системе на том или ином этапе инсталляции пакета. Все этапы рассматриваются относительно момента распаковки пакета и копирования файлов в корневую файловую систему. Если никаких действий совершать не надо, то функции должны возвращять истину (true).

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

#!/bin/sh 

# arg 1:  the new package version
pre_install() {
   /bin/true
}

# arg 1:  the new package version
post_install() {
   /bin/true
}

# arg 1:  the new package version
# arg 2:  the old package version
pre_update() {
   /bin/true
}

# arg 1:  the new package version
# arg 2:  the old package version
post_update() {
   post_install
}

# arg 1:  the old package version
pre_remove() {
   /bin/true
}

# arg 1:  the old package version
post_remove() {
   /bin/true
}


operation=$1
shift

$operation $*

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

Рассмотрим три основных режима инсталляции.

  1. Управление пакетами на работающей системе.
  2. Инсталляция системы с внешнего носителя.
  3. Приготовление целевой файловой системы на машине разработчика.

Первый режим характеризуется тем, что в скрипте инсталляции можно пользоваться всеми средствами, которые представлены в системе. Надо просто знать, что на данном этапе уже инсталлировано в систему, а чем еще пользоваться нельзя.

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

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

Для того чтобы скрипт инсталляции пакета мог определить текущий режим инсталляции, достаточно предусмотреть создание специального файла во втором режиме; таким файлом, например, может служить /etc/system-installer, создаваемый системмным инсталлятором в начале своей работы и удаляемый по окончанию инсталляции системы.

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

if [ -r proc/sys/kernel/osrelease -a ! -r /etc/system-installer ] ; then

   # we are on the working system

fi

Приведем несколько примеров.

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

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

#!/bin/sh 

# arg 1:  the new package version
pre_install() {
   /bin/true
}

# arg 1:  the new package version
post_install() {
   #
   # NOTE:
   #   'install-info' can work using relative paths and we can make use build machine
   #   utility during installation to the some partition and use target 'install-info'
   #   during installation directly on the running target machine.
   #
   if [ -x /usr/bin/install-info ] ; then
     install-info --info-dir=usr/share/info usr/share/info/grep.info.gz 2> /dev/null
   elif ! grep "(grep)" usr/share/info/dir 1> /dev/null 2> /dev/null ; then
     cat << EOF >> usr/share/info/dir

Text creation and manipulation
* grep: (grep).                 Print lines matching a pattern.
EOF
   fi
}

# arg 1:  the new package version
# arg 2:  the old package version
pre_update() {
   /bin/true
}

# arg 1:  the new package version
# arg 2:  the old package version
post_update() {
   post_install
}

# arg 1:  the old package version
pre_remove() {
   if [ -x /usr/bin/install-info ] ; then
     install-info --delete --info-file=usr/share/info/grep.info.gz --dir-file=usr/share/info/dir 2> /dev/null
   fi
}

# arg 1:  the old package version
post_remove() {
   /bin/true
}


operation=$1
shift

$operation $*

Легко заметить, что в данном скрипте заданы относительные пути, и работая в корне целевой файловой системы, скрипт правильно выполнит все необходимые действия. При этом будет использоваться утилита install-info, которая доступна как на машине разработчика (третий режим инсталляции), так и на работающей целевой машине (первый режим). Автору дистрибутива необходимо только предусмотреть наличие утилиты install-info в файловой системе итсталлятора (второй режим), инсталляцию пакета texinfo на целевую машину перед текущим пакетом (первый режим), ну и, разумеется, наличие texinfo на машине разработчика.

В следующем примере мы покажем действия, которые надо выполнять лишь в том случае, когда мы работаем в первом режиме инсталляции.

Например, обновлять кэш шрифтов в режиме инсталляции пакета имеет смысл только на работающей системе. Следовательноб мы можем предусмотреть эти действия лишь в двух случаях: во-первых, при инсталляции пакета в первом режиме, и, во-вторых, при самостоятельном старте системы. Во всех остальных случаях данные действия не нужны.

#!/bin/sh 

# arg 1:  the new package version
pre_install() {
   /bin/true
}

# arg 1:  the new package version
post_install() {
   # We use an relative path to 'proc/sys/kernel/osrelease' because we have
   # to be sure that we are running on the target platform. Only in this case
   # we will use absolute path to mkfonts{dir,scale}.
   if [ -r      proc/sys/kernel/osrelease \
        -a ! -r /etc/system-installer     \
        -a -x   /usr/bin/mkfontdir        \
        -a -x   /usr/bin/mkfontscale ] ; then
     ( cd /usr/share/fonts/TTF
       mkfontscale .
       mkfontdir .
     )
   fi
   # We use an relative path to 'proc/sys/kernel/osrelease' because we have
   # to be sure that we are running on the target platform. Only in this case
   # we will use absolute path to fc-cache.
   if [ -r      proc/sys/kernel/osrelease \
        -a ! -r /etc/system-installer     \
        -a -x   /usr/bin/fc-cache ] ; then
     /usr/bin/fc-cache -f
   fi
}

# arg 1:  the new package version
# arg 2:  the old package version
pre_update() {
   /bin/true
}

# arg 1:  the new package version
# arg 2:  the old package version
post_update() {
   post_install
}

# arg 1:  the old package version
pre_remove() {
   /bin/true
}

# arg 1:  the old package version
post_remove() {
   /bin/true
}


operation=$1
shift

$operation $*

В заключение скажем, что большое количество примеров скриптов инсталляции можно найти в репозитории исходных текстов дистрибутива по адресу https://svn.radix.pro/svn/platform/trunk.

.REQUIRES

Может отсутствовать или быть пустым. Если есть пакеты, от которых зависит данный пакет, то файл .REQUIRES должен содержать записи, подобные следующим:

libtiff=4.0.3
libxshmfence=1.1
libXinerama=1.1.3
giflib=5.1.0
libXft=2.3.2
libXrandr=1.4.2
libXaw=1.0.12
gettext=0.18.3.2

Здесь должны быть использованы только знаки равенства '='. Знаки больше ('>'), меньше ('<'), больше или равно ('>=') и меньше или равно ('<=') недопустимы.

Знак равенства '=' фактически означает то, что версия требуемого пакета должна быть не меньше указанной.

В системе сборки предусмотрены функции, с помощью которых файлы .REQUIRES можно строить автоматически по списку REQUIRES, представленному в начале Make-файла.

Install Package

Утилита install-package предназначена для установки одного или нескольких пакетов, указанных в командной строке.

$ install-package [options] package_tarball[s]

Основной задачей инсталляции пакета является распаковка его содержимого в целевую файловую систему. При этом заполняется так называемая Информационная База Пакетов и ведется лог.

Автору пакета предоставляется возможность выполнить дополнительные операции непосредственно перед началом распаковки содержимого пакета в целевую файловую систему, а также после распаковки. Для этого в файле .INSTALL предусмотрены функции pre_install() и post_install(). В разделе, посвященном утилите make-package, приведен шаблон файла .INSTALL, содержимое которого позволяет понять, что обоим функциям в качестве аргумента передается версия пакета.

Как правило, если на входе задано несколько пакетов, то при невозможности инсталлировать какой-либо пакет из списка утилита install-package переходит к следующему по списку пакету. Однако если во время инсталляции пакета произошла ошибка, которая может привести к нарущению целостности Информационной Базы Пакетов, утилита install-package останавливает работу полностью.

Результаты работы утилиты install-package рассматриваются в разделе Информационная База Пакетов.

Options

Ключевым управлением утилиты install-package является опция --root, с помощью которой задается полный путь к точке монтирования целевой файловой системы. Если данный путь не задан, то утилита install-package попытается инсталлировать пакет в корневой каталог /.

Если в целевой файловой системе на момент инсталляции еще не развернута Информационная База Пакетов, то утилита install-package создаст все необходимые каталоги и, тем самым, создаст базу пакетов.

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

Info Modes

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

bash-4.2$ install-package --root /opt/rootfs base/pkgtool-0.0.1-rk328x-glibc-radix-1.0.txz

 Installing package pkgtool... 
|======================================================================|
 
 pkgtool 0.0.1 (Package Tools)
 
 This is a set of scripts used for package creation, installing, etc.
 
 
 
 
 
 
 
 
 Uncompressed Size: 144K
   Compressed Sise: 20K
|======================================================================|

bash-4.2$

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

Infodialog

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

В первом случае, можно воспользоваться управлением --infodialog. При этом информация о пакетах отображается в виде чередующихся сообщений с использованием программы dialog, которая, в свою очередь, использует библиотеку ncurses.

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

Однако на режим диалога влияют не только управления --infodialog и --menudialog. Программа install-package учитывает еще и приоритет пакета. Приоритет может задаваться непосредственно в качестве аргумента управления --priority и, кроме того, утилита install-package может читать приоритеты пакетов из списка инсталляции. Списки инсталляции мы рассмотрим несколько позже.

Следует помнить, что в режимах console и infodialog инсталляция происходит автоматически, без предоставления пользователю возможности отменить установку. Но если приоритет пакета равен SKIP, то пакет будет игнорирован и утилита install-package перейдет к установке следующего пакета, согласно входного списка. Пакеты с приоритетами, равными REQUIRED, RECOMMENDED и OPTIONAL инсталлируются автоматически, при этом в информационном сообщении отображается уровень приоритета.

Menudialog

Для того чтобы предоставить пользователю возможность выбора, какой пакет устанавливать в систему, а какой нет, предусмотрен режим menudialog. Если управление --menudialog задано, и приоритет пакета равен REQUIRED, то пакет инсталлируется автоматически в режиме infodialog. Если в данном режиме приоритет пакета оказывается равным SKIP, то пакет игнорируется.

В остальных случаях пользователю предоставляется возможность либо установить данный пакет, либо отменить инсталляцию данного пакета и перейти к следующему пакету из набора, переданного на вход утилиты install-package. Кроме того, пользователь может полностью остановить процесс инсталляции всего набора пакетов, поданного на вход утилиты install-package.

Для того чтобы диалог с пользователем осуществлялся даже тогда, когда приоритет пакета равен REQUIRED или SKIP, необходимо задать управление --always-ask.

Priority

Как отмечалось ранее, приоритет пакета или группы пакетов, подаваемых на вход утилиты install-package, можно установить с помощью управления --priority. При этом уровень приоритета, заданный в списке инсталляции, учитываться не будет.

Следует помнить, что управление --priority устанавливает одинаковый приоритет для всех пакетов, которые в данный момент отданы программе install-package.

Packages List

Если не задавать приоритет пакета явно, то утилита install-package попытается прочесть приоритет из файла .pkglist. Утилита install-package подразумевает наличие файла .pkglist в каталоге, в котором находится инсталлируемый пакет. Такое поведение удобно в том случае, если мы имеем набор пакетов и предусмотрели порядок их инсталляции в заранее приготовленном файле .pkglist.

Такой способ задания приоритетов удобен в случае, когда мы имеем некоторый набор пакетов, расположенных в одном каталоге, и хотим воспользоваться утилитой install-package и при этом передаем имена пакетов непосредственно в командной строке. Утилита install-package не следует списку .pkglist, а вего лишь читает из него уровни приоритета пакетов.

Явно указать место разсположения списка инсталляции можно с помощью управления --pkglist. Аргументом должно являться полное имя файла, содержащего список.

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

Более полное использование возможностей, предоставляемых набором утилит управления пакетами, рассмотрено в разделе, посвященном утилите install-pkglist. Там же подробно рассматривается формат и назначение списков инсталляции.

Update Package

Утилита update-package предназначена для обновления одного или нескольких пакетов, указанных в командной строке. Важно заметить, что утилита update-package не делает никаких предположений о номерах версий пакетов, то есть пользователь может как обновить пакет, так и установить предыдущую версию пакета. Однако следует помнить, что при проверке межпакетных зависимостей, величина версий пакетов имеет значение и, если при обновлении пакета предыдущей версией все зависимости, накладываемые данным пакетом, будут удовлетворены, то это не означает, что другие пакеты в системе, зависимые от данного пакета, смогут нормально работать.

$ update-package [options] package_tarball[s]

Утилита update-package принимает такие же аргументы, что и утилита install-package. Но в отличие от простой инсталляции пакета, утилита update-package сначала проверяет наличие пакета в системе, затем удаляет файлы, принадлежащие ранее инсталлированной версии пакета, и лишь затем производит инсталляцию файлов новой версии пакета в целевую файловую систему.

Для нормального обновления пакета скрипт инсталляции .INSTALL должен предусматривать наличие функций pre_update() и post_update(), которые, в отличие от функций pre_install() и post_install(), могут рассчитывать на два аргумента. Первый является номером версии нового пакета, а второй – номером версии пакета, установленного до начала процедуры обновления.

В разделе, посвященном утилите make-package, приведен шаблон файла .INSTALL, дающий полное представление о количестве и назначении аргументов функций.

Следует отметить, что в случае возникновения каких-либо ошибок на этапе работы функции pre_update(), когда еще не разрушено содержимое существующей в системе предыдущей версии пакета, утилита update-package прекратит работу, и пользователь может быть уверен в том, что старый пакет остался без изменений.

Если же ошибка произойдет во время работы функции post_update(), то утилита update-package удалит из системы файлы, принадлежащие новой версии пакета, которые были скопированы в целевую файловую систему до вызова функции post_update(). Таким образом пакет окажется деинсталлирован.

При возникновении ошибок на каком-либо этапе обновления пакета пользователю следует удостоверится в целостности Информационной Базы Пакетов.

Install Packages List

Представить назначение утилиты install-pkglist легче всего на примере.

Допустим мы создали временный каталог products и расположили в нем пакеты:

   products
   ├── base
   │   ├── pkgtool-0.0.1-rk328x-glibc-radix-1.0.sha256
   │   ├── pkgtool-0.0.1-rk328x-glibc-radix-1.0.txz
   │   └── pkgtool-0.0.1-rk328x-glibc-radix-1.0.txt
   ├── dict
   │   ├── words-ru-0.99f7-1-rk328x-glibc-radix-1.0.sha256
   │   ├── words-ru-0.99f7-1-rk328x-glibc-radix-1.0.txz
   │   ├── words-ru-0.99f7-1-rk328x-glibc-radix-1.0.txt
   │   ├── words-ru-0.99f8-1-rk328x-glibc-radix-1.0.sha256
   │   ├── words-ru-0.99f8-1-rk328x-glibc-radix-1.0.txz
   │   └── words-ru-0.99f8-1-rk328x-glibc-radix-1.0.txt
   │
   └── .pkglist

Кроме того, в файле .pkglist мы разместили список:

pkgtool:0.0.1:Package Tools:base/pkgtool-0.0.1-rk328x-glibc-radix-1.0.txz:install:REQUIRED
words-ru:0.99f7-1:Russian wordlist:dict/words-ru-0.99f7-1-rk328x-glibc-radix-1.0.txz:install:REQUIRED
words-ru:0.99f8-1:Russian wordlist:dict/words-ru-0.99f7-1-rk328x-glibc-radix-1.0.txz:update:RECOMMENDED

Тогда, перейдя в каталог products и выполнив команду install-pkglist:

 $ cd products
 $ install-pkglist --root /destination

мы осуществим инсталляцию в каталог /destination.

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

Choose Packages Dialog
Fig.1. Choose Packages Dialog

В представленном диалоге рядом с именами пакетов с процедурой "update" (поле 5) будет начертано большими буквами слово UPDATE, как показано на следующем рисунке.

Choose Packages Dialog
Fig.2. Confirm UPDATE words-ru package

Отменить инсталляцию можно с помощью клавиши Escape или воспользовавшись кнопкой <Cancel>.

Нажав на кнопку <Ok>, останется только наблюдать за чередующимися сообщениями об инсталлируемых пакетах.

Необходимо отметить здесь, что система сборки позволяет создавать списки инсталляции автоматически. Управлять такими списками путем отмены отдельных пакетов надо с осторожностью, понимая, что если мы отменим инсталляцию пакета, который необходим в системе для работы других пакетов мы, тем самым, можем нарушить целостность дистрибутива. Кроме того, если возникнет такая ситуация, утилита install-pkglist остановит свою работу. Если же есть настоятельная необходимость не соблюдать межпакетные зависимости, то отменить отслеживание зависимостей можно с помошью управления --skip-requires. В этом случае пакеты будут устанавливаться независимо, и Информационная База Пакетов не будет содержать правильную информацию о зависимостях пакетов друг от друга.

Setup Database

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

    var
    └── log
        └── radix
            ├── packages
            │   ├── pkgtool-0.0.2-rk328x-glibc-radix-1.0
            │   ├── words-en_CA-7.1-rk328x-glibc-radix-1.0
            │   ├── words-en_CA-huge-7.1-rk328x-glibc-radix-1.0
            │   ├── words-en_CA-small-7.1-rk328x-glibc-radix-1.0
            │   ├── words-en_GB-insane-7.1-rk328x-glibc-radix-1.0
            │   └── words-ru-0.99f7-1-rk328x-glibc-radix-1.0
            ├── removed_packages
            │   └── pkgtool-0.0.1-rk328x-glibc-radix-1.0
            └── setup
                └── setup.log

Располагается база в каталоге /var/log/radix. Имя каталога radix соответствует названию дистрибутива. Система сборки предусматривает возможность изменения имени дистрибутива перед ее использованием. Для этого в файле constants.mk задается переменная с именем DISTRO_NAME. Именно ее значение используется для создания всех утилит, входящих в состав набора программ управления пакетами.

Каталог /var/log/radix/packages содержит так называемые log-файлы пакетов, установленных в системе. Каталог /var/log/radix/removed_packages, соответственно, содержит log-файлы деинсталлированных, с помощью утилиты remove-package пакетов. В каталоге /var/log/radix/setup размещается файл setup.log, в котором отображаются все действия с пакетами, происходящие в системе. Кроме того, каталог /var/log/radix/setup может содержать скрипты настройки системы, которые могут быть использованы как на этапе работы системного инсталлятора, так и для настройки системы во время ее работы.

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

PACKAGE NAME: pkgtool
PACKAGE VERSION: 0.0.1
ARCH: rk328x-glibc
DISTRO: radix
DISTRO VERSION: 1.0
GROUP: base
URL: https://www.radix.pro
LICENSE: GPLv2
UNCOMPRESSED SIZE: 144K
TOTAL FILES: 11
REFERENCE COUNTER: 5
words-ru=0.99f7-1
words-en_CA-small=7.1
words-en_CA-huge=7.1
words-en_GB-insane=7.1
words-en_CA=7.1
REQUIRES:
PACKAGE DESCRIPTION:
pkgtool: pkgtool 0.0.1 (Package Tools)
pkgtool:
pkgtool: This is a set of scripts used for package creation, install, etc.
pkgtool:
pkgtool:
pkgtool:
pkgtool:
pkgtool:
pkgtool:
pkgtool:
pkgtool:
RESTORE LINKS:
INSTALL SCRIPT:
#!/bin/sh 

# arg 1:  the new package version
pre_install() {
   /bin/true
}

# arg 1:  the new package version
post_install() {
   /bin/true
}

# arg 1:  the new package version
# arg 2:  the old package version
pre_update() {
   /bin/true
}

# arg 1:  the new package version
# arg 2:  the old package version
post_update() {
   post_install
}

# arg 1:  the old package version
pre_remove() {
   /bin/true
}

# arg 1:  the old package version
post_remove() {
   /bin/true
}


operation=$1
shift

$operation $*
FILE LIST:
sbin/pkgtool/change-refs
sbin/pkgtool/check-db-integrity
sbin/pkgtool/check-package
sbin/pkgtool/check-requires
sbin/pkgtool/install-package
sbin/pkgtool/install-pkglist
sbin/pkgtool/make-package
sbin/pkgtool/make-pkglist
sbin/pkgtool/pkginfo
sbin/pkgtool/pkglog
sbin/pkgtool/remove-package
sbin/pkgtool/update-package

Любой log-файл содержит семь разделов. Первый раздел содержит информацию, в основном, полученную из файла .PKGINFO:

  1. Общая информация о пакете.
PACKAGE NAME: pkgtool
PACKAGE VERSION: 0.0.1
ARCH: rk328x-glibc
DISTRO: radix
DISTRO VERSION: 1.0
GROUP: base
URL: https://radix.pro
LICENSE: GPLv2
UNCOMPRESSED SIZE: 144K
TOTAL FILES: 11

Здесь отсутствует короткое описание пакета потому, что в нем нет необходимости. Далее по порядку следуют разделы, содержащие:

  1. Список пакетов, зависящих от данного, с указанием их числа.
  2. Список пакетов, от которых зависит сам пакет.
  3. Полное описание пакета.
  4. Скрипт восстановления символических ссылок, полученный на этапе создания пакета.
  5. Скрипт инсталляции пакета.
  6. Полный список файлов, инсталлированных в систему. Имена файлов здесь представлены относительно корневого каталога.

Названия разделов записаны заглавными буквами с обязательным завершающим символом двоеточия (':'):

REFERENCE COUNTER:
REQUIRES:
PACKAGE DESCRIPTION:
RESTORE LINKS:
INSTALL SCRIPT:
FILE LIST:

Если пакет был удален из системы с помощью утилиты remove-package или при обновлении посредством утилиты update-package, то его log-файл перемещается в каталог /var/log/radix/removed_packages.

Пользователю системы такая структура базы удобна тем, что он всегда может отыскать информацию о пакете или узнать, инсталлирован какой-либо пакет, простым поиском файла с соответствующим названием в каталоге /var/log/radix/packages.

Remove Package

Удалить пакет из системы можно с помощью утилиты remove-package. Аргументом данной утилиты может являться либо имя файла архива, содержащего пакет, либо имя log-файла Информационной базы пакетов.

Для того, чтобы удалить пакет не взирая на то, что при этом межпакетные зависимости будут разрушены, необходимо использовать управление --skip-refs.

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

Разумеется, на этапе отладки дистрибутива данные управления допустимы. Но на работающей целевой системе лучше не пользоваться управлениями --skip-refs и --skip-requires, а следовать рекомендациям утилит управления пакетами.