Менеджер пакетов opkg. Offline инсталляция пакетов в образ корневой файловой системы

в 4:33, , рубрики: angstrom, embedded linux, ipk, open source, OpenWrt, opkg, rootfs, yocto, Настройка Linux

pinguin_packet_dry

Широко известный в узких кругах легковесный менеджер пакетов opkg получил распространение в embedded Linux не случайно. Opkg используется во многих встраиваемых дистрибутивах и проектах, например, в OpenEmbedded, Yocto Project, OpenWRT, Ångström, Arago Project и некоторых других. Менеджер прост в эксплуатации, для полноценной работы вполне достаточно встроенной справки, а на просторах всемирной паутины множество статей о том, как устроен сам пакет ipk (opkg работает с таким форматом): как его создать, как установить и т.д и т.п. Однако подавляющее большинство информации посвящено тому, как работать на уже установленной на целевую платформу (target) системе в online-режиме, но специфика Embedded подразумевает, что образ корневой файловой системы, а также ядро готовятся заранее на некоторой инструментальной платформе (host), отличной от целевой. Иными словами, собираем ядро и файловую систему на рабочем компьютере, упаковываем в образ, образ тиражируем на железо. Эта статья посвящена тому, как с помощью менеджера opkg установить пакеты в подготавливаемый образ rootfs.

Путь граблей и велосипедов

Много лет назад в бытность инженера одного небольшого завода, когда я запустил Linux на первой платке собственного производства, с помощью opkg установил из удаленного репозитория все требуемые пакеты, настроил все приложения, начальник лаборатории сказал: "Отлично! Теперь сделай то же самое на всех устройствах в партии". "Да не вопрос!" – ответил я. Система же есть, она запущена, она работает. Копируем все файлы из корня на внешний носитель, затем упаковываем в образ и радуемся жизни! В то время я не понимал, что при работе операционная система выполняет ряд локальных настроек, создает временные файлы, файлы конфигурации, генерирует какие-то ключи, а при первом запуске выполняет еще и скрипты инициализации. Хотя перенос файлов с одной работающей системы на другую методом тупого копирования с носителя и давал результат, но эффективность данного метода очень скоро для меня стала сомнительной. Получить "чистую" систему таким образом невозможно: система помнит свою предыдущую жизнь в другом аппаратном теле, и время от времени ее душат фантомные боли.

Еще одна бредовая идея

На target смонтировать внешний накопитель с rootfs, выполнить chroot и ставить пакеты. Комментировать не буду.

Следующим шагом для меня стало понимание структуры самого покета *.ipk. По сути вещей, пакет ipk является архивом, распаковать который можно легко с помощью команды:

ar -x *.ipk

В результате получим:

 .
├── control.tar.gz
├── data.tar.gz
└── debian-binary 

В архиве data.tar.gz содержатся файлы, которые должны быть помещены в корневую директорию target'а.
В архиве control.tar.gz содержатся служебные файлы: файл с описанием и скрипты. Идея простая: так как ipk – это всего лишь архив со скриптами, то мы можем всегда руками распаковать его в директорию с файловой системой, а потом запустить (если есть в этом необходимость) скрипты. Вот только все зависимости пакета нам придется устанавливать также вручную.
А если зависимости имеют еще зависимости? Возникает идея, может быть написать скрипт для автоматизации процесса? Как это часто бывает в мире linux, если перед тобой возникла задача, то, скорее всего, такая задача возникла не перед тобой одним, и, скорее всего, ты в этом деле не первый.
Далеко ходить не пришлось, на самом деле в сам менеджер пакетов opkg заложен такой режим, когда пакеты устанавливаются в неактивную файловую систему rootfs. При этом, архитектура host-машины (где запускаются утилиты opkg) и target-машины могут быть отличными. Такой режим называется Offline mode. В таком режиме opkg становится мощнейшим инструментом кросс-разработки.

Собираем opkg для host

Для работы в режиме Offline opkg должен запускаться на host'е. С давних пор на моем рабочем компьютере обосновалась Ubuntu (сейчас стоит Ubuntu 14.04 LTS), на ней и будем строить наш инструментарий. Мне не удалось найти репозиторий с opkg для Ubuntu, потому собираем набор утилит из исходников.
Получить исходные коды можно с git репозитория Yocto Project:

    git clone git://git.yoctoproject.org/opkg.git
    cd opkg

Для тех кого пугает git

можно обойтись и без него. На момент написания статьи, актуальная версия утилиты – opkg-0.3.1. Качаем исходники с сайта и распаковываем:

tar xzf opkg-0.3.1.tar.gz
cd opkg-0.3.1/

На самом деле настройка и компиляция проекта выполняется достаточно стандартным способом, но есть некоторые нюансы, и потому все по порядку.
Запускаем:

./autogen.sh

На заметку: если запустить ./autogen.sh с параметром --clean, то удалятся все труды по конфигурации проекта.
После выполнения ./autogen.sh в директории с исходниками появляется скрипт configure, он выполнит настройку пакета, определит и задаст системозависимые переменные. В результате работы скрипта создается Makefile. Посмотреть все опции скрипта можно стандартным способом:

./configure --help

Собирать пакет будем под текущую платформу, потому опции настройки кросс-компиляции пропускаем. Озаботимся инсталляцией. По умолчанию, выполнив make install, скрипт раскидает все полезные файлы (бинарники, скрипты, документация) по корневой директории: /etc, /usr/local, а это нам совершенно ни к чему. Мы ведь не собираемся использовать opkg для настройки пакетов в текущей системе? Кроме того, установив менеджер в системные папки, для использования утилит потребуются права суперпользователя, на мой взгляд, это излишне при настройке образа embedded linux. Скрипт configure.sh позволяет задать префикс для директории установки пакета. Указав в качестве префикса любую рабочую директорию, мы сообщим инсталлятору куда ставить пакет. При необходимости можно отдельно задать префикс для архитектурозависимых (бинарники и библиотеки) и архитектуронезависимых (скрипты и документация) файлов.
С фантазией у меня всегда было слабовато, потому для инсталляции в домашнем каталоге создадим каталог opkg_offline.

mkdir ${HOME}/opkg_offline

Выполним конфигурацию:

./configure --prefix=${HOME}/opkg_offline

При необходимости доставляем требуемые зависимости. Так мне на Ubuntu 14.04 для успешной сборки понадобилось доставить libarchive-dev, libcurl4-gnutls-dev, libssl-dev, libgpgme11-dev.

А как это сделать?

sudo apt-get install libarchive-dev
sudo apt-get install libcurl4-gnutls-dev
sudo apt-get install libssl-dev
sudo apt-get install libgpgme11-dev

Компилируем и устанавливаем opkg:

make  
make install  

В результате в директории opkg_offline имеем:

opkg_offline
├── bin
│   ├── opkg
│   ├── opkg-check-config
│   └── opkg-key
├── lib
│   ├── libopkg.a
│   ├── libopkg.la
│   ├── libopkg.so -> libopkg.so.1.0.0
│   ├── libopkg.so.1 -> libopkg.so.1.0.0
│   ├── libopkg.so.1.0.0
│   └── pkgconfig
│       └── libopkg.pc
└── share
├── man
│   └── man1
│       ├── opkg.1
│       └── opkg-key.1
└── opkg
└── intercept
├── depmod
├── ldconfig
└── update-modules

Менеджер пакетов собран и установлен. Исполняемые файлы находятся в директории opkg_offline/bin. Для работы с ними можно в переменную PATH прописать путь, либо для каждой сессии терминала вызывать экспорт (export), либо делать как я делаю – перейти в каталог opkg_offline и запустить непосредственно ./bin/opkg.

Краткий курс анатомии

Коротко рассмотрим как работает менеджер пакетов в стандартном режиме. После выполнения команды opkg update, утилита читает файлы конфигураций, которые по умолчанию расположены в /etc/opkg и имеют расширение .conf. Из этих файлов система определяет тип архитектуры, например armv5hf-vfp или armv5tehf-vfp (поддерживаемых архитектур может быть несколько, для каждой можно задать приоритет), список репозиториев и некоторые настройки самой программы. Далее для каждого репозитория из списка скачивается архив типа *_Packages.gz. Архивы по умолчанию помещаются в директорию var/cache/opkg/. После распаковки содержимое помещается в var/lib/opkg/lists. В каждом архиве лежит текстовый файл со списком пакетов в репозитории. Для каждого пакета помимо названия указана версия, архитектура, размер, краткое описание, лицензия, а самое главное – зависимости. На основании этих файлов менеджер пакетов по запросу может выдать информацию о требуемом пакете, а при его установке определить все зависимости и разрешить их.
Команда opkg list выдаст все доступные для установки пакеты; команда opkg list-installed покажет только установленные пакеты, команда opkg info покажет информацию об указаном пакете, а если он установлен, то и время установки.
Для установки пакета следует выполнить opkg install packname. В результате требуемый пакет из репозитория будет скачен во временную директрию и распокован. Все файлы из архива data.tar.gz разойдутся по своим местам в rootfs, а на основании содержимого control.tar.gz в каталоге var/lib/opkg/info будут созданы служебные файлы: packname.control – полная информация о пакете, packname.list — список директорий, по которым разошлись файлы из data.tar.gz (по этому списку пройдется opkg при удалении пакета), и файлы скриптов, типа packname.postinst, packname.preinst, packname.prerm, packname.postrm, назначения которых понятны из названия. Информация об установленном пакете будет добавлена в файле var/lib/opkg/status в виде (пример для популярного minicom):

Package: minicom
Version: 2.6.2-r0.2
Depends: libtinfo5 (>= 5.9), libc6 (>= 2.17)
Status: install ok installed
Architecture: armv7ahf-vfp-neon
Installed-Time: 1454529423

Важно обратить внимание на Status. Если пакет был установлен по всем правилам: все файлы скопированы на свое место, все скрипты выполнены, то статус будет Status: install ok installed. При работе в режиме offline все файлы будут скопированы, но скрипты не выполнятся, такие пакеты будут помечены как Status: install ok unpacked.
На этот случай в opkg предусмотрен специальный механизм пост конфигурации пакетов. Запускается он командой opkg configure <packname>. Если указать имя определенного пакета, то будут выполнены скрипты из var/lib/opkg/info для этого пакета; если имя опустить, то менеджер произведет конфигурацию для всех пакетов, у которых статус Status: install ok unpacked. Таким образом, при установке пакетов на host в режиме offline, при первой загрузке операционной системы на target следует выполнить opkg configure. Доверить это можно либо специальному скрипту, либо, если используется systemd, специальному сервису.

Работа с целевой rootfs

Настало время попробовать систему в деле. Для примера установим эмулятор терминала последовательного порта minicom.
Для установки пакетов нам понадобится распакованный образ корневой файловой системы целевой платформы rootfs. Предположим, что в rootfs установлен менеджер opkg, a в директории etc/opkg существуют файлы конфигурации *.conf. Если же его там нет, или по какой-то причине мы не хотим использовать конфигурацию из rootfs, мы можем через параметр указать какой файл настроек использовать: -f etc/opkg/opkg.conf. Путь к целевой файловой системе передаем через параметр --offline-root /path/to/rootfs.
Обновляем списки пакетов:

bin/opkg update --offline-root /path/to/rootfs

Просматриваем список доступных пакетов, ищем minicom.

bin/opkg list --offline-root ~/board/rootfs/angstrom/rootfs-v2015.10 | grep minicom

minicom - 2.7-r0.0 - Text-based modem control and terminal emulation program  Minicom is a
minicom-dbg - 2.7-r0.0 - Text-based modem control and terminal emulation program - Debugging files
minicom-dev - 2.7-r0.0 - Text-based modem control and terminal emulation program - Development
minicom-doc - 2.7-r0.0 - Text-based modem control and terminal emulation program - Documentation

Смотрим информацию о пакете:

bin/opkg info minicom --offline-root ~/board/rootfs/angstrom/rootfs-v2015.10

    Package: minicom
    Version: 2.7-r0.0
    Depends: libtinfo5 (>= 5.9), libc6 (>= linaro-2.20)
    Status: unknown ok not-installed
    Section: console/network
    Architecture: armv7at2hf-vfp-neon
    Maintainer: Angstrom Developers <angstrom-distro-devel@linuxtogo.org>
    MD5Sum: e4d11b7277fbc1c7db6bbd97ac52ca2c
    Size: 79354
    Filename: minicom_2.7-r0.0_armv7at2hf-vfp-neon.ipk
    Description: Text-based modem control and terminal emulation program  Minicom is a text-based modem control and terminal emulation program for Unix-like operating systems

Устанавливаем пакет:

bin/opkg install minicom --offline-root ~/board/rootfs/angstrom/rootfs-v2015.10

В файле var/lib/opkg появилась запись:

    Package: minicom
    Version: 2.7-r0.0
    Depends: libtinfo5 (>= 5.9), libc6 (>= linaro-2.20)
    Status: install user unpacked
    Architecture: armv7at2hf-vfp-neon
    Installed-Time: 1454594718

После того, как с созданного образа была запущена система и отработала команда opkg configure, запись в файле изменилась:

    Package: minicom
    Version: 2.7-r0.0
    Depends: libtinfo5 (>= 5.9), libc6 (>= linaro-2.20)
    Status: install user installed
    Architecture: armv7at2hf-vfp-neon
    Installed-Time: 1454594718

Так как настраиваемая rootfs предназначена для встраиваемого компьютера, конечный размер образа имеет значение. Поэтому рекомендую, после того как все нужные пакеты были установлены, удалить скаченные списки и почистить кэш:

rm -rvf  ~/board/rootfs/angstrom/rootfs-v2015.10/var/cache/opkg/*  
rm -rvf  ~/board/rootfs/angstrom/rootfs-v2015.10/var/lib/opkg/lists/*

На заметку: опция --volatile-cache позволит очистить кэш автоматически при завершении работы.

Вместо заключения

Несмотря на работоспособность, у Offline mode есть некоторые недостатки. Дело в том, что команда opkg configure запускает на выполнение только *.postinst, но остается нерешенным вопрос с выполнением скриптов *.preinst. В силу того, что *.preinst встречается достаточно редко в пакетах, для меня является приемлемым в ручном режиме просмотреть скрипты, и при необходимости отработать их при первом запуске целевой системы (специальны service для systemd). Буду благодарен за совет.

Почитать по теме:

Автор: Shamrel

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js