OpenBSD Порты - Работа с портами [Порты - На главную]



Введение

Использование портов предназначено для опытных пользователей. Всем рекомендуется использовать предварительно скомпилированные бинарные пакеты. Если вы задаете вопросы по теме портов, то подразумевается, что вы не просто умеете работать с портами, но и как минимум прочли соответствующие man-страницы и этот FAQ.

Дерево портов представляет из себя набор Makefile'ов, по одному для каждой программы, которые управляют:

Помимо файла Makefile, каждый порт как минимум содержит следующее: Вся эта информация хранится в подкаталогах в /usr/ports. В иерархии подкаталогов стоит выделить три особенных: Все остальные образуют разные категории приложений, в подкаталогах которых находятся порты. Сложные порты могут быть организованы на более глубоком уровне, например, если они разделены на основную часть и набор расширений, или стабильную версию и версию снапшота. Каждый каталог портов должен содержать подкаталог pkg/ со списком PLIST и файлом с описанием DESCR. Также порт может содержать каталог patches/, где содержатся патчи для этого порта, и files/ для других дополнительных файлов.

Когда пользователь запускает make(1) в подкаталоге того или иного порта, система рекурсивно просматривает свое дерево зависимостей, проверяет, установлены ли требуемые зависимости, собирает и устанавливает любые недостающие зависимости, а затем продолжает сборку нужного порта. Весь процесс сборки происходит внутри так называемого рабочего каталога (working directory), который создает порт. Обычно это ${WRKOBJDIR}, для которой по умолчанию используется /usr/ports/pobj, но вы можете переопределить это (см. настройка системы портов).

Дерево портов связано с версиями OpenBSD. Не стоит ожидать, что порты из дерева портов -current будут работать в release или -stable. Если вы используете -current, вам нужны и -current base system и дерево портов -current. Поскольку в -stable не вносятся навязчивые (intrusive) изменения, дерево портов release и -stable являются совместимыми.

Еще одна распространенная ошибка - отсутствующая установка X11. Даже если порт, который вы пытаетесь собрать, не имеет прямой зависимости к X11, для его подпакета или его зависимостей могут потребоваться headers и библиотеки X11. Сборка портов в системах без X11 не поддерживается.

Более исчерпывающая информация по теме системы портов находится в man-страницах:

Загрузка дерева портов

После того, как вы определились с тем, какой flavor дерева портов вам нужен, вы можете загрузить его себе из разных мест. В таблице ниже дается объяснение по поводу того, где вы можете найти тот или иной flavor, и в каком формате. «✓» обозначает, что flavor доступнен, а «✗» наоборот - невозможность загрузить исходники, используя этот источник.
Источник Формат Flavor
release -stable snapshots -current
Зеркала .tar.gz
AnonCVS cvs checkout

Обратите внимание на файл ports.tar.gz, который можно найти на наших зеркалах.

$ cd /tmp
$ ftp https://cdn.openbsd.org/pub/OpenBSD/$(uname -r)/{ports.tar.gz,SHA256.sig}
$ signify -Cp /etc/signify/openbsd-$(uname -r | cut -c 1,3)-base.pub -x SHA256.sig ports.tar.gz
Его надо распаковать в каталог /usr, что приведет к созданию /usr/ports и множества других подкаталогов внутри него.
# cd /usr
# tar xzf /tmp/ports.tar.gz
Снапшоты, доступные на наших зеркалах, генерируются ежедневно из дерева портов -current. Вы можете найти их в каталоге /pub/OpenBSD/snapshots/. Если вы решили установить снапшот того или иного дерева портов, вы должны использовать и соответствующий снапшот OpenBSD. Не забвайте синхронизировать установленное дерево портов с используемой OpenBSD!

Для получения дополнительной информации о загрузке дерева портов через CVS прочитайте страницу, посвященную AnonCVS. Там можно найти список доступных серверов и ряд полезных примеров.

Настройка системы портов

В этом разделе рассказывается о некоторых дополнительных глобальных настройках, полезных при сборке портов. Вы можете пропустить его, но тогда вам потребуется выполнить многие команды make(1) в последующих примерах от root.

Поскольку у проекта OpenBSD нет ресурсов для полного review всего исходного кода в дереве портов, вы можете предпринять нескоторые меры предосторожности, при помощи соответствующих настроек. Система портов, которую иногда называют «инфраструктурой портов», позволяет почти полностью собирать порты от имени обычного пользователя, и лишь некоторые шаги, которые требуют привилегий суперпользователя, от имени root (например, команда make install). Подробнее о том, как настроить разделение привилегий, рассказывается в man-странице bsd.port.mk(5).

Можно использовать read-only дерево портов при помощи разделения от каталогов, в которые производится запись во время сборки порта:

К примеру, вы можете добавить следующую строчку в файл /etc/mk.conf:
WRKOBJDIR=/usr/obj/ports
DISTDIR=/usr/distfiles
PACKAGE_REPOSITORY=/usr/packages
При желании вы также можете изменить владельца (ownership) этих каталогов на свое локальное имя пользователя и группу, чтобы система портов могла создавать базовые рабочие каталоги от имени обычного пользователя. Опять же, порты могут быть собраны от имени обычного пользователя, но установленны должны быть только пользователем root или при помощи doas(1).

Поиск в дереве портов

Как только вы скачали себе дерево портов и установили пакет portslist, можно начинать поиск доступного ПО. Для этого используйте команду make search key="searchkey" как показано в примере ниже:
$ cd /usr/ports
$ doas pkg_add portslist
$ make search key=rsnapshot
Port:   rsnapshot-1.4.2
Path:   net/rsnapshot
Info:   remote filesystem snapshot utility
Maint:  Antoine Jacoutot <ajacoutot@openbsd.org>
Index:  net sysutils
L-deps:
B-deps: devel/autoconf/2.69 devel/automake/1.15 devel/metaauto net/rsync
R-deps: devel/p5-Lchown net/rsync
Archs:  any
Результат поиска содержит не только название порта, но и предоставляет некоторую дополнительную информацию: PATH к порту, короткое описание, имя и почтовый адрес мейнтейнера, ключевые слова, связанные с портом, library/build/runtime зависимости и список архитектур, на которых порт поддерживается и работает.

Описанный способ очень прост. Тут просто запускается awk(1), который парсит index файл порта. Порт под названием «sqlports» напротив позволяет осуществлять очень детальный поиск при помощи поиска в базе данных. Это база данных SQLite, но практически любой формат базы данных может быть создан при помощи инфраструктуры портов. Порт sqlports включает в себя скрипт для создания базы данных, который можно использовать для создания баз данных различных форматах.

Просто установите пакет sqlports, чтобы попробовать. Пример сеанса может выглядеть так:

$ sqlite3 /usr/local/share/sqlports
sqlite> SELECT FULLPKGNAME,COMMENT FROM Ports WHERE COMMENT LIKE '%statistics%';
pg_statsinfo-3.3.0p0|monitor PostgreSQL activity & statistics
kactivities-stats-5.51.0|statistics for the KDE Activity concept
p5-Devel-Cover-Report-Clover-0.35|backend for Clover reporting of coverage statistics
mailgraph-1.14p1|RRDtool frontend for Postfix statistics
R-3.5.1p1|powerful math/statistics/graphics language
p5-Math-VecStat-0.08p0|provides basic statistics on numerical vectors
py-probstat-0.912p8|probability and statistics utilities for Python
py-statistics-1.0.3.5|port of Python 3.4 statistics module to Python 2
darkstat-3.0.719p1|network statistics gatherer with graphs
pfstat-2.5p2|packet filter statistics visualization
rtg-0.7.4p12|SNMP statistics monitoring system
slurm-0.4.3|network traffic monitor and statistics
tcpstat-1.5p0|report network interface statistics
libstatgrab-0.91p3|system statistics gathering library
p5-Unix-Statgrab-0.109p0|interface to libstatgrab system statistics library
diffstat-1.62|accumulates and displays statistics from a diff file
fragistics-1.7.0p2|Quake 3 statistics program
drupal7-google_analytics-1.2p2|add the Google Analytics web statistics to your site
dstat-0.5p0|dwm status bar statistics
kdf-4.14.3p4|KDE storage device statistics
libsysstat-0.4.1|library used to query system info and statistics
qdirstat-1.4p1|Qt-based directory statistics
sqlite>
Выше описан все же достаточно простой поиск. При помощи SQL можно искать практически все, что угодно, включая зависимости, флаги настройки, shared libraries и т.д.

Пример простой установки

Для ясности рассмотрим простой пример: rsnapshot. Это приложение имеет несколько build зависимостей: devel/autoconf/2.69, devel/automake/1.15, devel/metaauto и net/rsync. Выполнение следующей команды подразумевает, что вы настроили PORTS_PRIVSEP, как описано в man-странице bsd.port.mk.
$ cd /usr/ports/net/rsnapshot
$ make install
===>  Checking files for rsnapshot-1.4.2
>> Fetch https://github.com/rsnapshot/rsnapshot/archive/1.4.2/rsnapshot-1.4.2.tar.gz
100% |**************************************************|   365 KB    00:02
>> (SHA256) rsnapshot-1.4.2.tar.gz: OK
===> rsnapshot-1.4.2 depends on: metaauto-* - not found
===>  Verifying install for metaauto-* in devel/metaauto
===>  Checking files for metaauto-1.0p1
[...]
===>  Installing metaauto-1.0p1 from /usr/ports/packages/amd64/all/
metaauto-1.0p1: ok
===> Returning to build of rsnapshot-1.4.2
===> rsnapshot-1.4.2 depends on: metaauto-* -> metaauto-1.0p1
===> rsnapshot-1.4.2 depends on: autoconf-2.69 - not found
[...]
===> Returning to build of rsnapshot-1.4.2
===>  Extracting for rsnapshot-1.4.2
===>  Patching for rsnapshot-1.4.2
[...]
===>  Compiler link: clang -> /usr/bin/clang
===>  Compiler link: clang++ -> /usr/bin/clang++
===>  Compiler link: cc -> /usr/bin/cc
===>  Compiler link: c++ -> /usr/bin/c++
===>  Generating configure for rsnapshot-1.4.2
===>  Configuring for rsnapshot-1.4.2
[...]
===>  Building for rsnapshot-1.4.2
[...]
===>  Faking installation for rsnapshot-1.4.2
[...]
===>  Building package for rsnapshot-1.4.2
[...]
Link to /usr/ports/packages/amd64/all/rsnapshot-1.4.2.tgz
Link to /usr/ports/packages/amd64/ftp/rsnapshot-1.4.2.tgz
Link to /usr/ports/packages/amd64/cdrom/rsnapshot-1.4.2.tgz
===> rsnapshot-1.4.2 depends on: p5-Lchown-* - not found
[...]
===>  Installing rsnapshot-1.4.2 from /usr/ports/packages/amd64/all/
rsnapshot-1.4.2: ok

Как вы видете, много делается автоматически. Система портов загружает, распаковывает и накладывает патчи на исходники, настраивает и собирает (компилирует) их, устанавливает файлы в fake каталог, создает пакет (или даже список пакетов) и устанавливает этот пакет в вашу систему (обычно в /usr/local/). И все это проделывается рекурсивно для всех зависимостей порта. Обратите внимание на строки "===> Verifying install for ..." и "===> Returning to build of ..." в приведенном выше выводе, указывающие на обход дерева зависимостей.

Если вы хотите установить какую-то программу, а она уже установленна в вашей системе, но установленна её старая версия, используйте make update вместо make install. Это запустит pkg_add(1) с флагом -r.

Большие программы потребуют много системных ресурсов для сборки. Если вы получаете ошибки типа «out of memory» при попытке сборки такого порта, это обычно присходит по одной из двух причин:

Очистка после сборки

Скорее всего вы захотите почистить (не путать с "удалить") рабочий каталог порта после того, как соберете пакет и установите его.
$ make clean
===>  Cleaning for rsnapshot-1.4.2
По умолчанию зависимости workdir автоматически очищаются. Вы можете удалить установленные пакеты, которые были необходимы только для сборки порта.
# pkg_delete -a
p5-Module-Build-0.4224: ok
autoconf-2.69p2:automake-1.15.1: ok
autoconf-2.69p2: ok
metaauto-1.0p1: ok
Read shared items: ok
Если вы хотите удалить исходники порта (source distribution set(s) of the port), сделайте следующее:
$ make clean=dist
===>  Cleaning for rsnapshot-1.4.2
===>  Dist cleaning for rsnapshot-1.4.2
Если вы компилировали несколько версий одного и того же порта, вы можете очистить рабочие каталоги всех этих версий одновременно:
$ make clean=flavors
Вы также можете очищать все после каждой сборки, изменив BULK с auto на Yes.
$ make package BULK=Yes

Удаление пакета, собранного из порта

Удалить порт очень просто:
$ make uninstall
===> Deinstalling for rsnapshot-1.4.2
rsnapshot-1.4.2: ok
Read shared items: ok
Это запустит pkg_delete(1), который удалит соответствующий пакет из системы. Если вы хотите избавиться от только что собранных пакетов, это можно сделать следующим образом:
$ make clean=packages
===>  Cleaning for rsnapshot-1.4.2
rm -f /usr/ports/packages/amd64/all/rsnapshot-1.4.2.tgz

Использование Flavors и Subpackages

Мы настоятельно советуем прочитать ports(7), которая представляет из себя хороший обзор и введение в эту тему. Существует два различных механизма работы с пакетами в соответствии с их потребностями.

Первый механизм называется flavors. Flavor обычно указывает на определенный набор параметров компиляции. Например, некоторые приложения имеют flavor «no_x11», который предназначен для использования в системах без X. Некоторые оболочки имеют «статический» flavor, который создает статически связанную версию. Существуют порты, которые имеют разные flavors для их сборки с использованием различных графических инструментов. Другие примеры включают в себя поддержку различных форматов баз данных, различных параметры сети (SSL, IPv6, ...), различных размеров бумаги и т.д.

Подводим итог: Скорее всего, вы будете использовать flavors, если пакет не предоставляет (не поддерживает) flavor, который вам нужен. В этом случае вы можете указать желаемый flavor и собрать порт самостоятельно.

Большинство flavors портов имеют свой собственный рабочий каталог во время компиляции, и каждый flavor собирается в пакете с соответствующим именем, чтобы избежать путаницы. Чтобы увидеть различные flavor того или иного порта, посмотрите в его подкаталог и выполнить команду:

$ make show=FLAVORS
Вы также можете посмотреть файлы DESCR порта, где более подробно объясняются доступные flavors.

Второй механизм называется subpackages. Мэйнтейнер может решить создать подпакеты (subpackages) для разных частей одной программы, если они могут быть логически разделены. Вы будете часто видеть subpackages для клиентской части и серверной части программы. Иногда обширная документация упакована в отдельный subpackage, поскольку она занимает много места на диске. Другим примером могут быть дополнительный функционал программы, который тянет кучу зависимостей, и который часто упаковываются отдельно. Мэйнтейнер также решит, какой subpackage является основным, и будет установлен по умолчанию. Другими примерами являются обширные тестовые наборы, которые поставляются с программами, отдельные модули с поддержкой всего возможного и т.д.

Подводим итог: Некоторые порты могут быть разделены на несколько частей (или пакетов). make install установит только главную из них (main subpackage).

Список packages, на которые разделен порт, можно увидеть при помощи команды:

$ make show=PKGNAMES
make install установит только главный subpackage. Для того, чтобы установить их всех, используй команду:
$ make install-all
Список subpackages, доступных для порта, можно увидеть при помощи команды:
$ make show=MULTI_PACKAGES
Можно выбрать какие подпакеты (subpackage(s)) установить из дерева портов. После некоторых тестов эта процедура просто вызовет pkg_add(1) для установки нужного subpackage(s).
# env SUBPACKAGE="-server" make install
subpackages механизм обрабатывает только packages. Он не изменяет никакие параметры конфигурации перед сборкой порта. Вы должны использовать flavors для этой цели.

Использование dpb для сборки Multiple портов

Если вам нужно создать более одного порта одновременно, вы можете использовать для этого /usr/ports/infrastructure/bin/dpb. dpb(1) ожидает список портов для сборки и автоматически собирает их все параллельно в оптимальном порядке. Он также может использовать несколько машин для сборки, а также создает подробные build-logs, которые можно будет найти в /usr/ports/logs, и которые можно будет использовать для troubleshooting.
# /usr/ports/infrastructure/bin/dpb -P ~/localports
Эта команда запустит dpb, который прочтет список pkgpaths из ~/localports и соберет все перечисленные там пакеты. Он также может установить пакеты после их сборки. Файл ~/localports выглядит следующим образом:
net/rsync
www/mozilla-firefox
editors/vim
Если вы не передадите список портов для сборки в командной строке или через -P или -I, dpb(1) соберет все порты в дереве портов. При запуске от пользователя root, dpb автоматически отбрасывает привилегии, присвоенные пользователям для загрузки файлов с исходниками и сборки портов. Это рекомендуемый способ его использования, но он также может запускаться от имени обычного пользователя. Кроме того, утилита proot(1) может использоваться для дальнейшей изоляции build операций.

Обновления безопасности (-stable)

Когда в портах (third party software) обнаруживаются серьезные ошибки или проблемы безопасности, они исправляются в -stable branch дерева портов. В отличие от базовой системы, дерево портов -stable обновляется только из-за добавления в нее security backports для последней версии.

Это означает, что все, что вам нужно сделать, это убедиться, что вы проверили правильный branch дерева портов и собрали необходимые программы из него. Вы можете поддерживать свое дерево в актуальном состоянии (up to date) при помощи CVS и подписаться на почтовую рассылку ports-changes, чтобы получать уведомления о безопасности, связанные портами.

Подписи пакетов

Цифровые подписи являются хорошим способом быть уверенным в целостности загружаемых из сети пакетов. Они позволяют проверить не были ли пакеты кем-то умышленно измененны или просто повреждены при копировании. OpenBSD предоставляет официальные подписанные пакеты при помощи signify(1). Не требуется никаких дополнительных шагов со стороны пользователя, чтобы быть уверенным, что пакеты не были скомпрометированы.

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

# signify -Gns /etc/signify/my-pkg.sec -p /etc/signify/my-pkg.pub
Замечание по поводу имен: ключи, используемые для подписи пакетов, должны заканчиваться на pkg.

Существующие пакеты могуть быть подписаны при помощи pkg_sign(1) после их сборки.

# cd /usr/ports/packages/$(uname -p)
# pkg_sign -s signify2 -s /etc/signify/my-pkg.sec -o signed -S all
В случае установки такого пакета на другой машине, public key my-pkg.pub должен быть скопирован туда в каталог /etc/signify.

Сообщить об ошибке

Если у вас возникли какие-то проблемы с портом, отправьте email мэйнрейнеру (или как их еще называют в рунете - сопровождающему) порта. Узнать о том, кто поддерживает порт, можно вот так:
$ cd /usr/ports/archivers/unzip
$ make show=MAINTAINER
Если мэйнтейнер не указан, или же если по той или иной причине с ним не получается связаться, отправьте письмо в рассылку ports@openbsd.org.

Так или иначе, не забудьте предоставить следующую информацию:

Для портов, которые не собираются, почти всегда требуется полная стенограмма процесса сборки. Для этого вы можете использовать скрипт portslogger, находящийся в /usr/ports/infrastructure/bin. Пример может выглядеть так:
$ mkdir ~/portlog
$ cd /usr/ports/archivers/unzip
$ make 2>&1 | /usr/ports/infrastructure/bin/portslogger ~/portlog
После этого, в каталоге ~/portlog должен быть файл журнала сборки, который вы можете отправить мэйнтейнеру порта. Также убедитесь, что вы не используете никаких своих специальных параметров во время сборки, указанных например в /etc/mk.conf.

В качестве альтернативы вы можете сделать следующее:

Отладка пакетов, отладчики и backtraces

Если программа дает сбой, трассировка часто помогает определить причину проблемы. Обычно это делается при помощи GDB; старая версия этого отладчика входит в базовый комплект ОС, но, увы, часто не работает с текущими компиляторами. Для отладки пакетов установите более новую версию из портов, которые содержат бинарник egdb:
# pkg_add gdb
Для некоторых архитектур есть debug-пакеты (например, если порт называется neomutt-20201127, debug-пакет будет называться debug-neomutt-20201127). Эти пакеты содержат файлы с необходимой для отладки информацией (debug symbols); GDB знает, как загружать эти файлы автоматически. Debug-пакет должен соответствовать основному пакету: если вы используете snapshots, может потребоваться обновить пакет, чтобы быть увереным, что оба пакета собирались вместе (относятся к той же сборке). Устанавливается debug пакет, как и обычно, при помощи pkg_add:

# pkg_add debug-neomutt
Если debug-пакет недоступен, вы сможете увидеть лишь имена функций (но не более) из дампа ядра; иногда этого достаточно, чтобы разобраться в проблеме.

Порт может быть собран с отладочной информацией (debug symbols) на специальной ad-hoc основе (полезно на архитектурах, для которых debug-пакеты обычно не собираются) путем сборки порта при помоши make DEBUG=-g. Сначала вам нужно будет очистить существующую сборку и пакеты (а иногда даже могут возникать проблемы при сборке, если вы сначала не удалите/очистите все оставшееся с прошлой сборки). Если интересующий пакет является библиотекой или зависит от других портов, вам, возможно, придется удалить всю цепочку, чтобы сделать это. Также может быть полезно отключить оптимизацию (добавить -O0 в DEBUG).

$ cd /usr/ports/math/moo
$ make clean; make DEBUG="-g" repackage; make reinstall
Если у вас есть файл дампа ядра, скормите его GDB и вы получите backtrace:
$ egdb neomutt neomutt.core
GNU gdb (GDB) 7.12.1
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-unknown-openbsd6.8".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /usr/local/bin/neomutt...Reading symbols from /usr/local/bin/.debug/neomutt.dbg...done.
done.
[New process 577437]
Core was generated by `neomutt'.
Program terminated with signal SIGABRT, Aborted.
#0  _thread_sys_poll () at /tmp/-:3
3       /tmp/-: No such file or directory.
(gdb) bt
#0  _thread_sys_poll () at /tmp/-:3
<...>
#9  0x00000b3f1d5ec847 in main (argc=<optimized out>, argv=0x7f7ffffc8a08, envp=<optimized out>) at ../neomutt-20201127/main.c:1236
(gdb) q
Для программ setuid/setgid дампы ядра отключены по умолчанию, см. sysctl(8), чтобы узнать, как их разрешить. В качестве альтернативы вы можете загрузить программу при помощи отладчика, задать необходимые аргументы и сделать run:
$ egdb neomutt
<...>
(gdb) set args -d 2
(gdb) run
+<...>
Вы вернетесь в отладчик при получении определенных сигналов. (в большинстве случаев - в том месте, где произойдет сбой).

Чтобы включить debug-пакеты в обычной bulk сборке для порта, добавьте "DEBUG_PACKAGES=${BUILD_PACKAGES}" в Makefile. Это установит DEBUG во время сборки, а на packaging этапе автоматически отделит символы отладки от основных бинарников. Он также попытается сжать символы при помощи dwz; этот шаг срабатывает не всегда; в таком случае его можно переопределить при помощи "DWZ=:". Если вы регулярно занимаетесь разработкой портов, установка значения "INSTALL_DEBUG_PACKAGES=Yes" в файле /etc/mk.conf, что приведет к автоматической установке недавно собранных debug-пакетов.

Как помочь нам

Есть много способов помочь нам. Они перечисленны ниже, в порядке увеличения сложности.

Пожертвования железа может помочь в тестировании портов на поддерживаемых OpenBSD платформах.