Pull to refresh

Собираем пакет для Solaris из сорцов

Reading time 7 min
Views 3.6K

Предисловие


Итак, у вас есть исходный код очень нужной вам программы и некоторые количество серверов под Solaris, на которые необходимо его развернуть. Более того, для успешной компиляции нужна куча модулей Perl.

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

Задача: Собрать исходный код клиента munin-node под SPARC Solaris и распространить по нескольким серверам.

Весь процесс будет описан на примере операционной системы Solaris 10 SPARC (update, мне кажется особой роли не играет, у меня был и U6, и U9) и свободного распространяего приложения munin (http://munin-monitoring.org/).

Подготовка


Для сборки пакета понадобится следующее:
  • Тестовый сервер с чистой ОСью.
  • Исходный код нужного приложения. У меня это будет munin-node 1.44 (на момент написания, уже была доступна версия 1.45), взятый отсюда: sourceforge.net/projects/munin/files/munin%20stable/1.4.4/munin-1.4.4.tar.gz/download
  • Доступ с тестового сервера в Интернет. Либо зеркало CPAN в вашей сети. У меня был второй вариант.
  • Список необходимых модулей Perl.

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

Сборка


Прежде всего необходимо установить модули Perl. Отчасти, именно для успешной сборки пакета, включающего в себя модули Perl, выше было указано, что необходим тестовый сервер с чистой осью. Дело в том, что все модули складируются в одном месте. Обычно это /usr/perl5/site_perl/<версия>/. Желательно, чтобы на момент установки модулей для вашей программы эта папка, как и /usr/local/perl5/<версия>/был пуст. Это облегчит процесс интеграции модулей в пакет.

Примечание: под <версия> – имеется ввиду рабочая версия Perl на сервере.

Самый простой способ – это установка с помощью CPAN.
# perl -MCPAN -e shell 

cpan> install Module::Name


Нужный модуль установится, подтянув за собой все зависимости. В сети достаточно информации по CPAN, потому я опущу момент с установкой модулей. Замечу лишь, что гораздо эффективней где-нибудь у себя развернуть зеркало CPAN, чем скачивать их отдельно. Тем более, что зеркало настраивается очень быстро, и общий объем на данный момент не превышает 2гб! Ручная установка же чревата крайне долгими и неприятными поисками зависимых модулей.

Когда все модули установлены, запускаем:
# find /usr/perl5/site_perl/5.8.8/ > /tmp/perl_files


К файлу /tmp/perl_files я вернусь позже.

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

Скомпилируем исходный код в нужную директорию (/pkg):
# make DESTDIR=/pkg
# make install-common-prime DESTDIR=/pkg
# make install-node DESTDIR=/pkg
# make install-plugins-prime DESTDIR=/pkg


Исходный код программы munin-node скомпилирован и установлен.
Немного поясню, для чего это сделано. При обычной компиляции, без указания DESTDIR, программа установится в те директории, которые прописаны в Makefile.config. В этом случае будет тяжело собрать воедино всю информацию о том, в какие директории какие файлы были установлены.
Теперь необходимо сделать список всех файлов нашей программы:
# find /pkg -print > /tmp/files


В данном случае команда find выведет список содержимого /pkg, затем вывод команды направляется в файл /tmp/files.
После этого необходимо отредактировать файл /tmp/files, убрав из всех путей директорию /pkg.
Теперь можно установить программу, как полагается, без указания DESTDIR.
Ранее я при помощи команды find сделал файл /tmp/perl_files. Содержимое этого файла необходимо поместить в /tmp/files, причем необходимо просмотреть файл и удалить повторяющиеся строки. Строки не должны повторяться!
Можно приступать к созданию пакета. В первую очередь создаем “содержание” пакета:
# cat /tmp/files | pkgproto > /tmp/Prototype


Эта команда создаст файл /tmp/Prototype примерно подобного вида:
d none /opt 0755 root root
d none /opt/munin 0755 root root
d none /opt/munin/man 0755 root root
d none /opt/munin/man/man3 0755 root root
f none /opt/munin/man/man3/Munin::Common::TLSClient.3 0555 root root
f none /opt/munin/man/man3/Munin::Common::TLS.3 0555 root root
f none /opt/munin/man/man3/Munin::Common::Config.3 0555 root root
f none /opt/munin/man/man3/Munin::Common::Timeout.3 0555 root root
f none /opt/munin/man/man3/Munin::Common::Defaults.3 0555 root root
f none /opt/munin/man/man3/Munin::Common::TLSServer.3 0555 root root
f none /opt/munin/man/man3/Munin::Node::Config.3 0555 root root
f none /opt/munin/man/man3/Munin::Node::Server.3 0555 root root
f none /opt/munin/man/man3/Munin::Node::Service.3 0555 root root
f none /opt/munin/man/man3/Munin::Node::OS.3 0555 root root
f none /opt/munin/man/man3/Munin::Node::Configure::HostEnumeration.3 0555 root root
f none /opt/munin/man/man3/Munin::Node::Configure::PluginList.3 0555 root root
f none /opt/munin/man/man3/Munin::Node::SNMPConfig.3 0555 root root
f none /opt/munin/man/man3/Munin::Node::Session.3 0555 root root
f none /opt/munin/man/man3/Munin::Node::Logger.3 0555 root root
f none /opt/munin/man/man3/Munin::Node::Configure::Debug.3 0555 root root
f none /opt/munin/man/man3/Munin::Node::Utils.3 0555 root root
f none /opt/munin/man/man3/Munin::Node::Configure::Plugin.3 0555 root root
f none /opt/munin/man/man3/Munin::Node::Configure::History.3 0555 root root
f none /opt/munin/man/man3/Munin::Plugin::Pgsql.3 0555 root root
f none /opt/munin/man/man3/Munin::Plugin::SNMP.3 0555 root root
f none /opt/munin/man/man3/Munin::Plugin.3 0555 root root
d none /opt/munin/man/man1 0755 root rootf none /opt/munin/man/man1/munin-node.1 0555 root root
f none /opt/munin/man/man1/munin-run.1 0555 root rootf none /opt/munin/man/man1/munindoc.1 0555 root root
f none /opt/munin/man/man1/munin-node-configure.1 0555 root rootd none /opt/munin/bin 0755 root root
f none /opt/munin/bin/munindoc 0555 root rootd none /opt/munin/sbin 0755 root rootf none /opt/munin/sbin/munin-run 0555 root root
f none /opt/munin/sbin/munin-node-configure 0555 root rootf none /opt/munin/sbin/munin-node 0555 root root


При желании, можно отредактировать уровень доступа к каждому файлу.
Теперь в начало этого файла нужно добавить указатель на файл pkginfo, в котором будет храниться информация о пакете. Также в начало можно добавить указатели на checkinstall, preinstall и postinstall, если они необходимы. Краткое описание:
  • checkinstall служит для проверки перед установкой. Запускается от имени nobody. Этим скриптом можно проверить зависимости или права на директории. Если условия неудовлетворительны, скрипт закончит работу утилиты pkgadd.
  • preinstall запускается от рута во время установки пакета. Этим скриптом, к примеру, можно создать пользователя для устанавливаемого пакета. Если прервать его выполнение, понадобится запустить pkgrm для удаление неудачной установки пакета.
  • postinstall запускается после того, как основная часть пакета установлена. Этим скриптом, к примеру, можно создать SMF сервис, или вывести какую-либо информацию для конечного пользователя. Вариантов масса.

Все эти файлы в нашем случае должны находиться в /tmp.
Pkginfo же, в свою очередь, выглядит так:
PKG="Munin-node"
NAME="Munin-node 1.44"
VERSION="1.44"
ARCH="sparc"
CLASSES="none"
CATEGORY="application"
VENDOR="GNU"
PSTAMP="Creator Name"
EMAIL="Creator.Name@mail"
BASEDIR="/"


Синтаксис для добавления pkginfo, checkinstall, preinstall и postinstall таков:
i pkginfo
i checkinstall
i preinstall
i postinstall


Итак. Конфигурационные файлы готовы. Можно приступать к созданию пакета:
# pkgmk -o -r / -d /tmp -f Prototype


Создаем пакет, перезаписывая все предыдущие попытки (-o), используя / в качестве корневой директории (-r), собрать пакет в /tmp, используя список из файла Prototype (-f).
Теперь в /tmp можно найти каталог с собранным пакетом, пока еще не запакованный. Директория будет носить имя, указанное строке PKG в файле pkginfo. Все скрипты, если они были добавлены в Prototype, находятся в директории install. Файлы программы – в директории root. В процессе отладки установки пакета можно смело редактировать содержимое файлов. Правда при этом нужно учитывать, что контрольная сумма и размер файлов может поменяться и эти изменения необходимо отразить в файле pkgmap, в противном случае установка провалится. Приятно, что при запуске pkgadd -d установщик укажет на несоответствие размера и суммы, причем обязательно напишет правильное значение.
Осталась сущая мелочь:
# cd /tmp
# tar -cf - Munin-node | gzip -9 -c > Munin-node.1.44.SPARC.pkg.tar.gz


Полученный архив можно переносить на другие серверы и запускать установку:
# gunzip -c Munin-node.1.44.SPARC.pkg.tar.gz | tar -xvf -
# pkgadd -d $PWD


Основная часть закончена.

Приложение


Ниже будет приведем пример скрипта postinstall, в котором производится первоначальная настройка клиента munin-node и создается сервис (демон?) для munin-node.

#!/bin/sh
#
/opt/munin/sbin/munin-node-configure --shell --families=contrib,auto | sh -x
svccfg -v validate /etc/opt/munin/munin-node.xml
svccfg -v import /etc/opt/munin/munin-node.xml
svcadm disable application/munin-node
echo "Before start munin-node service DO:"
echo "1. edit munin-node.conf"
echo "2. configure dns client"
echo "3. passwd munin user"


Файл munin-node.xml создавался отдельно.
Его содержимое:
<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
 <service_bundle type="manifest" name="export"> 
  <service name="application/munin-node" type="service" version="0"> 
    <create_default_instance enabled="true"/>  
    <single_instance/>  
    <dependency name="fs" grouping="require_all" restart_on="none" type="service">  
       <service_fmri value="svc:/system/filesystem/local"/>  
     </dependency>  
     <dependency name="network" grouping="require_all" restart_on="none" type="service">  
       <service_fmri value="svc:/milestone/network:default"/><code>
     </dependency>  
    <dependency name="name-services" grouping="require_all" restart_on="none" type="service">    
       <service_fmri value="svc:/milestone/name-services:default"/>  
    </dependency>  
    <code><exec_method name="start" type="method" exec="munin-node" timeout_seconds="60">  
      <method_context>  
         <method_credential user="root" group="root"/>    
         <method_environment>    
           <envvar name="PATH" value="/opt/munin/sbin:/usr/bin:/bin:/opt/csw/bin"/> 
         </method_environment>  
      </method_context>  
    </exec_method>  
    <exec_method name="stop" type="method" exec=":kill" timeout_seconds="60">  
      <method_context/> 
    </exec_method> 
</service>
<code></service_bundle>

Тут стоит лишь обратить внимание на путь до исполнительного файла munin-node.

Файл preinstall:
#!/bin/shgroupadd munin
useradd -d /var/munin -m -s /usr/bin/bash -g munin munin
cp /.profile /var/munin/
chown munin:munin /var/munin/.profile
Tags:
Hubs:
+29
Comments 5
Comments Comments 5

Articles