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

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
Версія: 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 control and modem terminal emulation program is a Minicom
minicom-dbg - 2.7-r0.0 - Text-based control and modem terminal emulation program - Debugging files
minicom-dev - 2.7-r0.0 - Text-based control and modem terminal emulation program - Development
minicom-doc - 2.7-r0.0 - Text-based control and modem terminal emulation program - Documentation

Дивимося інформацію про пакет:

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

Package: minicom
Версія: 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 control and modem terminal emulation program Minicom is a text-based control and modem 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
Версія: 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
Версія: 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). Буду вдячний за пораду.

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


Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.