2010
Расширенные возможности Portage в Gentoo GNU/Linux
Пакетный менеджер «portage» в «Gentoo GNU/Linux» - система с огромными возможностями. Разработчики «portage» позаботились о том, чтобы пользователи были максимально свободны в выборе, как устанавливать любой пакет в системе с параметрами, отличными от тех, что заложены в официальном дереве «Portage». Я не буду рассказывать о использовании различных оверлеев - рано или поздно об их использовании узнает любой пользователь «Gentoo GNU/Linux». В данной заметке я хочу рассказать, как влиять на процесс сборки пакета, по желанию изменяя чуть ли не все содержимое файла «ebuild», не внося никаких изменений в дерево «Portage». Это будет полезно в первую очередь пользователям, уже поработавшим некоторое время с «Gentoo GNU/Linux», и желающим внести некоторые коррективы в устанавливаемые пакеты.
Итак, первым на очереди будет файл «/etc/portage/bashrc». Если его нет, то его можно легко создать. Этот файл выполняется всегда при установке любого пакета. В него можно поместить все, что угодно. Приведу простые примеры с решением конкретных задач.
Например, мне не нужны сертификаты, которые устанавливаются некоторыми пакетами по умолчанию, так как я использую собственные сертификаты. Я хочу отказаться от их установки. Это решается просто добавлением следующего содержания в файл «/etc/portage/bashrc».
/etc/portage/bashrcinstall_cert() {
einfo "No need SSL certs install"
}
Этим действием я заменяю функцию установки сертификатов, содержащуюся в официальном дереве в файле «eclass/ssl-cert.eclass». То есть, можно заменить любую функцию, содержащуюся в каталоге «eclass» официального дерева. Уже неплохо. Идем далее.
При установке из бинарных пакетов, собранных на другом компьютере, как я рассказывал в этой статье, совершенно неинтересно держать кэш этих пакетов, если они всегда доступны с компьютера, где производилась их компиляция. Поэтому я буду просто чистить кэш сразу после установки очередного пакета. Для этого в файле «/etc/make.conf» в переменную «FEATURES» я добавил параметр «-parallel-fetch», чтобы пакеты устанавливались последовательно. А в файл «/etc/portage/bashrc» добавил следующее.
/etc/portage/bashrcpost_pkg_postinst() {
rm -f "${PORTAGE_BINPKG_FILE}"
[ ! "$(ls -A "${PKGDIR}/${CATEGORY}")" ] && \
rm -rf "${PKGDIR}/${CATEGORY}"
rm -f "${PKGDIR}/Packages"
}
Теперь, после установки любого бинарного пакета, файл «.tbz2» будет удален из кэша, что позволит увеличить доступное место в системе.
В последнем примере применяется необычная функция - «post_pkg_postinst». Откуда она и что из себя представляет я расскажу ниже.
Итак, пакет на стадии установки проходит несколько фаз. При этом выполняются соответствующие функции. Ниже я приведу примерный список функций в порядке их выполнения:
pkg_setup
src_unpack
src_prepare
src_configure
src_compile
src_test
src_install
pkg_preinst
pkg_postinst
pkg_prerm
pkg_postrm
Более полный список и описание функций фаз установки можно получить из следующей справки.
# man 5 ebuild
Так вот, с некоторых пор пакетный менеджер «portage» умеет обрабатывать функции, состоящие из префиксов «pre_» и «post_» с именем функции фазы установки, то есть либо «до», либо «после» определенной фазы. Как я показал выше, например «post_pkg_postinst» будет выполняться после вызова функции «pkg_postinst». И вот тут-то и открываются поистине безграничные возможности по управлению пакетами с помощью «portage». Создавая свои собственные функции, можно влиять на процесс установки пакета самым разнообразным способом.
Как известно, «portage» выполняет не только файл «/etc/portage/bashrc», но и файлы в каталоге «/etc/portage/env», с именами пакетов, разложенные по каталогам с именами категорий пакетов. Например, как я уже рассказывал в этой заметке, для пакета «sys-kernel/gentoo-sources» будет выполняться файл «/etc/portage/env/sys-kernel/gentoo-sources».
Как все это можно использовать, я расскажу на примерах.
В последних версиях программы «portage» переменную из «/etc/make.conf» «PORTAGE_BINPKG_TAR_OPTS» почему-то сделали «только для чтения» в процессе установки пакета. Мне такое положение вещей совершенно не подходит, поэтому я просто изменяю исходные тексты пакета «portage» прямо в процессе установки, чтобы не бросать пакет в локальный оверлей и потом следить за выходом новых версий, что крайне неудобно. Для этого я просто создаю файл «/etc/portage/env/sys-apps/portage» следующего содержания.
/etc/portage/env/sys-apps/portagepre_src_compile() {
sed -e 's/PORTAGE_BINPKG_TAR_OPTS//' -i "${S}/bin/ebuild.sh"
}
Что же делает этот файл? Перед процессом компиляции, что видно по имени функции «pre_src_compile», происходит редактирование определенного файла, в котором убирается единственное упоминание о переменной «PORTAGE_BINPKG_TAR_OPTS». Пакет «portage» устанавливается, как обычно, а я получаю необходимый мне функционал.
Можно выполнять различные функции не только «до» и «после» некоторой фазы установки пакета, но и полностью заменять функции, описанные в файле «ebuild» пакета.
Например, при установке бинарного пакета «sys-devel/bison», мне не понравилась функция «pkg_postinst». Я создал файл «/etc/portage/env/sys-devel/bison» следующего содержания с функцией, которая мне подходит.
/etc/portage/env/sys-devel/bisonpkg_postinst() {
if [[ ! -e ${ROOT}/usr/bin/yacc ]] ; then
einfo "No need link"
fi
}
При установке пакета «sys-devel/bison» будет выполняться именно та функция, которая задана в файле «/etc/portage/env/sys-devel/bison». И так можно поступить с любой функцией, заданной в файле «ebuild».
С помощью всего этого функционала можно делать с «неудобными» пакетами все, что угодно. Например, накладывать необходимые патчи, не копируя пакет в локальный оверлей и не изменяя его. Покажу это на примере пакета «net-fs/samba». Ветка «3.5.X» имеет известную проблему с NTLM-аутентификацией. В сети нашелся патч для ее решения.
Я хочу сделать некоторую автоматизацию процесса наложения патчей. Для начала нужно решить, где будут храниться все дополнительные патчи. Для этих целей я создал каталог «/var/portage/patches».
# mkdir -p /var/portage/patches
Затем, внутри этого каталога можно создавать подкаталоги, состоящие из категории и имени пакета. В моем примере я создал каталог «/var/portage/patches/net-fs/samba».
# mkdir -p /var/portage/patches/net-fs/samba
Сюда я и скопирую найденный в сети патч. Кстати, вот он.
/var/portage/patches/net-fs/samba/samba-3.5.6-winbindd.patchdiff -Nuar samba-3.5.6.orig/source3/winbindd/winbindd_util.c samba-3.5.6/source3/winbindd/winbindd_util.c
--- samba-3.5.6.orig/source3/winbindd/winbindd_util.c 2010-10-07 19:41:16.000000000 +0300
+++ samba-3.5.6/source3/winbindd/winbindd_util.c 2010-11-15 01:03:51.000000000 +0200
@@ -76,6 +76,17 @@
if (sid == NULL)
return False;
+ /* This is to show the different results of this function between
+ samba versions 3.4.8 and 3.5.4, for bug 7481 */
+ static bool res_v34x, res_v35x;
+ res_v35x = (sid_check_is_domain(sid) || sid_check_is_builtin(sid));
+ if ( IS_DC ) {
+ res_v34x = sid_check_is_builtin(sid);
+ DEBUG(3,("is_internal_domain(): 3.5.x would return %d\n", res_v35x));
+ DEBUG(3,("is_internal_domain(): 3.4.x would return %d\n", res_v34x));
+ return (res_v34x);
+ }
+
return (sid_check_is_domain(sid) || sid_check_is_builtin(sid));
}
Осталось добавить в файл «/etc/portage/bashrc» следующие функции.
/etc/portage/bashrcpost_src_unpack() {
src_autopatcher
}
src_autopatcher() {
# Specify a directory for patches.
PATCH_DIR="/var/portage/patches"
PATCH_OPTS="-g0 -E --no-backup-if-mismatch"
local count=0
if [ -d "${PATCH_DIR}/${CATEGORY}/${PN}" ]; then
for PATCH in $(find "${PATCH_DIR}/${CATEGORY}/${PN}" -type f -name "*.patch"|sort)
do
einfo "Patching ${PATCH/*\//} ..."
while [[ ${count} -lt 5 ]]; do
if (patch -p${count} ${PATCH_OPTS} --dry-run -f < "${PATCH}") >/dev/null; then
patch -p${count} ${PATCH_OPTS} < "${PATCH}" >/dev/null
break
fi
(( count++ ))
done
if [[ ${count} -ge 5 ]] ; then
eerror "Failed Patch: ${PATCH/*\//} !"
die "Failed Patch: ${PATCH/*\//} !"
fi
done
fi
}
В функции «src_autopatcher» можно изменить место для хранения патчей. Оно задано в переменной «PATCH_DIR».
Попробуем обновить пакет «net-fs/samba».
# emerge samba -1
These are the packages that would be merged, in order:
Calculating dependencies .... done!
[ebuild R ] net-fs/samba-3.5.6 USE="acl -addns -ads aio -avahi caps client -cluster cups -debug -doc -examples -fam ldap -ldb netapi pam quota readline server smbclient -smbsharemodes -swat -syslog winbind" 0 kB
Total: 1 package (1 reinstall), Size of downloads: 0 kB
>>> Verifying ebuild manifests
>>> Emerging (1 of 1) net-fs/samba-3.5.6
* samba-3.5.6.tar.gz RMD160 SHA1 SHA256 size ... [ ok ]
* Package: net-fs/samba-3.5.6
* Repository: gentoo
* Maintainer: samba@gentoo.org
* USE: acl aio caps client cups elibc_glibc kernel_linux ldap netapi pam quota readline server smbclient userland_GNU winbind x86
>>> Unpacking source...
>>> Unpacking samba-3.5.6.tar.gz to /var/tmp/portage/net-fs/samba-3.5.6/work
>>> Source unpacked in /var/tmp/portage/net-fs/samba-3.5.6/work
* Patching samba-3.5.6-winbindd.patch ...
>>> Preparing source in /var/tmp/portage/net-fs/samba-3.5.6/work/samba-3.5.6/source3 ...
>>> Source prepared.
...
Как видно из вывода команды «emerge», дополнительный патч успешно наложился, что и требовалось.
Теперь у меня есть возможность накладывать патчи на любой пакет, не изменяя файл «ebuild». Можно попробовать сделать в файле «/etc/portage/bashrc» в функции «post_src_unpack» еще и проверку на версию пакета и в зависимости от этого накладывать соответствующий патч, но, я думаю, с этим вы уж и сами справитесь.
Пока что это все, что я хотел рассказать о дополнительных возможностях пакетного менеджера «portage». Надеюсь, этот материал будет полезен пользователям «Gentoo GNU/Linux», желающих узнать свою систему немного глубже.
Если сайт принес Вам пользу, то будьте благодарным - угостите пивом!