Подход, описанный в данном разделе, не применим ко всем пакетам, но он приводит к увеличению производительности при установке в неоднородную среду. Приведенная здесь информация практически не относится к пакетам, поставляемым как часть ОС Solaris (собранные пакеты); однако на несобранных пакетах можно попрактиковаться в нетрадиционных способах создания пакетов.
Причиной стимулирования использования перемещаемых пакетов является поддержка следующего требования:
При добавлении или удалении пакета существующее желательное поведение установленных программных продуктов не должно измениться.
Несвязанные пакеты должны размещаться в каталоге /opt с тем, чтобы гарантировать отсутствие влияния нового пакета на существующие программные продукты.
Существуют два правила, которым необходимо следовать при создании полнофункционального составного пакета:
Разместить базовый каталог там, где находится абсолютное большинство объектов пакета.
Если объект пакета размещается в обычном каталоге, не являющимся базовым каталогом (например, /etc), укажите этот объект в виде абсолютного имени пути в файле prototype.
Иными словами, поскольку "перемещаемый" означает, что объект может быть установлен в любом месте и по-прежнему работать, ни один стартовый сценарий, запускаемый с помощью init во время загрузки, не может считаться перемещаемым! И, хотя в поставляемом пакете вполне можно указать /etc/passwd в качестве относительного пути, есть только одно место, где он может быть размещен.
При создании составного пакета абсолютные пути должны работать так, чтобы не влиять на уже установленное программное обеспечение. Пакет, полностью размещаемый в каталоге /opt, обходит эту проблему, поскольку никакие существующие файлы ему не мешают. При включении файла из каталога /etc в пакет необходимо гарантировать, что абсолютные имена путей будут вести семя так же, как это ожидается от относительных имен путей. Рассмотрите следующие примеры.
В таблицу добавляется запись или объект представляет собой новую таблицу, которая скорее всего будет изменена другими программами или пакетами.
Определите объект как файловый типа e и относящийся к классу build, awk или sed. Сценарий, выполняющий эту задачу, должен удалять себя так же эффективно, как добавляет.
Необходимо добавить запись в /etc/vfstab для обеспечения поддержки нового твердотельного жесткого диска.
Запись в файле pkgmap может быть такой:
1 e sed /etc/vfstab ? ? ? |
Сценарий request спрашивает оператора, должен ли каталог /etc/vfstab быть изменен пакетом. Если оператор отвечает “no” (нет), то сценарий запроса выведет на печать инструкции о том, как выполнить это задание вручную, и выполнит
echo "CLASSES=none" >> $1 |
Если оператор отвечает “yes” (да), тогда сценарий выполнит
echo "CLASSES=none sed" >> $1 |
активируя сценарий действия над классом, который произведет необходимые изменения. Класс sed означает, что файл пакета /etc/vfstab представляет собой программу sed, содержащую операции по установке и удалению одноименного файла в целевой системе.
Объект представляет собой совершенно новый файл, который вряд ли будет изменяться в будущем, или он заменяет файл, принадлежащий другому пакету.
Определите объект пакета как тип файла f и установите его с помощью сценария действия над классом, способного отменить изменения.
В каталоге /etc необходим совершенно новый файл для предоставления необходимой информации для поддержки твердотельного жесткого диска с именем /etc/shdisk.conf. Запись в файле pkgmap может выглядеть следующим образом:
. . . 1 f newetc /etc/shdisk.conf . . . |
Сценарий действия над классом i.newetc отвечает за установку этого и любых других файлов, которые должны быть размещены в каталоге /etc. Он проверяет наличие в этом каталоге другого файла. Если файла нет, сценарий просто скопирует новый файл на место. Если же там уже существует файл, сценарий произведет его резервное копирование перед установкой нового файла. Сценарий r.newetc удаляет эти файлы и, если требуется, восстанавливает оригиналы файлов. Ниже представлен ключевой фрагмент установочного сценария.
# i.newetc while read src dst; do if [ -f $dst ]; then dstfile=`basename $dst` cp $dst $PKGSAV/$dstfile fi cp $src $dst done if [ "${1}" = "ENDOFCLASS" ]; then cd $PKGSAV tar cf SAVE.newetc . $INST_DATADIR/$PKG/install/squish SAVE.newetc fi |
Обратите внимание, что сценарий использует переменную среды PKGSAV для сохранения резервной копии заменяемого файла. Когда аргумент ENDOFCLASS передается в сценарий, команда pkgadd сообщает сценарию, что это последние записи в данном классе, после чего сценарий производит архивирование и сжатие файлов, сохраненных с помощью частной программы сжатия, хранящейся в установочном каталоге пакета.
Использование переменной среды PKGSAV во время обновления пакета представляется ненадежным; однако, если пакет не обновляется (посредством внесения изменений, например), то архивный файл остается в безопасности. Следующий сценарий удаления содержит программный код, который решает другую проблему - старые версии команды pkgrmне передают сценариям правильный путь к переменной среды PKGSAV.
Сценарий удаления может выглядеть так:
# r.newetc # make sure we have the correct PKGSAV if [ -d $PKG_INSTALL_ROOT$PKGSAV ]; then PKGSAV="$PKG_INSTALL_ROOT$PKGSAV" fi # find the unsquish program UNSQUISH_CMD=`dirname $0`/unsquish while read file; do rm $file done if [ "${1}" = ENDOFCLASS ]; then if [ -f $PKGSAV/SAVE.newetc.sq ]; then $UNSQUISH_CMD $PKGSAV/SAVE.newetc fi if [ -f $PKGSAV/SAVE.newetc ]; then targetdir=dirname $file # get the right directory cd $targetdir tar xf $PKGSAV/SAVE.newetc rm $PKGSAV/SAVE.newetc fi fi |
Данный сценарий использует частный не установленный алгоритм (unsquish), который расположен в установочном каталоге базы данных пакета. Это происходит автоматически с помощью команды pkgadd во время установки. Все сценарии, не опознанные явно командой pkgadd как сценарии "только для установки", остаются в этом каталоге для использования командой pkgrm. Нельзя рассчитывать на местоположение каталога, но можно положиться на то, что каталог является неструктурированным и содержит все надлежащие информационные файлы и установочные сценарии, необходимые для пакета. Данный сценарий находит каталог благодаря тому, что сценарий действия над классом наверняка будет исполняться из каталога, содержащего программу unsquish.
Обратите также внимание на то, что в данном сценарии просто не предполагается, что целевым каталогом является каталог /etc. В действительности это может быть каталог /export/root/client2/etc . Правильный каталог может быть составлен одним из двух способов.
Использовать конструкцию ${PKG_INSTALL_ROOT}/etc или
Путем принятия имени каталога файла, передаваемого командой pkgadd (что и делает этот сценарий).
Используя данный подход для каждого абсолютного объекта в пакете, можно быть уверенным, что существующее желаемое поведение не изменится или, по крайней мере, его можно восстановить.
Ниже приведен пример файлов pkginfo и pkgmap для составного пакета.
PKG=SUNWstuf NAME=software stuff ARCH=sparc VERSION=1.0.0,REV=1.0.5 CATEGORY=application DESC=a set of utilities that do stuff BASEDIR=/opt VENDOR=Sun Microsystems, Inc. HOTLINE=Please contact your local service provider EMAIL= MAXINST=1000 CLASSES=none daemon PSTAMP=hubert990707141632 |
: 1 1758 1 d none SUNWstuf/EZstuf 0775 root bin 1 f none SUNWstuf/EZstuf/dirdel 0555 bin bin 40 773 751310229 1 f none SUNWstuf/EZstuf/usrdel 0555 bin bin 40 773 751310229 1 f none SUNWstuf/EZstuf/filedel 0555 bin bin 40 773 751310229 1 d none SUNWstuf/HRDstuf 0775 root bin 1 f none SUNWstuf/HRDstuf/mksmart 0555 bin bin 40 773 751310229 1 f none SUNWstuf/HRDstuf/mktall 0555 bin bin 40 773 751310229 1 f none SUNWstuf/HRDstuf/mkcute 0555 bin bin 40 773 751310229 1 f none SUNWstuf/HRDstuf/mkeasy 0555 bin bin 40 773 751310229 1 d none /etc ? ? ? 1 d none /etc/rc2.d ? ? ? 1 e daemon /etc/rc2.d/S70dostuf 0744 root sys 450 223443 1 i i.daemon 509 39560 752978103 1 i pkginfo 348 28411 760740163 1 i postinstall 323 26475 751309908 1 i postremove 402 33179 751309945 1 i preinstall 321 26254 751310019 1 i preremove 320 26114 751309865 1 i r.daemon 320 24573 742152591 |
Хотя S70dostufпринадлежит к классу daemon, каталоги, которые ведут к нему (и которые уже находятся на месте во время установки), принадлежат к классу none. Даже если каталоги являются уникальными для этого пакета, все равно следует оставить их в классе none. Причина этого кроется в том, что каталоги необходимо создавать в первую, а удалять в последнюю очередь, что всегда истинно для класса none. Команда pkgadd создает каталоги; они не копируются из пакета и не передаются в сценарий действия над классом для создания. Вместо этого они создаются командой pkgadd перед тем, как она вызывает установочный сценарий действия над классом, а команда pkgrm удаляет каталоги после завершения удаления сценария действия над классом.
Это означает, что если каталог в особом классе содержит объекты в классе none, то при попытке команды pkgrm удалить этот каталог произойдет сбой, поскольку каталог не будет вовремя освобожден. Если объект класса none необходимо вставить в каталог какого-либо особого класса, этот каталог еще не будет существовать в это время для принятия такого объекта. Команда pkgadd создаст каталог динамически в ходе установки объекта и, возможно, не сможет синхронизировать атрибуты этого каталога на момент появления его определения в файле pkgmap.
При назначении каталога классу всегда помните о порядке создания и удаления.