Руководство разработчика по пакетированию приложений

За пределами традиции

Подход, описанный в данном разделе, не применим ко всем пакетам, но он приводит к увеличению производительности при установке в неоднородную среду. Приведенная здесь информация практически не относится к пакетам, поставляемым как часть ОС Solaris (собранные пакеты); однако на несобранных пакетах можно попрактиковаться в нетрадиционных способах создания пакетов.

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

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

Несвязанные пакеты должны размещаться в каталоге /opt с тем, чтобы гарантировать отсутствие влияния нового пакета на существующие программные продукты.

Другой взгляд на составные пакеты

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

Иными словами, поскольку "перемещаемый" означает, что объект может быть установлен в любом месте и по-прежнему работать, ни один стартовый сценарий, запускаемый с помощью 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 . Правильный каталог может быть составлен одним из двух способов.

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

Пример. Составной пакет

Ниже приведен пример файлов pkginfo и pkgmap для составного пакета.

Файл pkginfo

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

Файл pkgmap

: 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.


Примечание –

При назначении каталога классу всегда помните о порядке создания и удаления.