Наши партнеры








Книги по Linux (с отзывами читателей)

Библиотека сайта rus-linux.net

На главную -> MyLDP -> Тематический каталог -> Установка новых программных пакетов

Упаковка программ с помощью 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 отработают только после того, как пакет будет уже удален из системы.

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

  1. Отрабатывается раздел %pre в пакете RPM, который устанавливается.
  2. Устанавливаются файлы, которые есть в пакете RPM
  3. Выполняется раздел %post установленного пакета RPM
  4. Запускается раздел %preun старого пакета.
  5. Удаляются все старые файлы, которые не были переписаны новой версией (удаляются только те файлы, которые ненужны в новой версии).
  6. Выполняется раздел %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) :

  1. Исполняем скрипт %pre нового пакета N.
  2. Копируем в систему новые файлы нового пакета N.
  3. Исполняем скрипт %post нового пакета N.
  4. Исполняем все инсталляционные триггеры (те, которые в других пакетах помечены как %triggerin), которые компенсируют установку нового пакета N.
  5. Исполняем все инсталляционные триггеры нового пакета N.
  6. Исполняем все деинсталляционные триггеры (%triggerun) предыдущей версии пакета n.
  7. Исполняем все деинсталляционные триггеры (найденные в других пакетах), которые компенсируют деинсталляцию предыдущей версии пакета n.
  8. Исполняем все действия из раздела %preun предыдущей версии пакета n.
  9. Удаляем все файлы, которые не были переписаны при установке нового пакета N.
  10. Исполняем все деинсталляционные триггеры (%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 в нашей Библиотеке.