Библиотека сайта rus-linux.net
Упаковка программ с помощью RPM, часть 2: Обновление и деинсталляция программ
Оригинал: "Packaging software with RPM, Part 2: Upgrading and uninstalling software"Автор: Martin Streicher
Дата публикации: 12 January 2010
Перевод: Н.Ромоданов
Дата перевода: февраль 2010 г.
Краткое содержание: В этой второй статье из серии из трех статей, посвященных менеджеру пакетов RPM, изучается, как использовать пакеты RPM для обновления и деинсталляции программного обеспечения в системах Linux.
В телекоммуникационной отрасли понятие "последняя миля" подразумевает инфраструктуру, строительные конструкции, затраты и прочие сложности, связанные с предоставлением услуг большому числу потребителей. Кабельный провайдер может проложить канал связи из одного конца страны в другой с помощью спутниковой связи; однако совсем другое дело, когда нужно рыть траншеи и прокладывать кабель, чтобы подключиться к каждому дому и каждому предприятию. В некоторых случаях понятие последней мили может не обязательно указывать точное расстояние - это могут быть миллионы миль.
В других отраслях тоже сталкиваются с трудносями, эквивалентными понятию последней мили в телекоммуникационной отрасли. Бакалейные лавки теряют доходы из-за того, что "последняя миля" обходится им так дорого. Почтовая служба Соединенных Штатов продолжает испытывать серьезные убытки на последней миле (буквально!) доставки писем. Разработчики программного обеспечения также лицом к лицу сталкиваются с "последней милей". После того, как вы создадите свою программу, она будет всего лишь только коллекцией большого количества нулей и единиц до тех пор, пока она не будет развернута в системе. Концептуально установка очень проста, но точно также, как и с доставкой проводов, бананов и писем, проблема кроется в деталях.
Первая статья данной серии познакомила вас с RPM — популярной системой доставки программного обеспечения. Вы можете обнаружить менеджер пакетов RPM во многих дистрибутивах Linux, а технология RPM, как таковая, широко используется для развертывания коммерческих программ и программ с открытым исходным кодом, например, в системах Red Hat Linux и Fedora Core Linux. В первой статье также было показано, как собирать приложения в пакеты и как установливать их из исходного кода на чистую систему.
В настоящей статье продолжим изучение RPM и углубимся в вопросы обновления и деинсталляции существующего программного обеспечения. В третьей и заключительной статье будут рассмотрены реже встречающиеся задачи, такие как установка патчей и поставка исходного кода.
Вся правда об обновлении программ
Первоначальная установка программы — это самый простейший случай развертывания программного обеспечения. В целевой системе (т. е. той, на которую происходит установка) отсутствуют демоны, бинарные и конфигурационные файлы и файлы с данными из вашего пакета, так что при первой установке нет необходимости останавливать работу программы, делать резервные копии, выполнять восстановление и, возможно, объединять файлы.
Однако, если в системе, в которой осуществляется установка вашей программы, имеется ее предыдущая или текущая версия, либо если ваша программа тесно взаимодействует с другим кодом и сервисами, ваш пакет RPM должен действовать с особой осторожностью с тем, чтобы не уничтожить рабочие настройки. Вам может потребоваться остановить процессы, подменить или предварительно сохранить файлы, а затем перезапустить приложение после того, как новый код будет скопирован в систему. Конечно, не всегда можно обеспечить обратную совместимость. В таких случаях ваш пакет RPM должен вносить минимально возможное количество изменений с тем, чтобы сохранить систему функциональной и безопасной. В некоторых случаях это может означать, что потребуется создать скрипты, которые проанализируют старые настройки и трансформируют их в новые.
В RPM есть четыре способа добавления команд в процесс установки и удаления программ: два - для установки и два — для удаления. Их все можно использовать прямо в системе, где происходит установка, и их, как правило, достаточно для выполнения практически всего, что может потребоваться. Эти следующие четыре способа:
- Все команды, перечисленные в разделе
%pre
, выполняются прежде, чем будет установлен ваш пакет. - Команды из раздела
%post
выполняются после того, как ваш пакет будет установлен. - Раздел
%preun
исполняется перед тем, как ваш пакет будет удален из системы. - Команды из раздела
%postun
отработают только после того, как пакет будет уже удален из системы.
Таким образом, порядок операций, выполняемый во время обновления пакета, будет следующим:
- Отрабатывается раздел
%pre
в пакете RPM, который устанавливается. - Устанавливаются файлы, которые есть в пакете RPM
- Выполняется раздел
%post
установленного пакета RPM - Запускается раздел
%preun
старого пакета. - Удаляются все старые файлы, которые не были переписаны новой версией (удаляются только те файлы, которые ненужны в новой версии).
- Выполняется раздел
%postun
старого пакета.
Шаги 4 и 6 могут показаться слегка подозрительными, и вполне обоснованно: если вы обновляете пакет, запуск действий по удалению старой версии может полностью или частично аннулировать результаты шагов с 1 по 3. Действительно, операции по удалению старой версии, если они будут выполняться без проверки каких-либо условий, могут разрушить новую версию. Для того, чтобы предотвратить непреднамеренное затирание, в пакете RPM в каждый раздел передается один аргумент - флаг. Значение флага указывает, какие операции следует выполнять:
- Если первый аргумент в разделе
%pre
равен 1, то действие, выполняемое пакетом RPM, является первоначальной установкой. Если первый аргумент в разделе%pre
равен 2, то действие является обновлением. - Аналогичным образом аргументы в разделе
%post
равны 1 или 2 в случае новой установки или обновления, соответственно (разделы%pre
и%post
не выполняются при деинсталляции). - Если первый аргумент в разделах
%preun
и%postun
равен 1, то действие является обновлением. - Если первый аргумент в разделах
%preun
и%postun
равен 0, то действие является деинсталляцией.
Вставляем в каждый раздел логические операции, проверяющие значения аргументов, и выполняем
правильный код. По умолчанию, каждый раздел интерпретируется как скрипт оболочки Борна (как
правило, /bin/sh), если вы не указали имя другого интерпретатора скриптов, такого как Perl.
Ниже приведен пример раздела %pre
, подготовленного для интерпретатора Bourne:
%pre if [ "$1" = "1" ]; then # Выполняются задачи для подготовки первоначальной установки elif [ "$1" = "2" ]; then # Выполняют операции, которые требуются перед началом обновления пакета fi
Тот же самый раздел, но переписанный для Perl. Чтобы использовать другой интерпретатор скриптов, укажите параметр -p и задайте полный путь к интерпретатору.
%pre -p /usr/bin/perl if ( $ARGV[0] == 1 ) { print "Preparing for initial install...\n" } elsif ( $ARGV[0] == 2 ) { print "Preparing to upgrade software...\n" }
Если вы укажете интепретатор, которого нет на целевой машине, то утилита RPM сгенерирует ошибку, что будет выглядеть следующим образом:
$ sudo rpm -i RPMS/i386/wget-1.12-1.i386.rpm error: Failed dependencies: /usr/bin/perl is needed by wget-1.12-1.i386
Если администратор целевой системы увидит такое сообщение, он должен установить пакет, от которого зависит наш пакет RPM, и должен повторить установку.
Будьте аккуратны с триггерами
Обычно с помощью RPM устанавливается один пакет, который вряд ли зависит от других пакетов. Как правило в пакетах RPM имеется все, что нужно, а если что и используется совместно, то оно изолировано иным образом. Тем не менее, существуют пакеты, которые оказывают влияние на другие пакеты.
Например, некоторые текстовые редакторы являются расширяемыми: скажем, добавляем вспомогательный пакет для Ruby и редактор может подсвечивать синтаксис этого языка программирования. Если сначала установлен редактор, а затем вспомогательные пакеты, то новая функция будет добавлена в редактор, как вы и ожидали. Но что, если, скажем, вспомогательные пакеты будут установлены не первыми, поскольку они предназначены сразу для нескольких редакторов, а затем будет установлен редактор? В идеале, новая функция также должна быть добавлена. Появляется понятие триггера RPM.
RPM может подключить триггер к другому пакету с тем, чтобы выполнить одну или несколько задач в случае, если этот другой пакет будет инсталлироваться или деинсталлироваться после того, как данные пакет уже установлен. Каждый триггер является просто скриптом точно таким, как мы записывали в разделах %pre
или %post
. Вы даже можете, если желаете, указать альтернативный интерпретатор.
- Скрипт
%triggerin
работает тогда, когда устанавливается указанный пакет - Скрипт
%triggerun
работает тогда, когда указанный пакет деинсталлируется. - Скрипт
%triggerpostun
работает после того, как указанный пакет деинсталлирован.
Например, если вы хотите запустить скрипт только если установлен пакет Ruby, причем уже после того, как ваш пакет уже размещен в системе, вы можете написать следующее:
%triggerin -p /usr/bin/perl -- ruby # Реакция на добавление пакета Ruby
Параметр -p
является необязательным. Вы должны набрать –-
(два дефиса), а затем указать имя пакета, который вы хотите отслеживать.
С учетом копирования, использования механизма выполнения дополнительных команд и использования триггеров, порядок выполнения всех действий при установке нового пакета N будет следующей (предыдущая версия пакета будет обозначаться n) :
- Исполняем скрипт
%pre
нового пакета N. - Копируем в систему новые файлы нового пакета N.
- Исполняем скрипт
%post
нового пакета N. - Исполняем все инсталляционные триггеры (те, которые в других пакетах помечены как
%triggerin
), которые компенсируют установку нового пакета N. - Исполняем все инсталляционные триггеры нового пакета N.
- Исполняем все деинсталляционные триггеры (
%triggerun
) предыдущей версии пакета n. - Исполняем все деинсталляционные триггеры (найденные в других пакетах), которые компенсируют деинсталляцию предыдущей версии пакета n.
- Исполняем все действия из раздела
%preun
предыдущей версии пакета n. - Удаляем все файлы, которые не были переписаны при установке нового пакета N.
- Исполняем все деинсталляционные триггеры (
%triggerpostun
), найденные в предыдущей версии пакета n.
Установка программного обеспечения может быть сложной, но механизм дополнительных команд и триггеры могут справиться с практически любым сценарием. Одно предостережение: не пытайтесь взаимодействовать с пользователем на любом шаге этого процесса. RPM предназначен для установки в пакетном режиме, т. е. когда пользователь не должен обязательно присутствовать. Если пакет RPM во время установки делает паузу с тем, чтобы задать вопрос, и никто не увидит этот вопрос, установка, несомненно, зависнет.
Переменные RPM
Файлы RPM могут становиться длинными и сложными. Точно также, как вы используете переменные для сокращения записи в приложениях, вы можете использовать переменные в качестве хранилища значений в файле спецификаций RPM.
Например, вы можете задать переменную в верхней части вашего файла спецификаций, а затем
можете ссылаться на нее везде, используя для этого конструкцию %{имя_переменной
} — даже в скрипте из раздела %pre
:
%define foo_dir /usr/lib/foo %install cp install.time.message $RPM_BUILD_ROOT/%{foo_dir} %files %{foo_dir}/install.time.message %post /bin/cat %{foo_dir}/install.time.message
Заключение
Если вы разрабатываете программное обеспечение для машин, работающих под UNIX ® и Linux, написание инсталлятора может быть утомительным делом. К счастью, вам не нужно изобретать технологию инсталляции с самого нуля. Для этого есть технология RPM, которая широко используется для распространения программного обеспечения. Это делает "последнюю милю" похожей на прогулку в парке.
Продолжение: часть 3: Разрешение зависимостей между пакетами
Другие статьи об управлении программным обеспечением в Linux в нашей Библиотеке.