Вве­де­ние

Суще­ствует целый арсе­нал устройств, на кото­рых сборка «Gentoo GNU/Linux» либо невоз­можна, либо затруд­ни­тельна из-за недо­статка аппа­рат­ных ресур­сов, либо попро­сту бес­смыс­ленна. Это может быть VPS, нет­бук или ста­рый ком­пью­тер. А может быть и пул одно­тип­ных сер­ве­ров с оди­на­ко­вой архи­тек­ту­рой и оди­на­ко­вым про­грамм­ным обес­пе­че­нием. В любом из этих слу­чаев пред­по­чти­тельна сборка системы на дру­гом, доста­точно мощ­ном, ком­пью­тере, высту­па­ю­щем в роли репо­зи­то­рия бинар­ных пакетов.

На таком ком­пью­тере дол­жен сто­ять любой дис­три­бу­тив на базе «GNU/Linux», той же архи­тек­туры, что тре­бу­ется конеч­ному устрой­ству, или вир­ту­аль­ная машина с необ­хо­ди­мой архи­тек­ту­рой.
Я не буду рас­ска­зы­вать о кросс-компиляции для архи­тек­туры, отлич­ной от той, кото­рая исполь­зу­ется на ком­пью­тере. Это немного дру­гая тема.

Допол­ни­тельно на этом ком­пью­тере потре­бу­ется настро­ен­ный http-сервер для воз­мож­но­сти загрузки бинар­ных паке­тов конеч­ному устрой­ству по сети. Можно любым дру­гим спо­со­бом мон­ти­ро­вать репо­зи­то­рий с бинар­ными паке­тами в фай­ло­вую систему на конеч­ном устрой­стве или про­сто пере­не­сти на любом носи­теле все бинар­ные пакеты на конеч­ное устрой­ство, что немного неудобно в плане даль­ней­шего обновления.

Допол­ни­тель­ным пре­иму­ще­ством уста­новки «Gentoo GNU/Linux» на конеч­ное устрой­ство из бинар­ных, пред­ва­ри­тельно собран­ных, паке­тов явля­ется избав­ле­ние от «мусора», кото­рый необ­хо­дим только для сборки из исход­ных тек­стов, но не тре­бу­ется для работы. Так же есть воз­мож­ность осво­бо­дить допол­ни­тель­ное место в системе, изба­вив­шись от исход­ных тек­стов ядра и дерева «Portage», зани­ма­ю­щих вме­сте чуть больше одного гигабайта.

Итак, на выходе мы имеем всю быст­роту работы и гиб­кость «Gentoo GNU/Linux» с воз­мож­но­стью не соби­рать пакеты на конеч­ном устрой­стве, а уста­нав­ли­вать пред­ва­ри­тельно собран­ные на более мощ­ном компьютере.

Для работы потре­бу­ются права суперпользователя.

Я рас­скажу как все это сде­лать на при­мере сборки «Gentoo GNU/Linux» для тесто­вой вир­ту­аль­ной машины, рабо­та­ю­щей на очень сла­бом, по совре­мен­ным мер­кам, ноут­буке с исполь­зо­ва­нием неболь­шого сер­вера под управ­ле­нием «Gentoo GNU/Linux», на кото­ром и будет про­ис­хо­дить весь про­цесс сборки необ­хо­ди­мых бинар­ных пакетов.

Под­го­товка chroot-окружения

Для начала, нужно опре­де­литься с местом, где будет нахо­диться наша система для сборки. Я для себя решил, что в «/srv/cfarm» ей самое место. Итак, создаем ката­лог «/srv/cfarm/test» и захо­дим в него.
# mkdir -p /srv/cfarm/test
# cd /srv/cfarm/test

Ска­чи­ваем «Stage3» с любого зер­кала «Gentoo GNU/Linux» под свою архи­тек­туру и рас­па­ко­вы­ваем. В моем слу­чае это будет i686-архитектура. Ска­чи­вать будем из «current-stage3», так как релиз совсем уста­рел. Для этого доста­точно зайти на любое удоб­ное зер­кало «Gentoo GNU/Linux» в дирек­то­рию «/releases/x86/current-stage3» и ска­чать послед­ний сни­мок.
# wget http://distfiles.gentoo.org/releases/x86/autobuilds/current-stage3-i686/stage3-i686-hardened-hardened-hardened-hardened-hardened-20171212T011501Z.tar.bz2
# tar -xjvpf ./stage3-i686-hardened-hardened-hardened-hardened-hardened-20171212T011501Z.tar.bz2

Если рас­па­ковка про­шла успешно, то можно уда­лить файл «Stage3» и содер­жи­мое «/srv/cfarm/test/dev».
# rm -f ./stage3-i686-hardened-hardened-hardened-hardened-hardened-20171212T011501Z.tar.bz2
# rm -rf  /srv/cfarm/test/dev/*

Нужно опре­де­лится, где будет хра­ниться дерево «Portage». Если ком­пью­тер, на кото­ром будет выпол­няться сборка, рабо­тает под управ­ле­ние «Gentoo GNU/Linux», то все про­сто - веро­ятно дерево «Portage» уже нахо­диться в «/usr/portage» или в дру­гом месте, опре­де­лен­ном пере­мен­ной «PORTDIR» в файле «/etc/make.conf». Иначе, нужно будет ска­чать послед­ний сни­мок дерева «Portage» и рас­па­ко­вать в отдель­ное место, напри­мер в «/srv/cfarm/portage». Так удобно посту­пить, если пла­ни­ру­ется созда­вать несколько chroot-окружений под раз­лич­ные конеч­ные устрой­ства. Дерево «Portage» будет для всех одно.
# wget http://de-mirror.org/distro/gentoo/releases/snapshots/current/portage-latest.tar.bz2
# tar -xjvpf portage-latest.tar.bz2 -C /srv/cfarm
# rm -f portage-latest.tar.bz2

Так же имеет смысл выне­сти из chroot-окружения загру­жен­ные архивы фай­лов исход­ных тек­стов в отдель­ную дирек­то­рию, напри­мер «/srv/cfarm/distfiles». Таким обра­зом можно исполь­зо­вать их в раз­лич­ных chroot-окружениях, не загру­жая каж­дый раз заново.
# mkdir -p /srv/cfarm/distfiles

Поза­бо­тимся зара­нее о буду­щих полу­ча­е­мых бинар­ных паке­тах. Их тоже лучше выне­сти отдельно, чтобы дать воз­мож­ность http-серверу уви­деть их все в одном месте. Бинар­ные пакеты будем скла­ды­вать в «/srv/cfarm/binhost».
# mkdir -p /srv/cfarm/binhost

Под­го­то­вим буду­щее chroot-окружение.
Ско­пи­руем файл «resolv.conf» из основ­ной системы.
# cp -f /etc/resolv.conf ./etc/resolv.conf

Нужно задать вре­мен­ную зону, ско­пи­ро­вав необ­хо­ди­мый файл зоны в «/etc/localtime». В моем слу­чае вре­мен­ная зона будет «Europe/Moscow».
# cp -f ./usr/share/zoneinfo/Europe/Moscow ./etc/localtime

Редак­ти­руем файл «/etc/make.conf».
# nano ./etc/make.conf

У меня полу­чился сле­ду­ю­щий файл «/etc/make.conf».
make.confCHOST="i686-pc-linux-gnu"
CFLAGS="-O2 -march=i686 -pipe -fomit-frame-pointer"
LDFLAGS="-Wl,-O1 -Wl,--sort-common -Wl,--hash-style=gnu -Wl,--as-needed"

ACCEPT_KEYWORDS="~x86"
ACCEPT_LICENSE="PUEL"

PORTAGE_NICENESS="5"
MAKEOPTS="-j3"
PORTAGE_IONICE_COMMAND="ionice -c 3 -p \${PID}"

FEATURES="buildpkg ccache userpriv usersandbox usersync"
EMERGE_DEFAULT_OPTS="--alphabetical --verbose --nospinner --with-bdeps=y --keep-going"

INSTALL_MASK="/usr/share/gtk-doc"

PORTAGE_BINPKG_TAR_OPTS="-X /etc/portage/package.exclude"

PORTDIR="/var/portage/portage"
PKGDIR="/var/portage/packages"
DISTDIR="/var/portage/distfiles"

GENTOO_MIRRORS="http://de-mirror.org/distro/gentoo/
ftp://mirror.yandex.ru/gentoo-distfiles/"

COLLISION_IGNORE="/usr/share/man/man1/maildirmake.1.bz2
                  /usr/share/man/man8/deliverquota.8.bz2
                  /usr/bin/maildirmake"

CCACHE_SIZE="1G"
CCACHE_DIR="/var/cache/ccache"

LINGUAS="ru"
LANGUAGE="ru"

VIDEO_CARDS="none"

LD_AS_NEEDED="1"

I_KNOW_WHAT_I_AM_DOING="yes"

USE="bash-completion bzip2
gd
charconv
network-cron
urandom
sse2
threads
vchroot vhosts
-berkdb
-fortran
-gdbm -gpm
-ipv6
-python
-tcpd
-sqlite"

Я сразу же изме­нил дирек­то­рии хра­не­ния дерева «Portage», архи­вов исход­ных кодов и место для хра­не­ния бинар­ных паке­тов из «/usr/portage» в «/var/portage». Это видно по пере­мен­ным «PORTDIR», «PKGDIR» и «DISTDIR». Поэтому надо создать соот­вет­ству­ю­щие дирек­то­рии.
# mkdir -p ./var/portage/{portage,distfiles,packages}

Сле­дует обра­тить вни­ма­ние на пере­мен­ную «ACCEPT_KEYWORDS». Не всем подой­дет «сидеть под тиль­дой», то есть исполь­зо­вать тесто­вые вер­сии паке­тов. Мне это под­хо­дит, так как боль­шин­ство клю­че­вых паке­тов на сер­ве­рах необ­хо­димо дер­жать все­гда све­жими.
Так же нужно посмот­реть на пере­мен­ную «CFLAGS» и заме­нить зна­че­ние в опции «-march=…» на тип вашего про­цес­сора на конеч­ном устрой­стве. Подроб­нее о настрой­ках пере­мен­ных «CHOST» и «CFLAGS» под раз­лич­ные типы про­цес­со­ров можно посмот­реть по ссылке «http://en.gentoo-wiki.com/wiki/Safe_Cflags».

Пере­мен­ная «LDFLAGS» отве­чает за опции лин­ковки.
Пере­мен­ная «FEATURES» должна содер­жать опцию «buildpkg», чтобы после уста­новки при­ло­же­ний в chroot-окружении в дирек­то­рии «/var/portage/packages» созда­ва­лись бинар­ные пакеты.
Пере­мен­ная «PORTAGE_BINPKG_TAR_OPTS» ука­зы­вает опции упа­ковки бинар­ных паке­тов. А в файле «/etc/portage/package.exclude» будут хра­ниться маски исклю­че­ний при упа­ковке. Созда­дим этот файл.
# mkdir ./etc/portage
# nano ./etc/portage/package.exclude

package.exclude*/LICENSE*
*/README*
*.a
*.la
*.prl
*/.keep*
*/cmake*
*.cmake
*/examples*
*/etc/xinetd.d*
*/include*
*/mkspecs*
*/usr/bin/*-config
*/usr/bin/*-config-2
*/usr/lib/cmake*
*/usr/lib/pkgconfig*
*/usr/share/aclocal*
*/usr/share/apps/cmake*
*/usr/share/common-lisp*
*/usr/share/doc/*/html*
*/usr/share/getopt*
*/usr/share/gtk-doc*
*/usr/share/locale/a*
*/usr/share/locale/b*
*/usr/share/locale/c*
*/usr/share/locale/d*
*/usr/share/locale/e*
*/usr/share/locale/f*
*/usr/share/locale/g*
*/usr/share/locale/h*
*/usr/share/locale/i*
*/usr/share/locale/j*
*/usr/share/locale/k*
*/usr/share/locale/l*
*/usr/share/locale/m*
*/usr/share/locale/n*
*/usr/share/locale/o*
*/usr/share/locale/p*
*/usr/share/locale/ro*
*/usr/share/locale/rs*
*/usr/share/locale/rw*
*/usr/share/locale/s*
*/usr/share/locale/t*
*/usr/share/locale/u*
*/usr/share/locale/v*
*/usr/share/locale/w*
*/usr/share/locale/x*
*/usr/share/locale/y*
*/usr/share/locale/z*
*/usr/share/locale/l10n/a*
*/usr/share/locale/l10n/b*
*/usr/share/locale/l10n/c*
*/usr/share/locale/l10n/d*
*/usr/share/locale/l10n/e*
*/usr/share/locale/l10n/f*
*/usr/share/locale/l10n/g*
*/usr/share/locale/l10n/h*
*/usr/share/locale/l10n/i*
*/usr/share/locale/l10n/j*
*/usr/share/locale/l10n/k*
*/usr/share/locale/l10n/l*
*/usr/share/locale/l10n/m*
*/usr/share/locale/l10n/n*
*/usr/share/locale/l10n/o*
*/usr/share/locale/l10n/p*
*/usr/share/locale/l10n/q*
*/usr/share/locale/l10n/ro*
*/usr/share/locale/l10n/rs*
*/usr/share/locale/l10n/rw*
*/usr/share/locale/l10n/s*
*/usr/share/locale/l10n/t*
*/usr/share/locale/l10n/u*
*/usr/share/locale/l10n/v*
*/usr/share/locale/l10n/w*
*/usr/share/locale/l10n/x*
*/usr/share/locale/l10n/y*
*/usr/share/locale/l10n/z*
*/usr/share/man/a*
*/usr/share/man/b*
*/usr/share/man/c*
*/usr/share/man/d*
*/usr/share/man/e*
*/usr/share/man/f*
*/usr/share/man/g*
*/usr/share/man/h*
*/usr/share/man/i*
*/usr/share/man/j*
*/usr/share/man/k*
*/usr/share/man/lt*
*/usr/share/man/n*
*/usr/share/man/p*
*/usr/share/man/ro*
*/usr/share/man/rw*
*/usr/share/man/s*
*/usr/share/man/t*
*/usr/share/man/u*
*/usr/share/man/v*
*/usr/share/man/w*
*/usr/share/man/x*
*/usr/share/man/y*
*/usr/share/man/z*
*/usr/share/pkgconfig*
*/usr/share/rfc*
*/usr/share/sgml*
*/usr/share/sounds*
*/usr/share/templates*
*/usr/share/wallpapers*

Подроб­нее о настройке файла «/etc/make.conf» можно почи­тать в настоль­ной книге «Gentoo GNU/Linux» по адресу «http://www.gentoo.org/doc/ru/handbook».

Работа в chroot-окружении

Все готово для пере­хода в chroot-окружение. Для этого я исполь­зую неболь­шой скрипт «cfarm-chroot.sh», кото­рый мон­ти­рует все необ­хо­ди­мое, а при выходе из chroot-окружения - отмон­ти­рует.
cfarm-chroot.sh#!/bin/bash

CFARM="/srv/cfarm"
PORTAGE="/srv/cfarm/portage"
DISTFILES="${CFARM}/distfiles"
BINHOST="${CFARM}/binhost"
PROFILE="${CFARM}/$1"

if [ ! -d "${PROFILE}" ]; then
    echo "Directory ${PROFILE} not found"
    exit 1
fi

if [ ! -d "${BINHOST}/$1" ]; then
    mkdir -p "${BINHOST}/$1"
fi

if [ ! $(mount -l -t proc|cut -d ' ' -f3|grep ${PROFILE}/proc) ]; then
    mount -t proc none ${PROFILE}/proc
    mount -o bind /dev ${PROFILE}/dev
    mount -o bind /dev/pts ${PROFILE}/dev/pts
    mount -o bind ${PORTAGE} ${PROFILE}/var/portage/portage
    mount -o bind ${BINHOST}/$1 ${PROFILE}/var/portage/packages
    mount -o bind ${DISTFILES} ${PROFILE}/var/portage/distfiles
fi

COUNT=0
[ -f "/tmp/.cfarm-$1" ] && COUNT=$(cat "/tmp/.cfarm-$1")
(( COUNT++ ))
echo "${COUNT}" >"/tmp/.cfarm-$1"

chroot ${PROFILE} /bin/bash

COUNT=$(cat "/tmp/.cfarm-$1")
(( COUNT-- ))
echo "${COUNT}" >"/tmp/.cfarm-$1"

if [ "$(cat "/tmp/.cfarm-$1")" -le 0  ]; then
    rm -f "/tmp/.cfarm-$1"
    echo "Umount chroot ${PROFILE}..."
    umount ${PROFILE}/var/portage/distfiles
    umount ${PROFILE}/var/portage/packages
    umount ${PROFILE}/var/portage/portage
    umount ${PROFILE}/proc
    umount ${PROFILE}/dev/pts
    umount ${PROFILE}/dev
fi

Ско­пи­руйте содер­жи­мое скрипта в файл «/srv/cfarm/cfarm-chroot.sh», изме­ните зна­че­ния пере­мен­ных «CFARM» и «PORTAGE» в начале скрипта на те, кото­рые вам удобны и выпол­ните сле­ду­ю­щее.
# chmod 755 /srv/cfarm/cfarm-chroot.sh

Чтобы как-то выде­лить chroot-окружение от дру­гих кон­со­лей, под­пра­вим файл «/srv/cfarm/test/etc/profile».
# echo 'PS1="(chrt test) $PS1"' >>/srv/cfarm/test/etc/profile

Далее все дей­ствия будем выпол­нять в создан­ном chroot-окружении. Для пере­хода в него выпол­ните только что создан­ный скрипт, а в каче­стве пара­метра пере­дайте ему имя дирек­то­рии внутри «/srv/cfarm».
# /srv/cfarm/cfarm-chroot.sh test
# env-update && source /etc/profile

Необ­хо­димо сразу же обно­вить дерево «Portage».
# emerge --sync

Теперь, как ска­зано в доку­мен­та­ции, нужно опре­де­литься с про­фи­лем системы. Смот­рим спи­сок доступ­ных про­фи­лей.
# eselect profile list

В моем слу­чае под­хо­дит про­филь «default/linux/x86/10.0»
Я не хочу делить про­филь на «desktop» или «server», поэтому выпол­няю сле­ду­ю­щее.
# eselect profile set default/linux/x86/10.0

Так же нужно изме­нить файл «/etc/locale.gen», содер­жа­щий спи­сок необ­хо­ди­мых лока­лей.
# nano /etc/locale.gen

У меня он выгля­дит сле­ду­ю­щим обра­зом.
locale.genen_US.UTF-8  UTF-8
ru_RU.UTF-8  UTF-8
ru_RU.KOI8-R KOI8-R
ru_RU.CP1251 CP1251
ru_RU.IBM866 IBM866

Для уско­ре­ния ком­пи­ля­ции уста­но­вим пакет «dev-util/ccache».
# emerge ccache

Чтобы видеть ста­ти­стику работы «ccache», выпол­ним сле­ду­ю­щее.
# echo 'CCACHE_DIR="/var/cache/ccache"' >/etc/env.d/99ccache
# env-update && source /etc/profile
# ccache -s

Под­го­то­вим chroot-окружение для обнов­ле­ния «system». Посмот­рим, что же хочет уста­но­виться и попра­вим USE-флаги в файле «/etc/make.conf».
# emerge system -ep

На момент напи­са­ния еще не все рабо­тало с «python-3», поэтому два пакета «dev-lang/python» в системе мне не нужно.
# echo '>=dev-lang/python-3' >/etc/portage/package.mask

Позже, когда все исполь­зу­е­мые про­граммы перей­дут на исполь­зо­ва­ние «python-3», можно будет уда­лить строчку «>=dev-lang/python-3» из «/etc/portage/package.mask».

Все устра­и­вает, за исклю­че­нием USE-флагов пакета «sys-apps/util-linux». Но не будем изме­нять флаги в файле «/etc/make.conf», так как USE-флаги, кото­рые не устра­и­вают, будут вли­ять только на сборку этого кон­крет­ного пакета. Поэтому инфор­ма­цию о нем поме­стим в файл «/etc/portage/package.use».
# echo 'sys-apps/util-linux -crypt -perl' >>/etc/portage/package.use

Опре­де­лить, куда удоб­нее про­пи­сать USE-флаг, в «/etc/make.conf» или «/etc/portage/package.use», можно только исполь­зуя «Gentoo GNU/Linux» на про­тя­же­нии неко­то­рого вре­мени. Одно­знач­ного ответа никто не даст.

Созда­ние бинар­ных пакетов

Почти все готово для пер­вой сборки «system». Оста­лось решить вопрос с бинар­ными паке­тами. Ранее создан­ный файл «/etc/portage/package.exclude» убе­рет доста­точно много «мусора» из бинар­ных паке­тов, но этого недо­ста­точно. Все равно будет создано боль­шое коли­че­ство паке­тов c «лиш­ними» фай­лами, кото­рые позже попа­дут на конеч­ное устрой­ство. Необ­хо­дим метод борьбы с этим явлением.

Пер­во­на­чаль­ная идея была исполь­зо­вать файл «/etc/portage/profile/package.provided» для исклю­че­ния паке­тов, необ­хо­ди­мых только для сборки. Но веде­ние этого файла отни­мает много вре­мени и, в конеч­ном итоге, не дает жела­е­мого резуль­тата. Так же была идея гра­мотно настра­и­вать пере­мен­ную «RDEPEND» в фай­лах «.ebuild» дерева «Portage» и поме­щать их в локаль­ный овер­лей. Идея была так же отверг­нута из за боль­шой тру­до­ем­ко­сти и слож­но­стей с даль­ней­шим обнов­ле­нием. Выход нашелся в исполь­зо­ва­нии пере­мен­ной «PORTAGE_BINPKG_TAR_OPTS». Бла­го­даря ей, появи­лась воз­мож­ность задей­ство­вать опции «--exclude» и «--exclude-from» архи­ва­тора «tar».

Да, я зна­ком с пере­мен­ной «PKG_INSTALL_MASK» в «/etc/make.conf», но ее исполь­зо­ва­ние пока­за­лось мне менее удоб­ным, хотя ничто не мешает исполь­зо­вать и ее.

Созда­дим дирек­то­рию «/etc/portage/env» и файл «/etc/portage/bashrc».
# mkdir /etc/portage/env
# nano /etc/portage/bashrc

bashrc# Search and exclude fake '.so' in '/usr/lib', but it is needed only linkage
EXCLUDELD=$(cat "${EBUILD}"|sed -e 's/^[ \t]*//'| \
sed -n '/^gen_usr_ldscript/p'| \
sed -e 's/^gen_usr_ldscript[ \t]*//;s/-a[ \t]*//;s/\( \)\+/\n/g')
EXCLUDELD=$(echo "${EXCLUDELD}"| \
sed -e 's/^lib//;s/\.so.*//;s/^/--exclude \*\/usr\/lib\/lib/;s/$/.so/')
[ -n "${EXCLUDELD}" ] && \
PORTAGE_BINPKG_TAR_OPTS="${EXCLUDELD} ${PORTAGE_BINPKG_TAR_OPTS}"

# Per package exclude list
[ -f "/etc/portage/env/${CATEGORY}/${PN}.exclude" ] && \
PORTAGE_BINPKG_TAR_OPTS="${PORTAGE_BINPKG_TAR_OPTS} -X \
/etc/portage/env/${CATEGORY}/${PN}.exclude"

С помо­щью этого файла можно выре­зать из состава бинар­ного пакета все «лиш­нее». В дан­ном слу­чае у всех паке­тов про­ве­ря­ется нали­чие «под­дель­ных» фай­лов биб­лио­тек в «/usr/lib» необ­хо­ди­мых только для про­цесса лин­ковки, но бес­по­лез­ных для работы. Такие файлы игно­ри­ру­ются. Так же появ­ля­ется воз­мож­ность зада­вать инди­ви­ду­аль­ную маску для фай­лов, кото­рые не будут попа­дать в архив бинар­ного пакета. Напри­мер, в пакеты, необ­хо­ди­мые только для сборки, файлы вообще попа­дать не будут, только метаданные.

К при­меру, если выпол­нить ниже­при­ве­ден­ные дей­ствия, то полу­чится бинар­ный пакет «sys-devel/make», содер­жа­щий мета­дан­ные, но не уста­нав­ли­ва­ю­щий в систему ника­ких фай­лов. То есть пакет - «заглушка», про­сто удо­вле­тво­ря­ю­щий зави­си­мо­сти.
# echo '*' >/etc/portage/env/sys-devel/make.exclude
# emerge make -1

Для теку­щей уста­новки потре­бу­ются файлы с инди­ви­ду­аль­ными мас­ками для паке­тов. Я сде­лал неболь­шие наброски для базо­вой системы и собрал в архив. Ска­чи­ваем его и рас­па­ко­вы­ваем.
# wget http://mrcat.ru/download/chroot-install/packages.exclude.tar.bz2
# tar -xjvpf ./packages.exclude.tar.bz2 -C /etc/portage
# rm -f ./packages.exclude.tar.bz2

Таким обра­зом на конеч­ном устрой­стве будут и зави­си­мо­сти удо­вле­тво­рены, и фай­лов, необ­хо­ди­мых только для про­цесса сборки, не будет. Этим про­стым спо­со­бом можно сильно сокра­тить набор уста­нав­ли­ва­е­мых фай­лов. Един­ствен­ная слож­ность здесь - это дол­гий руч­ной поиск «ненуж­ных» фай­лов в бинар­ных паке­тах и запол­не­ние фай­лов исклю­че­ний. Но, я думаю, на это можно потра­тить один вечер и в даль­ней­шем про­сто поль­зо­ваться, изредка под­прав­ляя эти файлы по мере необходимости.

При­шло время пер­вой сборки. Еще раз про­ве­рим все ли USE-флаги заданы верно и обно­вим «system».
# emerge system -ep
# emerge system -e

После обнов­ле­ния «system» нужно выпол­нить обнов­ле­ние фай­лов в «/etc». Это можно сде­лать с помо­шью ути­литы «etc-update», пред­ва­ри­тельно настроив файл «/etc/etc-update.conf».
# nano /etc/etc-update.conf

Я изме­няю только два пара­метра.
etc-update.confmode="1"
pager=""

Затем, как реко­мен­до­вано в этом файле, уста­нав­ли­ваем «dev-util/dialog».
# emerge dialog

Выпол­няем обнов­ле­ние «/etc».
# etc-update

Можно смело заме­нить все файлы на новые, за исклю­че­нием «/etc/locale.gen».

Пере­клю­чаем про­филь «gcc». Посмот­реть уста­нов­лен­ные про­фили можно сле­ду­ю­щей коман­дой.
# gcc-config -l

У меня уста­но­ви­лось «gcc-4.4.4», поэтому я выпол­няю сле­ду­ю­щее.
# gcc-config i686-pc-linux-gnu-4.4.4
# env-update && source /etc/profile

Затем про­смат­ри­ваем и чистим в системе ненуж­ные пакеты.
# emerge --depclean -p
# emerge --depclean

Запу­стите поиск нару­шен­ных зави­си­мо­стей, пред­ва­ри­тельно уста­но­вив набор ути­лит из пакета «app-portage/gentoolkit».
# emerge gentoolkit
# revdep-rebuild

Обнов­ляем «world» новой вер­сией «gcc».
# emerge world -e

Если необ­хо­димо, повторно выпол­ните обнов­ле­ние «/etc» с помо­щью «etc-update».
# etc-update

Уста­но­вим ряд систем­ных паке­тов. Это демон syslog, демон cron и загруз­чик. Я выбрал для этого «app-admin/syslog-ng», «sys-process/cronie» и «sys-boot/grub».
# emerge syslog-ng cronie grub

Уста­но­вим набор допол­ни­тель­ных паке­тов. Я про­сто при­веду при­мер­ный спи­сок.
# emerge logrotate sudo mc screen bind-tools dhcpcd telnet-bsd htop lsof clockspeed

Пока что этого будет достаточно.

Сборка ядра

У нас уже есть набор необ­хо­ди­мых бинар­ных паке­тов, но еще нет ядра. Посмот­рим спи­сок доступ­ных ядер.
# emerge --search '%-sources'

Мне под­хо­дит пакет «sys-kernel/gentoo-sources». Его я и буду уста­нав­ли­вать.
# emerge gentoo-sources

Чтобы не тра­тить много вре­мени на про­смотр всех опций ядра, для пер­вого запуска можно вос­поль­зо­ваться гото­вым кон­фи­гу­ра­ци­он­ным фай­лом, взя­тым из любого «LiveCD» на основе «GNU/Linux». Я пред­по­чи­таю исполь­зо­вать «SystemRescueCD».

Загру­жа­емся с «LiveCD» и извле­каем кон­фи­гу­ра­цию ядра.
# cat /proc/config.gz | gunzip >/.config

После этого файл «.config» любым доступ­ным спо­со­бом пере­но­сим на наш ком­пью­тер, где ведется сборка, и копи­руем в «/usr/src/linux» в нашем chroot-окружении.

Выпол­няем кон­фи­гу­ра­цию ядра.
# cd /usr/src/linux
# sed -e "/CONFIG_INITRAMFS_SOURCE/d" -i .config
# make oldconfig

Позже при­дется не раз запус­кать «make menuconfig» для опти­маль­ного кон­фи­гу­ри­ро­ва­ния ядра с после­ду­ю­щей ком­пи­ля­цией. Но пока что, для пер­вого старта, этого достаточно.

Вос­поль­зу­емся неболь­шим скрип­том «makekernel.sh» для сборки, созда­ния и уста­новки пакета с бинар­ным ядром.
makekernel.sh#!/bin/bash
#
# Make kernel and modules
# Install into portage
# Build binary package
#

source "/usr/lib/portage/bin/isolated-functions.sh"

if [ ! -L "/usr/src/linux" ]; then
    eerror "'/usr/src/linux' not a symlink"
    exit 1
fi

TMPDIR=$(mktemp -u -d -p /tmp/ krn.XXXXXX)
KERNELLINK=$(readlink /usr/src/linux|sed -e 's/^linux-//')
KERNEL="/usr/src/linux-${KERNELLINK}"

if [ -d "${KERNEL}" ]; then
    if [ ! -f "${KERNEL}/.config" ]; then
        eerror "Kernel confiruration '.config' not found"
        exit 1
    fi
else
    eerror "Kernel source directory not exist"
    exit 1
fi

PREFIX="$(echo "${KERNELLINK}"|cut -d '-' -f2)"
PN="${PREFIX}-kernel"
PNFW="kernel-firmware"
PV=$(echo "${KERNELLINK}"|cut -d '-' -f1)
PR=$(echo "${KERNELLINK}"|cut -d '-' -f3)
[ -n "${PR}" ] && PR="-${PR}"
PVR="${PV}${PR}"
PF="${PN}-${PVR}"
PFFW="${PNFW}-${PVR}"

INSTALL="${TMPDIR}/sys-kernel/${PN}/files"
INSTALLFW="${TMPDIR}/sys-kernel/${PNFW}/files/lib"

eval $(portageq envvar -v PKGDIR)

if [ -z "${PKGDIR}" ]; then
    eerror "Variable 'PKGDIR' not set in '/etc/make.conf'"
    exit 1
fi

cd "${KERNEL}"
einfo "Preparing kernel and modules..."
if make bzImage modules EXTRAVERSION=-${PREFIX}; then
    einfo "Install modules..."
    INSTALL_MOD_PATH="${INSTALL}" make modules_install EXTRAVERSION=-${PREFIX}
else
    eerror "Kernel compilation error!"
    exit 1
fi

if [ -d "${INSTALL}/lib/modules" ]; then
    einfo "Prepare environment..."

    mkdir -p "${INSTALLFW}"

    if [ -d "${INSTALL}/lib/firmware" ]; then
        mv -f "${INSTALL}/lib/firmware" "${INSTALLFW}"
        FWDEP=">=sys-kernel/kernel-firmware-${PVR}"
    else
        ewarn "Firmware not found."
        FWDEP=""
    fi

    mkdir -p "${INSTALL}/boot"

    cp "${KERNEL}/System.map" "${INSTALL}/boot/System.map-${PV}-${PREFIX}"
    cp "${KERNEL}/arch/i386/boot/bzImage" "${INSTALL}/boot/kernel-${PV}-${PREFIX}"
    rm -f "${INSTALL}/lib/modules/${PV}-${PREFIX}/build"
    rm -f "${INSTALL}/lib/modules/${PV}-${PREFIX}/source"

    cat > "${TMPDIR}/sys-kernel/${PN}/${PF}.ebuild" << EOF
# Copyright 1999-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

inherit mount-boot

EAPI="2"

DESCRIPTION="Binary ${PVR} kernel and modules"
HOMEPAGE="http://mrcat.ru"
SRC_URI=""

LICENSE="GPL-2"
SLOT="${PV}"
KEYWORDS="~amd64 ~x86"
IUSE=""

RDEPEND="virtual/dev-manager ${FWDEP}"

pkg_setup() {
    ewarn 'All modules from "/lib/modules/${PV}-${PREFIX}" removed'
    ewarn 'Please, run "module-rebuild rebuild" after installation'
    rm -rf /lib/modules/${PV}-${PREFIX}
}

src_install() {
        insinto /
        doins -r "\${FILESDIR}/boot"
        doins -r "\${FILESDIR}/lib"
}

pkg_prerm() {
    mount-boot_mount_boot_partition
}
EOF
    cat > "${TMPDIR}/sys-kernel/${PNFW}/${PFFW}.ebuild" << EOF
# Copyright 1999-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

EAPI="2"

DESCRIPTION="Binary ${PVR} kernel firmware"
HOMEPAGE="http://mrcat.ru"
SRC_URI=""

LICENSE="GPL-2"
SLOT="0"
KEYWORDS="~amd64 ~x86"
IUSE=""

RDEPEND="!sys-kernel/linux-firmware"

src_install() {
        insinto /
        doins -r "\${FILESDIR}/lib"
}
EOF
    if [ -n "${FWDEP}" ]; then
        einfo "Building kernel firmware..."
        ebuild "${TMPDIR}/sys-kernel/${PNFW}/${PFFW}.ebuild" digest package
        einfo "Install kernel firmware..."
        [ -f "${PKGDIR}/sys-kernel/${PFFW}.tbz2" ] && emerge -1K "=sys-kernel/${PFFW}" || eerror "Kernel firmware not installed"
    fi
    einfo "Building binary kernel..."
    ebuild "${TMPDIR}/sys-kernel/${PN}/${PF}.ebuild" digest package
    einfo "Install binary kernel..."
    [ -f "${PKGDIR}/sys-kernel/${PF}.tbz2" ] && emerge -K "=sys-kernel/${PF}" || eerror "Kernel not installed"
    rm -rf "${TMPDIR}"
else
    eerror "Kernel compilation error!"
    exit 1
fi

Сохра­ним скрипт в «/usr/src/makekernel.sh» и выпол­ним.
# chmod 755 /usr/src/makekernel.sh
# /usr/src/makekernel.sh

Если все про­шло успешно, то в нашем chroot-окружении появится два уста­нов­лен­ных пакета. Напри­мер, если уста­нов­лен пакет «sys-kernel/gentoo-sources», то появятся пакеты «sys-kernel/gentoo-kernel» и, если есть в том необ­хо­ди­мость, «sys-kernel/kernel-firmware». Таким обра­зом, нико­гда не при­дется выпол­нять сборку ядра на конеч­ном устрой­стве, если у нас есть бинар­ные пакеты с ядром, кото­рые можно уста­но­вить, как и любые дру­гие, исполь­зуя пакет­ный менеджер.

Под­го­товка конеч­ного устрой­ства к установке

В моем слу­чае, оста­лось настро­ить http-сервер для доступа к дирек­то­рии «/srv/cfarm/binhost» из локаль­ной сети. Для этого я исполь­зую сер­вер «Apache», уста­нов­лен­ный на этом же компьютере.

Не исполь­зуйте ftp-сервер для доступа к бинар­ным паке­там! Послед­ние вер­сии пакет­ного мене­джера «portage» рабо­тают с про­бле­мами по ftp-протоколу.

Настало время уста­новки «Gentoo GNU/Linux» на конеч­ное устрой­ство. Для этого необ­хо­димо иметь загру­жен­ную систему на конеч­ном устрой­стве с рабо­та­ю­щей систе­мой «Portage».

Для этих целей я исполь­зую все тот же «SystemRescueCD». Нужно выпол­нить загрузку с iso-образа дан­ного «LiveCD» на конеч­ном устрой­стве. О том, как это сде­лать, подробно рас­ска­зано на офи­ци­аль­ной стра­нице про­екта в раз­деле документации.

Я буду про­из­во­дить уста­новку на вир­ту­аль­ной машине, создан­ной в «VirtualBox» с раз­ме­ром вир­ту­аль­ного диска 1Gb и раз­ме­ром опе­ра­тив­ной памяти 128Mb. Этого более чем доста­точно для уста­новки системы. Так «много» опе­ра­тив­ной памяти необ­хо­димо только для уста­новки системы. При хоро­шей опти­ми­за­ции ядра, система будет непри­нуж­денно рабо­тать и с 64Mb RAM.

Выпол­нив загрузку с «LiveCD», зада­дим пароль супер­поль­зо­ва­теля «root» и настроим сеть, чтобы иметь воз­мож­ность под­клю­читься к системе по «ssh» и рабо­тать с при­выч­ным и удоб­ным тер­ми­на­лом.
# passwd
# net-setup eth0

Для удоб­ства уста­новки полезно исполь­зо­вать ути­литу «screen», кото­рая дает воз­мож­ность быстро пере­клю­чаться между сессиями.

Выпол­ним син­хро­ни­за­цию вре­мени.
# ntpdate pool.ntp.org
# hwclock -uw

Раз­би­ваем жест­кие диски на раз­делы. У меня в тесто­вой вир­ту­аль­ной машине он всего один.
# cfdisk /dev/sda

Пер­вый раз­дел «/dev/sda1» - загру­зоч­ный, раз­ме­ром 32 Mb. Далее идет раз­дел под­качки «/dev/sda2» раз­ме­ром 256 Mb. Все осталь­ное идет под кор­не­вой раз­дел «/dev/sda3».

В резуль­тате вывод команды «fdisk -l» будет выгля­деть как пока­зано ниже.
Disk /dev/sda: 1073 MB, 1073741824 bytes
255 heads, 63 sectors/track, 130 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1           4       32098+  83  Linux
/dev/sda2               5          35      249007+  83  Linux
/dev/sda3              36         130      763087+  83  Linux

Фор­ма­ти­руем раз­делы и акти­ви­руем раз­дел под­качки.
# mkfs.ext2 /dev/sda1
# mkfs.ext3 /dev/sda3
# mkswap /dev/sda2
# swapon /dev/sda2

Создаем необ­хо­ди­мые дирек­то­рии и мон­ти­руем раз­делы.
# mkdir /mnt/test
# mount /dev/sda3 /mnt/test
# mkdir -p /mnt/test/{boot,dev,home,mnt,proc,root,sys,var/portage/portage,var/portage/packages,/etc/portage/env,var/tmp}
# chmod 700 /mnt/test/root
# touch /mnt/test/boot/.keep
# mount /dev/sda1 /mnt/test/boot

Созда­дим два устрой­ства, без кото­рых про­цесс загрузки будет про­бле­ма­тич­ным.
# mknod -m 600 /mnt/test/dev/console c 5 1
# mknod -m 666 /mnt/test/dev/null c 1 3

Сле­ду­ю­щий этап наи­бо­лее инте­ре­сен. Нет необ­хо­ди­мо­сти снова раз­во­ра­чи­вать «Stage3», как реко­мен­дует руко­вод­ство. Мы уже имеем набор бинар­ных паке­тов, а на дан­ном «LiveCD» - уста­нов­лен­ный мене­джер паке­тов «portage». Так что нам мешает про­сто уста­но­вить бинар­ные пакеты в нуж­ное нам место?

Уста­новка бинар­ных пакетов

При­сту­пим. Необ­хо­димо уда­лить базу дан­ных уста­нов­лен­ных паке­тов c «LiveCD», иначе «portage» будет пытаться обно­вить в ней инфор­ма­цию, что затя­нется надолго, а ждать не хочется.
# rm -rf /var/db/pkg/*

Настроим файл «/etc/make.conf» системы на «LiveCD» для того, чтобы «emerge» мог видеть наш репо­зи­то­рий с бинар­ными паке­тами. Для этого изме­ним файл «/etc/make.conf».
# nano /etc/make.conf

...
PORTDIR="/mnt/test/var/portage/portage"
PORTAGE_RSYNC_EXTRA_OPTS="--progress --delete-excluded --exclude-from=/etc/portage/portage.exclude"
PORTAGE_BINHOST="http://packages.myhost.cxm/test"

Созда­дим файл «/etc/portage/portage.exclude».
# nano /etc/portage/portage.exclude

portage.exclude+ /profiles
- *.mask
- /*

Я пла­ни­рую хра­нить на конеч­ном устрой­стве остатки дерева «Portage» в «/var/portage/portage». Поэтому сразу задаю соот­вет­ству­ю­щее зна­че­ние пере­мен­ной «PORTDIR» в файле «/etc/make.conf»

Выпол­ним син­хро­ни­за­цию.
# emerge --sync

Настроим «portage» для уста­новки бинар­ных паке­тов на конеч­ное устрой­ство.
Созда­дим файл «/mnt/test/etc/make.conf».
# nano /mnt/test/etc/make.conf

make.confCHOST="i686-pc-linux-gnu"

ACCEPT_KEYWORDS="~x86"

FEATURES="-parallel-fetch getbinpkg nodoc noman noinfo"

EMERGE_DEFAULT_OPTS="--alphabetical --verbose --nospinner"

PORTAGE_RSYNC_EXTRA_OPTS="--delete-excluded --exclude-from=/etc/portage/portage.exclude"

PORTAGE_BINHOST="http://packages.myhost.cxm/test"
PORTDIR="/var/portage/portage"
PKGDIR="/var/portage/packages"

LINGUAS="ru"

Обра­тите вни­ма­ние на зна­че­ние пере­мен­ной PORTAGE_BINHOST. Путь дол­жен ука­зы­вать на место­рас­по­ло­же­ние бинар­ных паке­тов на сервере.

Копи­руем файлы «/etc/portage/portage.exclude» и «/etc/make.globals» с «LiveCD».
# cp -f /etc/portage/portage.exclude /mnt/test/etc/portage
# cp -fH /etc/make.globals /mnt/test/etc

При уста­новке допол­ни­тель­ных моду­лей ядра, «portage» будет искать исход­ные тек­сты ядра, а их не будет. Так же нет необ­хо­ди­мо­сти сохра­нять файлы бинар­ных паке­тов на конеч­ном устрой­стве.
Для реше­ния этих задач созда­дим файл «/mnt/test/etc/portage/bashrc».
# nano /mnt/test/etc/portage/bashrc

bashrclinux-mod_pkg_setup() {
    debug-print-function ${FUNCNAME} $*
    strip_modulenames;
    set_kvobj;
}

update_depmod() {
    debug-print-function ${FUNCNAME} $*

    # if we haven't determined the version yet, we need too.
    get_version;

    ebegin "Updating module dependencies ${KV_FULL}"
        depmod -a -b ${ROOT} -r ${KV_FULL}
    eend $?
}

post_pkg_postinst() {
    rm -f "${PORTAGE_BINPKG_FILE}"
    [ ! "$(ls -A "${PKGDIR}/${CATEGORY}")" ] && \
        rm -rf "${PKGDIR}/${CATEGORY}"
    rm -f "${PKGDIR}/Packages"
}

Уста­но­вим про­филь системы, пред­ва­ри­тельно про­смот­рев их спи­сок.
# eselect profile list
# ln -s ../var/portage/portage/profiles/default/linux/x86/10.0 /mnt/test/etc/make.profile

Так же, зара­нее созда­дим файл со спис­ком лока­лей, как мы делали это при сборке в chroot-окружении.
# nano /mnt/test/etc/locale.gen

locale.genen_US.UTF-8  UTF-8
ru_RU.UTF-8  UTF-8
ru_RU.KOI8-R KOI8-R
ru_RU.CP1251 CP1251
ru_RU.IBM866 IBM866

Зада­дим вре­мен­ную зону.
# echo 'Europe/Moscow' >/mnt/test/etc/timezone

Ско­пи­руем файл «/etc/resolv.conf» в буду­щее chroot-окружение.
# cp -f /etc/resolv.conf /mnt/test/etc

Почти все готово для начала уста­новки бинар­ных паке­тов на диск. Оста­лось уста­но­вить несколько заглу­шек для паке­тов, кото­рые желают что либо ском­пи­ли­ро­вать или про­из­ве­сти дру­гие дей­ствия с фай­лами, кото­рых не будет в системе. Я под­го­то­вил неболь­шой набор таких файлов.

# wget http://mrcat.ru/download/chroot-install/eclass.patches.tar.bz2
# tar -xjvpf ./eclass.patches.tar.bz2 -C /mnt/test/etc/portage
# rm -f ./eclass.patches.tar.bz2

Теперь под­го­то­вим окру­же­ние и нач­нем уста­новку бинар­ных паке­тов на диск. Нет необ­хо­ди­мо­сти ста­вить «system», доста­точно сразу поста­вить «world».
# mkdir -p /var/portage/packages
# mount -o bind /mnt/test/var/portage/packages /var/portage/packages
# mount -o bind /mnt/test/var/tmp /var/tmp
# export ROOT="/mnt/test"
# export PORTAGE_CONFIGROOT="/mnt/test"
# emerge world -e

Уста­новка допол­ни­тель­ных паке­тов и настройка

Под­го­то­вим chroot-окружение для даль­ней­шей уста­новки и перей­дем в него.
# mount -o bind /dev /mnt/test/dev
# mount -o bind /dev/pts /mnt/test/dev/pts
# mount -t proc proc /mnt/test/proc
# chroot /mnt/test /bin/bash
# unset ROOT
# unset PORTAGE_CONFIGROOT
# eselect python set 1
# env-update && source /etc/profile

Сразу же выпол­ним гене­ра­цию лока­лей, задан­ных в файле «/etc/locale.gen».
# locale-gen

Если уста­нав­ли­вался пакет «sys-libs/cracklib», то нужно выпол­нить сле­ду­ю­щее.
# create-cracklib-dict /usr/share/dict/* >/dev/null

Пере­уста­но­вим пакет «net-misc/openssh», так как он создает для своей работы поль­зо­ва­теля «sshd» и без него не запу­стится.
# emerge openssh -1

Уста­но­вим допол­ни­тель­ные пакеты.
# emerge logrotate sudo syslog-ng mc screen \
gentoolkit dialog bind-tools dhcpcd telnet-bsd grub \
cronie htop lsof clockspeed

Под­пра­вим, как делали раньше, файл «/etc/etc-update.conf».
# nano /etc/etc-update.conf

etc-update.confmode="1"
pager=""

Обно­вим «/etc».
# etc-update

Про­ве­рим систему на нали­чие «битых» биб­лио­тек.
# revdep-rebuild -p

Если «revdep-rebuild» пока­зы­вает нали­чие недо­ста­ю­щих биб­лио­тек, зна­чит при сборке паке­тов, в кото­рых должны при­сут­ство­вать эти биб­лио­теки, их не обна­ру­жено. Видимо, пере­ста­ра­лись с исклю­че­нием «мусора» из этих пакетов.

Уста­но­вим пакет с ядром, кото­рое собрали ранее.
# emerge gentoo-kernel

При­шло время уста­но­вить загруз­чик. Созда­дим файл «/boot/grub/grub.conf«
# nano /boot/grub/grub.conf

grub.conftimeout 5
default 0

# Gentoo
title=Gentoo
root (hd0,0)
kernel /kernel-2.6.33-gentoo root=/dev/sda3

# Reboot
title Reboot
reboot

# Shutdown
title Shutdown
halt

Созда­дим файл «/etc/mtab», выпол­нив сле­ду­ю­щее.
# cat /proc/mounts >/etc/mtab

Выпол­ним уста­новку «grub» в «MBR».
# grub-install /dev/sda

На этом уста­новка загруз­чика закончена.

Доба­вим необ­хо­ди­мые сер­висы в авто­за­грузку.
# rc-update add consolefont boot
# rc-update add cronie default
# rc-update add syslog-ng default
# rc-update add sshd default

Зада­дим пароль супер­поль­зо­ва­теля «root» и доба­вим ему в домаш­нюю дирек­то­рию файлы из «/etc/skel«
# passwd
# cp -rf /etc/skel/. /root

Созда­дим учет­ную запись поль­зо­ва­теля, под кото­рой будем рабо­тать, зада­дим пароль и обес­пе­чим запуск про­грамм с пра­вами супер­поль­зо­ва­теля для воз­мож­но­сти адми­ни­стри­ро­ва­ния системы. Я добавлю поль­зо­ва­теля «mrcat».
# useradd -g users -G wheel,audio,cdrom,video,cdrw -m mrcat
# chmod 700 /home/mrcat
# passwd mrcat
# echo 'mrcat ALL=(ALL) ALL'>>/etc/sudoers

Зада­дим локаль по умол­ча­нию.
# echo -e 'LANG="ru_RU.UTF-8"\nLC_ALL="ru_RU.UTF-8"' >/etc/env.d/02locale

Изме­ним файл «/etc/fstab».
# nano /etc/fstab

fstab/dev/sda1       /boot           ext2    noauto,noatime          1 2
/dev/sda3       /               ext3    noatime                 0 1
/dev/sda2       none            swap    sw                      0 0
shm             /dev/shm        tmpfs   nodev,nosuid,noexec     0 0

Далее при­сту­пим к настройке раз­лич­ных при­ло­же­ний.
Поскольку у меня уста­нов­лен пакет «app-shells/bash-completion», то я выпол­няю сле­ду­ю­щее.
# eselect bashcomp enable --global base

Так же я запре­щаю захо­дить по про­то­колу «SSH» поль­зо­ва­телю «root», редак­ти­руя файл «/etc/ssh/sshd_config».
# sed -e 's/^#PermitRootLogin yes/PermitRootLogin no/' -i /etc/ssh/sshd_config

Изме­ним файл «/etc/conf.d/consolefont».
# nano /etc/conf.d/consolefont

consolefontconsolefont="cyr-sun16"

Изме­ним файл «/etc/conf.d/hostname».
# nano /etc/conf.d/hostname

hostnamehostname="test"

Изме­ним файл «/etc/conf.d/hwclock».
# nano /etc/conf.d/hwclock

hwclockclock_systohc="YES"

Изме­ним файл «/etc/conf.d/keymaps».
# nano /etc/conf.d/keymaps

keymapskeymap="ruwin_ctrl-UTF-8"

Настроим сеть. Созда­дим сим­во­ли­че­скую ссылку.
# ln -s net.lo /etc/init.d/net.eth0

Изме­ним файл «/etc/conf.d/net».
# nano /etc/conf.d/net

Для загрузки с исполь­зо­ва­нием «DHCP», как в моем слу­чае, доба­вим сле­ду­ю­щее.
netmodules_eth0="dhcpcd"
config_eth0="dhcp"
dhcpcd_eth0="-b -L"

Изме­ним файл «/etc/rc.conf».
# nano /etc/rc.conf

Рас­ком­мен­ти­руем сле­ду­ю­щие строки.
rc.confrc_interactive="YES"
rc_depend_strict="NO"
rc_hotplug="*"
unicode="YES"

Воз­вра­ща­емся из choot-окружения в основ­ную систему.

Пер­вый запуск

Все готово для пер­вой загрузки во вновь уста­нов­лен­ную систему. Для этого я выклю­чаю вир­ту­аль­ную машину в «VirtualBox», уби­раю авто­за­грузку с образа компакт-диска и снова включаю.

Если после пере­за­грузки не рабо­тает лока­ли­за­ция, то пере­за­гру­зи­тесь еще раз - про­блема должна исчезнуть.

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

Посмот­рим, сколько места система заняла на диске. У меня полу­чился вот такой заме­ча­тель­ный резуль­тат.
# df -h
Filesystem            Size  Used Avail Use% Mounted on
rootfs                734M  239M  459M  35% /
/dev/root             734M  239M  459M  35% /
devtmpfs               56M  160K   56M   1% /dev
rc-svcdir             1.0M   44K  980K   5% /lib/rc/init.d
shm                    57M     0   57M   0% /dev/shm

Ока­зы­ва­ется, «Gentoo GNU/Linux» можно сде­лать совсем нетре­бо­ва­тель­ным к дис­ко­вым ресур­сам. Даже не тре­бу­ется уста­новка ути­литы «localepurge» для уда­ле­ния неис­поль­зу­е­мых лока­лей - их уже и так нет.

Обнов­ле­ние системы

Далее я рас­скажу, как обнов­лять такую систему. Если посмот­реть, то почти все команды «emerge» идут сна­чала с опцией «-p (--pretend)», потом без нее. Так удоб­нее делать для того, чтобы перед обнов­ле­нием или уста­нов­кой видеть, что будет про­ис­хо­дить и иметь воз­мож­ность сна­чала изме­нить кон­фи­гу­ра­цию пакет­ного мене­джера «portage».

Все настройки «portage» и USE-флаги меня­ются только на ком­пью­тере, где про­ис­хо­дит сборка. На конеч­ном устрой­стве кон­фи­гу­ра­ция мене­джера паке­тов «portage» оста­ется неизменной.

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

Для обнов­ле­ния системы на ком­пью­тере, где про­из­во­ди­лась сборка, я исполь­зую неболь­шой скрипт «ecleaner», кото­рый заме­няет собой команду «eclean -d packages» и допол­ни­тельно чистит файл «Packages», кото­рый рас­по­ло­жен в дирек­то­рии бинар­ных паке­тов, от лиш­них запи­сей, так как «portage» этого почему-то не делает.
ecleaner#!/bin/bash

source "/usr/lib/portage/bin/isolated-functions.sh"
source "/etc/make.conf"

# Clean unused packages
/usr/bin/qpkg -E

# Clean unused blocks
einfo "Cleaning unused blocks..."
PKGLIST=$(cat "${PKGDIR}/Packages"|grep 'CPV:'|sed -e 's/CPV: //')
for CPV in ${PKGLIST}; do
    if [ ! -f "${PKGDIR}/${CPV}.tbz2" ]; then
        sed -e "/^CPV: ${CPV//\//\\/}$/,/^$/d" -i "${PKGDIR}/Packages"
        ewarn "${CPV}"
    fi
done

Сохра­ним скрипт в «/usr/local/sbin/ecleaner» и сде­лаем его испол­ня­е­мым.
# chmod 755 /usr/local/sbin/ecleaner

Дей­ствия при регу­ляр­ном обнов­ле­нии мира.
На ком­пью­тере, где про­из­во­дится сборка бинар­ных паке­тов, выпол­няем сле­ду­ю­щее.
# emerge --sync
# emerge world -uDNp
# emerge world -uDN
# etc-update
# emerge --depclean -p
# emerge --depclean
# revdep-rebuild
# ecleaner

На конеч­ном устрой­стве, если отсут­ствует дерево «Portage», при выпол­не­нии команды «emerge», у послед­ней пере­стает рабо­тать опция «--newuse». Поэтому, если изме­нить USE-флаги, и потом на конеч­ном устрой­стве выпол­нить «emerge world -uDNp», то для паке­тов с изме­нен­ными USE-флагами обнов­ле­ние выпол­няться не будет.

Поэтому пой­дем на неболь­шую хит­рость и обнов­ле­ние мира будем выпол­нять скрип­том «eworld».
eworld#!/bin/bash

UPDLIST=$(emerge -eqp --color=n world | grep -e '\[binary' \
    | sed -n '/^\[.*U.*\].*\//p;/^\[.*S.*\].*\//p;/\*/p;/\%/p' \
    | cut -d ']' -f2 | sed -e 's/^\s/=/' | cut -d' ' -f1| uniq)

if [ -z "${UPDLIST}" ]; then
    echo "Nothing to do."
else
    emerge -1 ${UPDLIST} $*
fi

Сохра­ним скрипт в «/usr/local/sbin/eworld» на конеч­ном устрой­стве и выпол­ним сле­ду­ю­щее.
# chmod 755 /usr/local/sbin/eworld

Теперь про­из­ве­дем обнов­ле­ние мира на конеч­ном устрой­стве.
# emerge --sync
# eworld -p
# eworld
# etc-update
# emerge --depclean -p
# emerge --depclean

Дей­ствия при уста­новке нового пакета.
На ком­пью­тере, где про­из­во­дится сборка бинар­ных паке­тов, выпол­няем сле­ду­ю­щее.
# emerge foo -p
# emerge foo

На конеч­ном устрой­стве - сле­ду­ю­щее.
# emerge foo -p
# emerge foo

Дей­ствия при уда­ле­нии пакета.
На ком­пью­тере, где про­из­во­дится сборка бинар­ных паке­тов, выпол­няем сле­ду­ю­щее.
# emerge -С foo
# emerge --depclean -p
# emerge --depclean
# revdep-rebuild
# ecleaner

На конеч­ном устрой­стве -сле­ду­ю­щее.
# emerge -C foo
# emerge --depclean -p
# emerge --depclean
# revdep-rebuild

Дей­ствия при обнов­ле­нии ядра. Допу­стим, у нас было уста­нов­лено ядро «gentoo-sources-2.6.33-r1», а при обнов­ле­нии мира уста­но­ви­лось еще и ядро «gentoo-sources-2.6.33-r2».
Дей­ствия на ком­пью­тере, где про­из­во­дится сборка бинар­ных паке­тов.
# eselect kernel list
# eselect kernel set linux-2.6.33-gentoo-r2
# cp -f /usr/src/linux-2.6.33-gentoo-r1/.config /usr/src/linux
# cd /usr/src/linux && make oldconfig
# /usr/src/makekernel.sh
# ecleaner
# rm -rf /usr/src/linux-2.6.33-gentoo-r1
# rm -rf /lib/modules/2.6.33-gentoo-r1

Если уста­нав­ли­ва­лись допол­ни­тель­ные модули ядра, то для их обнов­ле­ния удобно исполь­зо­вать ути­литу «module-rebuild». Уста­но­вим ее и выпол­ним.
# emerge  module-rebuild
# module-rebuild rebuild

Выпол­ним на конеч­ном устрой­стве.
# emerge gentoo-kernel
# emerge --depclean -p
# emerge --depclean

Так же, если уста­нав­ли­ва­лись допол­ни­тель­ные модули, нужно выпол­нить сле­ду­ю­щее.
# module-rebuild rebuild

Затем нужно изме­нить кон­фи­гу­ра­ци­он­ный файл загруз­чика «/boot/grub/grub.conf», чтобы вклю­чить загрузку с нового ядра.
# nano /boot/grub/grub.conf

Заклю­че­ние

Как видно из ста­тьи, можно подойти к про­цессу уста­новки «Gentoo GNU/Linux» более ори­ги­нально, нежели реко­мен­дует офи­ци­аль­ное руко­вод­ство. Можно заста­вить рабо­тать самый раз­лич­ный класс устройств с дан­ным дис­три­бу­ти­вом, при­ме­няя метод, опи­сан­ный в статье.

По дан­ной схеме уже доста­точно про­дол­жи­тель­ное время рабо­тают несколько сер­ве­ров и рабо­чих стан­ций. Выиг­рыш в исполь­зо­ва­нии оче­ви­ден - опти­ми­за­ция паке­тов для кон­крет­ного про­цес­сора, пакеты собраны только с необ­хо­ди­мыми USE-флагами, эко­но­мия дис­ко­вого про­стран­ства и ресурсы ком­пью­те­ров исполь­зу­ются по назна­че­нию, а не для про­цесса компиляции.