Печать

Осторожно! Многобукафф!

Это четвертая и главная часть длинного повествования об одном исследовании, цели которого:

1. Автоматизация процесса установки и переустановки.

2. Определение оптимального разбиения диска.

3. Определение оптимальной процедуры установки.

Здесь рассматривается Автоматическая установка FreeBSD 10 на ZFS.

Рассмотрим внимательно процесс загрузки дистрибутива.

Сначала загрузчик (описание LOADER.4TH и сценарий LOADER.RC) показывает нам меню (сценарий MENU.RC), описанное в нескольких файлах.

SHORTCUTS.4TH — указывает что отобразить

BEASTIE.4TH — описывает псевдографику «демона».

BRAND.4TH - «прорисовка» бренда (слово FreeBSD).

VERSION.4TH – версии.

MENU.4TH, MENU_COMMANDS.4TH, MENUSETS.4TH — меню.

По результату выполнения сценария меню происходит загрузка.

После загрузки ядра и непосредственно операционной системы с дистрибутива выполняется сценарий \distrib\ETC\RC.LOCAL (еще в монопольном режиме), где и описано первое меню операционной системы (если нет /etc/installerconfig): Install – запускается Bsdinstall, Shell – открывается строка, также в монопольном режиме, LiveCD – выходим из однопользовательского режима в многопользовательский в среде LiveCD. Пользователь один — root с пустым паролем.

/etc/installerconfig – это список параметров автоматической установки и сценарий послеустановочных операций, которые выполнятся без всяких вопросов.

Но нам эта схема не подходит, мы хотим выполнить всю установку без bsdinstall, с помощью нашего скрипта. Поэтому наш скрипт (назовем его instscr.sh) мы поместим в /etc дистрибутива, а в rc.local добавим несколько строк перед запуском этого меню (строка if [ -f /etc/installerconfig ]; then), первые строки, где определяется тип терминала мы не трогаем.

Вставленный код:

if [ -f /etc/instscr.sh ]; then

/bin/sh -xv /etc/instscr.sh

exit 0

fi

параметр —xv поставлен для принудительного вывода в терминал команд и результатов для отладки. В «боевой» версии скрипта его можно убрать.

Пара слов о создании собственного дистрибутива FreeBSD. По непонятным мне причинам UltraIso не смог внедрить нужные файлы в ISO установочного диска FreeBSD. Возможно потому, что это была пробная версия программы. После долгого поиска бесплатной утилиты я решил не заморачиваться, а

1) на тестовом серваке FreeBSD установил инструменты записи CD (/usr/ports/sysutils/cdrtools),

2) смонтировал официальный дисрибутив в /mnt

mount_cd9660 /dev/cd0 /media

3) скопировал содержимое в подготовленную папку ~/distr

4) сделал скрипт на запуск формирования дистрибутива из папки, состоящий из одной строки

#!/bin/sh

mkisofs -V 10_1_RELEASE_AMD64_CD -J -R -b boot/cdboot -no-emul-boot -o ~/FreeBSD10_2.iso ~/distr

5) все изменения мы вносим в дистрибутив в каталоге ~/distr, запускаем скрипт и по окончанию его работы забираем готовый образ установочного диска из домашнего каталога.

В начале скрипта мы попробуем определить имена устройств жесткого диска и сетевой платы. Если кто знает способ проще и надежней — пишите.

iface=`dmesg | grep Ethernet | awk -F: ' { print ($1) } '`

dev=`camcontrol devlist | awk -F\( ' $2!~/cd/ { print($2) } ' | awk -F, ' { print($1) } '`

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

Далее мы будем использовать эти переменные.

По окончании работы скрипт предупредит о необходимости изъять установочный диск из привода. Обращаю Ваше внимание на то, что этот диск без всяких вариантов удаляет все на имеющемся диске и устанавливает новую систему, поэтому важно соблюдать осторожность и не уничтожить действующую машину случайным запуском. Если не вынуть диск из привода, с каждым запуском будет происходить установка при условии, что первым в BIOS стоит наш диск.

Также мы добавим несколько строк для выполнения некоторых послеустановочных настроек.

В установленной системе создаем файл /etc/rc.local. Этот файл содержит только команду на запуск послеустановочного скрипта, который запустится при первом запуске до выхода в многопользовательский режим (до появления приглашения ко входу пользователя):

cat << EOF > /mnt/etc/rc.local

#!/bin/sh

/bin/sh -xv /etc/postinstall.sh

EOF

А вот создание этого скрипта:

cat << EOF > /mnt/etc/postinstall.sh

#!/bin/sh

sed -I -e 's/KOI8-R/UTF-8/g' /etc/login.conf

cap_mkdb /etc/login.conf

echo 'Passw0rd' | pw usermod root -h 0

echo 'fff' |pw useradd fff -h 0 -G wheel -L russian

pw usermod -n root -L russian

rm /etc/rc.local

rm /etc/postinstall.sh

EOF

С помощью sed меняем кодировку с KOI8-R на UTF8, затем пересоздаем базу, меняем пароль root, создаем пользователя, руту также назначаем русский язык, и удаляем все эти файлы, чтоб они не выстрелили при следующем запуске. Теперь система будет полностью готова к тому, что мы зайдем на этот сервер по ssh с нормальным UTF-8 терминалом. Русский язык, на мой взгляд, root-у тоже нужен, иначе после выполнения su мы увидим вместо папок и файлов с русскими именами всякие закорючки.

Смысл всего этого действа в том, что нам необязательно присутствовать около сервера. Достаточно выслать дистрибутив (по почте или по tftp, через netboot), который все сделает сам, мы зайдем на готовый сервер и настроим его, как надо. Либо при установке большого числа одинаковых серверов такой дистрибутив сэкономит нам немного сил и времени.

Полностью скрипт:

#!/bin/sh -xv

echo " This script will install FreeBSD in unattended mode."

echo " Please be patient."

########### var

#dev="da0"

#iface="m0"

iface=`dmesg | grep Ethernet | awk -F: ' { print ($1) } '`

dev=`camcontrol devlist | awk -F\( ' $2!~/[cd|md|fd]/ { print($2) } ' | awk -F, ' { print($1) } '`

honame="FreeBSDtest11.seczone.ru"

########### gpart

gpart destroy -F $dev

kldload zfs

sysctl vfs.zfs.min_auto_ashift=12

gpart create -s GPT $dev

gpart add -s 512 -a 4k -t freebsd-boot -l boot0 $dev

gpart add -s 4g -a 4k -t freebsd-swap -l swap0 $dev

gpart add -a 4k -t freebsd-zfs -l disk0 $dev

gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 $dev

########### zpool

zpool create -f -m /mnt zroot /dev/gpt/disk0

zpool set bootfs=zroot zroot

zfs set mountpoint=/mnt zroot

zpool export zroot

zpool import -o cachefile=/tmp/zpool.cache zroot

zfs create zroot/usr

zfs create zroot/usr/home

zfs create zroot/var

zfs create zroot/data1

zfs create -o compression=gzip zroot/data2

zfs create -o compression=lzjb zroot/tmp

zfs create -o compression=lzjb zroot/usr/ports

zfs create zroot/usr/local

zfs create zroot/usr/local/www

zfs create -o compression=lzjb zroot/usr/src

zfs create -o compression=lzjb zroot/usr/obj

zfs create -o compression=lzjb zroot/var/crash

zfs create zroot/var/db

zfs create zroot/var/log

zfs create -o compression=gzip zroot/var/mail

zfs create -o compression=lzjb zroot/var/tmp

########## prepare

swapon /dev/gpt/swap0

chmod 1777 /mnt/tmp

chmod 1777 /mnt/var/tmp

cd /mnt ; ln -s usr/home home

######### install

echo "install ..."

cd /usr/freebsd-dist

#fetch ftp://ftp.freebsd.org/pub/FreeBSD/releases/i386/10.0-RELEASE/src.txz

#fetch ftp://ftp.freebsd.org/pub/FreeBSD/releases/i386/10.0-RELEASE/base.txz

#fetch ftp://ftp.freebsd.org/pub/FreeBSD/releases/i386/10.0-RELEASE/kernel.txz

cat base.txz | tar --unlink -xvpJf - -C /mnt

cat kernel.txz | tar --unlink -xvpJf - -C /mnt

cat src.txz | tar --unlink -xvpJf - -C /mnt

echo "install ok"

cp /tmp/zpool.cache /mnt/boot/zfs/zpool.cache

########## tuning

cat << EOF > /mnt/etc/rc.conf

dumpdev="AUTO"

zfs_enable="YES"

hostname=$honame

ifconfig_$iface="inet 192.168.1.103 netmask 255.255.255.0"

defaultrouter="192.168.1.1"

sshd_enable="YES"

EOF

cat << EOF > /mnt/boot/loader.conf

zfs_load="YES"

EOF

cat << EOF > /mnt/etc/resolv.conf

nameserver 78.108.68.68

nameserver 78.108.68.108

EOF

cat << EOF > /mnt/etc/postinstall.sh

#!/bin/sh -xv

sed -I -e 's/KOI8-R/UTF-8/g' /etc/login.conf

cap_mkdb /etc/login.conf

echo 'Passw0rd' | pw usermod root -h 0

echo 'fff' |pw useradd fff -h 0 -G wheel -L russian

pw usermod -n root -L russian

rm /etc/rc.local

rm /etc/postinstall.sh

EOF

cat << EOF > /mnt/etc/rc.local

#!/bin/sh -xv

/bin/sh -xv /etc/postinstall.sh

EOF

cat << EOF > /mnt/etc/fstab

# Device Mountpoint FStype Options Dump Pass#

/dev/gpt/swap0 none swap sw 0 0

EOF

zfs umount -a

zfs set mountpoint=legacy zroot

zfs set mountpoint=/data1 zroot/data1

zfs set mountpoint=/data2 zroot/data2

zfs set mountpoint=/tmp zroot/tmp

zfs set mountpoint=/usr zroot/usr

zfs set mountpoint=/var zroot/var

echo "Please remove install media"

echo "AFTER system shutdown"

sleep 30

shutdown -p now

Однако при установке на BIOS с поддержкой UEFI внезапно наступил на грабли. BIOS не может найти загрузочную запись в файловой системе zfs на GPT разделе.

 

Согласно мануалу (https://www.freebsd.org/cgi/man.cgi?query=uefi&sektion=8&manpath=FreeBSD+10.2-stable) имеем проблему:

“Переменные окружения EFI не поддерживаются в загрузчике или ядре.

Boot1.efi загружает loader.efi с первой файловой системы freebsd-ufs, которую он находит, даже если она располагается на другом диске.

Boot1.efi не может загрузить loader.efi с файловой системы zfs. В результате UEFI не поддерживает расположение файловой системы root в конфигурации zfs.”

Все, приплыли.

Поясню глубину фэйла. Мы хотели просто накатывать втихую FreeBSD на любую систему, имея только загрузочный раздел, своп и zfs, а UEFI требует наличие msdos раздела (причем, не все UEFI могут прочитать msdos раздел, созданный FreeBSD, разработчики рекомендуют использовать Fat16 или даже Fat12), на котором будет лежать загрузчик. К тому же загрузчик boot1.efi будет искать loader.efi на ufs разделе, таким образом наш zfs будет третьим в зоопарке систем на диске, при этом он не будет загрузочным. И последнее, если мы так настроим диск, тогда не-EFI системы не смогут загрузиться с этого диска. Таким образом, прежде чем приступить к установке мы должны определиться, будет ли система с обычным BIOS, или EFI. От этого зависит способ нарезки диска и порядок установки. Мы не сможем использовать один универсальный линейный способ, подходящий для разных систем. Добавляет неразберихи то, различные производители материнских плат используют отличающиеся способы реализации efi загрузчиков. В общем, пока нет сколько-нибудь универсального и надежного способа установки FreeBSD на GPT раздел. Если мы имеем на диске MBR, тогда даже EFI системы используют эмуляцию BIOS и грузят ось «по старинке» (либо автоматически, либо указваем руками параметр Legacy в настройках EFI). Некоторые материнские платы пользователю указать даже для GPT разделов Legacy режим загрузки. Тогда система, установленная по схеме из предыдущей главы, запустится нормально.

Итог: для реализации красивой и универсальной установки нам надо подождать, пока выйдут подходящие версии системы, а пока мы можем ставить FreeBSD только на Legacy BIOS.