FreeBSD"с нуля"

В этой статье описывается мои по полностью автоматизированная установка преднастроенной компилируемой из исходных текстов, включая компиляцию всех ваших любимых портов и преднастроенной так, что она соответствует вашим представлениям о настоящей системе. Если вы полагаете, что концепция make world является прекрасным подходом, то FreeBSD From Scratch расширяет это понятие до make evenmore

.

1 Введение

Вы когда-либо обновляли вашу систему при помощи make world? Существует одна проблема, возникающая при наличии всего лишь одной системы на диске. Если выполнение цели installworld прерывается на середине, у вас остаётся неработоспособная система, которая может даже не загружаться. Либо цель installworld отрабатывает нормально, а новое ядро не загружается. Тогда наступает момент для поиска Fixit CD и резервных копий, которые вы делали полгода назад.

Я исповедую подход ``сотрите данные на дисках при обновлении систем''. Удаление дисков, и даже разделов, обеспечивает вам то, что нигде не остаётся никаких частей старого, то, о чём не заботятся большее число процедур обновления. Однако очистка разделов означает, что вам нужно перекомпилировать/переустановить все ваши порты и пакаджи, а также проделать все тонкие процедуры настройки. Если вы думаете, что эта задача тоже должна быть автоматизирована, то читайте дальше.

2 Почему мне (не) нужна FreeBSD From Scratch?

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

Проблема с утилитой sysinstall заключается в том, что она несколько ограничена в том, что, куда и как может устанавливать.

· Обычно она использовалась для установки уже откомпилированных дистрибутивных наборов и пакаджей с некоторого носителя (CD, DVD, FTP). Она не может устанавливать результат выполнения make buildworld.

· Она не может устанавливать вторую систему в некоторый каталог уже работающей системы.

· Она не может выполнять установку в разделы Vinum.

· Она не может строить порты, а лишь устанавливать уже откомпилированные пакаджи.

· Создание скриптов или выполнение нестандартных действий после установки затруднено.

· И последним, но одним из самых важных факторов, является полуофициальное прекращение дальнейшей поддержки sysinstall.

Хорошо известный способ полного построения и установки системы, описанный в Руководстве, по умолчанию замещает существующую систему. При этом сохраняются только модули и ядро. Системные бинарные файлы, файлы объявлений функций и множество других файлов перезаписываются; уже ненужные файлы остаются и могут преподносить сюрпризы. Если по какой-либо причине обновление завершилось неудачно, бывает трудно и даже невозможно вернуть систему в исходное состояние.

FreeBSD From Scratch решает все эти проблемы. Её стратегия проста: использование работающей системы для установки новой в пустое дерево каталогов, при этом новые разделы монтируются в соответствующие места этого дерева. Многие конфигурационные файлы могут быть скопированы в соответствующее место, а mergemaster(8) сможет позаботиться о тех, что скопировать не удалось. Тонкая настройка новой системы может быть выполнена в старой, вплоть до момента, когда вы сможете выполнить chroot в новую систему. Другими словами, мы проходим через три этапа, при этом каждый шаг представляет собой либо запуск скрипта, либо вызов команды make:

1. stage_1.sh: Создание новой загружаемой системы в пустом каталоге и объединение либо копирование максимально большего количества необходимых файлов. Затем загрузка новой системы.

2. stage_2.sh: Установка требуемых портов.

3. stage_3.mk: Выполнение последующей настройки программного обеспечения, установленного на предыдущем этапе.

После того, как вы воспользуетесь FreeBSD From Scratch для построения второй системы и в течение нескольких недель убедитесь, что она работает удовлетворительно, можете затем использовать её повторно для переустановки исходной системы. С этого момента, как только вы почувствуете необходимость обновления, то просто выберите разделы, которые хотите удалить и выполнить переустановку.

Может быть, вы слышали и даже пробовали использовать систему Linux From Scratch, или LFS для краткости. LFS также определяет, как построить и установить систему с нуля на пустой раздел при помощи работающей системы. LFS делает упор на выяснение роли каждого компонента системы (таких, как ядро, компилятор, устройства, командный процессор, база данных терминальных устройств и так далее) и деталей установки каждого компонента. FreeBSD From Scratch не опускается до такого уровня детализации. Моей целью является проведение автоматизированной и полной установки, а не описание всех кровавых подробностей полного перепостроения системы. В случае, если вы хотите изучить FreeBSD до такого уровня, начните с просмотра /usr/src/Makefile и следуйте действиям, которые выполняет make buildworld.

В подходе, который применяется в FreeBSD From Scratch, имеются свои отрицательные стороны, которые вы должны иметь в виду.

· При компиляции портов на втором этапе систему нельзя использовать в обычном режиме. Если вы имеете дело с сервером, работающим в режиме промышленной эксплуатации, вы должны быть готовы к простою, к которому приводит выполнение второго этапа. Порты, построенные при помощи stage_2.conf.default ниже, требуют примерно 4 часа для построения на системе AMD1800+ со SCSI-дисками, имеющими скорость вращения 10krpm и 1 Гбайтом ОЗУ.

3 Предварительные требования

Для того, чтобы воспользоваться подходом FreeBSD From Scratch, вам нужно иметь:

· Работающую систему FreeBSD с исходными текстами и деревом портов.

· По крайней мере один неиспользуемый раздел, куда будет устанавливаться новая система.

· Опыт работы с mergemaster(8). Или по крайней мере отсутствие страха его использовать.

· Если у вас нет подключения или слабый канал в Internet: дистрибутивные файлы для ваших любимых портов.

· Знание основ написания скриптов на языке командного процессора Bourne, sh(1).

· Наконец, вы должны уметь указывать загрузчику системы на загрузку новой системы, либо интерактивно, либо из конфигурационного файла.

4 Этап первый: Установка системы

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

Скрипт с кодом для первого этапа называется stage_1.sh, и он запускается с единственным аргументом, например

# ./stage_1.sh default

будет считывать свою конфигурацию из файла stage_1.conf.default и записывать протокол в файл stage_1.log.default.

Далее приводится мой файл stage_1.conf.default. Вам необходимо подправить его в различных местах для того, чтобы он соответствовал вашим представлениям об ``идеальной системе''. Я попытался подробно прокомментировать те места, которые вы должны исправлять. Конфигурационный скрипт должен предоставлять четыре функции для оболочки, create_file_systems, create_etc_fstab, copy_files и all_remaining_customization (в случае, если это имеет смысл: именно в такой последовательности они будут вызываться из stage_1.sh).

Следует внимательно отнестись к следующим моментам:

· Разбиение разделов.

Я не являюсь сторонником наличия одного большого раздела для всей системы. Мои системы, как правило, имеют по крайней мере по одному разделу для /, /usr и /var с каталогом /tmp, образованным символической ссылкой в /var/tmp. Вдобавок я использую файловые системы в режиме совместного доступа к /home (домашние каталоги пользователей), /home/ncvs (копия CVS-хранилища FreeBSD), /usr/ports (дерево портов), /src (различные выгруженные из хранилища деревья исходных текстов) и /share (остальные совместно используемые данные, резервные копии которых не нужны, например, спул сервера телеконференций).

· Новые возможности.

Это то, что вы хотите иметь сразу после загрузки новой системы и даже до запуска второго этапа. Причина отказа от простой установки всех моих любимых портов на первом этапе заключается в том, что теоретически и практически существуют проблемы начальной загрузки и целостности: на первом этапе работает ваше старое ядро, однако в chroot-окружении содержится новые двоичные файлы программ и файлы объявлений. Если новая система, к примеру, поддерживает новый системный вызов (согласно её заголовочным файлам), некоторый скрипт конфигурации может попытаться использовать его и завершить работу аварийно, потому что работает под старым ядром. Я наблюдал и другие проблемы при попытке построения порта lang/perl5.

Перед тем, как запускать stage_1.sh, убедитесь, что выполнили обычные действия при подготовке к make installworld installkernel, типа:

· отредактировали конфигурационный файл вашего ядра

· успешно выполнили make buildworld

· успешно выполнили make buildkernel KERNCONF=whatever

Когда вы запускаете stage_1.sh первый раз, и конфигурационный файл, скопированный с работающей системы в новую, является устаревшим по сравнению с тем, что находится в каталоге /usr/src, mergemaster будет запрашивать вас на отработку этой ситуации. Я рекомендую переносить изменения. Если вам надоело отвечать на запросы, вы можете просто обновить файлы в вашей работающей системе за раз (Если только это вам подходит. Скорее всего, вам не нужно это делать, если одна из ваших систем работает под управлением -STABLE, а другая с -CURRENT. Изменения могут оказаться несовместимыми). Последующие вызовы утилиты mergemaster обнаружат, что RCS-идентификаторы версий соответствуют тем, что находятся в /usr/src, и пропустят файл.

Скрипт stage_1.sh остановится на первой команде, которая завершится неудачно (возвратит ненулевой код завершения) из-за set -e, так что вы не пропустите ошибки. Он также остановится, если вы используете отмену значения переменной окружения, как правило, из-за опечатки. Вы должны исправить все ошибки в вашей версии stage_1.conf.default перед тем, как продолжить работу.

В скрипте stage_1.sh мы вызываем mergemaster. Даже если никаким файлам объединение не требуется, он выведет сообщение и в конце сделает запрос

*** Comparison complete

Do you wish to delete what is left of /var/tmp/temproot.stage1? [no] no

Пожалуйста, ответьте no или просто нажмите Enter. Причина в том, что mergemaster оставит несколько файлов нулевой длины в каталоге /var/tmp/temproot.stage1, которые позже будут скопированы в новую систему (если их здесь уже нет).

После этого будет выдан список установленных файлов при помощи утилиты постраничного вывода, по умолчанию это more(1), может быть less(1):

*** You chose the automatic install option for files that did not

exist on your system. The following were installed for you:

/newroot/etc/defaults/rc.conf

...

/newroot/COPYRIGHT

(END)

Нажмите q для того, чтобы прекратить просмотр. Затем вы будете проинформированы о login.conf:

*** You installed a login.conf file, so make sure that you run

'/usr/bin/cap_mkdb /newroot/etc/login.conf'

to rebuild your login.conf database

Would you like to run it now? y or n [n]

Ответ не имеет значения, так как мы будем запускать cap_mkdb(1) в любом случае.

Вот авторский файл stage_1.conf.default, который вы должны потом модифицировать. В комментариях даётся достаточно информации о том, что необходимо изменить.

Warning: Пожалуйста, обратите на команды newfs(8). Хотя вы не можете создавать новые файловые системы на смонтированных разделах, скрипт успешно удалит все несмонтированные разделы /dev/da0s1a, /dev/da0s1e и /dev/da2s1e. Этого может оказаться достаточным, чтобы испортить вам день, так что подправьте имена устройств.

# This file: stage_1.conf.default, sourced by stage_1.sh.

#

# $Id: stage_1.conf.default,v 1.2 2004/01/03 13:55:06 toor Exp toor $

# $FreeBSD: doc/en_US.ISO8859-1/articles/fbsd-from-scratch/stage_1.conf.default,v 1.2 2004/01/21 19:39:26 schweikh Exp $

# Root mount point where you create the new system. Because it is only

# used as a mount point, no space will be used on that file system as all

# files are of course written to the mounted file system(s).

DESTDIR="/newroot"

# Where your src tree is.

SRC="/usr/src"

# Your kernel config name as from make buildkernel KERNCONF=...

KERNCONF="HAL9000"

# Available time zones are those under /usr/share/zoneinfo.

TIMEZONE="Europe/Berlin"

#

# The create_file_systems function must create the mountpoints under

# DESTDIR, create the file systems, and then mount them under DESTDIR.

#

create_file_systems () {

# The new root file system. Mandatory.

# Change DEVICE names or risk foot shooting.

# You must use newfs -O 1 for the root fs if you want to boot it from grub.

DEVICE=/dev/da0s1a

mkdir -m 755 -p ${DESTDIR}

chown root:wheel ${DESTDIR}

newfs -U -O 1 ${DEVICE}

mount -o noatime ${DEVICE} ${DESTDIR}

# Additional file systems and initial mount points. Optional.

DEVICE=/dev/da0s1e

mkdir -m 755 -p ${DESTDIR}/var

chown root:wheel ${DESTDIR}/var

newfs -U ${DEVICE}

mount -o noatime ${DEVICE} ${DESTDIR}/var

DEVICE=/dev/da2s1e

mkdir -m 755 -p ${DESTDIR}/usr

chown root:wheel ${DESTDIR}/usr

newfs -U ${DEVICE}

mount -o noatime ${DEVICE} ${DESTDIR}/usr

}

#

# The create_etc_fstab function must create an fstab matching the

# file systems created in create_file_systems.

#

create_etc_fstab () {

cat <<EOF >${DESTDIR}/etc/fstab

# Device Mountpoint FStype Options Dump Pass#

/dev/da0s1b none swap sw 0 0

/dev/da1s2b none swap sw 0 0

/dev/da2s2b none swap sw 0 0

/dev/da3s2b none swap sw 0 0

/dev/da0s1a / ufs rw,noatime 1 1

/dev/da0s1e /var ufs rw,noatime 1 1

/dev/da2s1e /usr ufs rw,noatime 1 1

/dev/vinum/Share /share ufs rw,noatime 0 2

/dev/vinum/home /home ufs rw,noatime 0 2

/dev/vinum/ncvs /home/ncvs ufs rw,noatime 0 2

/dev/vinum/ports /usr/ports ufs rw,noatime 0 2

/dev/ad0s1 /2k ntfs ro,noauto 0 0

/dev/ad0s6 /linux ext2fs ro,noauto 0 0

#

/dev/cd0 /cdrom cd9660 ro,noauto 0 0

/dev/cd1 /dvd cd9660 ro,noauto 0 0

proc /proc procfs rw 0 0

linproc /compat/linux/proc linprocfs rw 0 0

EOF

chmod 644 ${DESTDIR}/etc/fstab

chown root:wheel ${DESTDIR}/etc/fstab

}

#

# The copy_files function is used to copy files before mergemaster is run.

#

copy_files () {

# Add or remove from this list at your discretion. Mostly mandatory.

for f in

/.profile

/etc/group

/etc/hosts

/etc/inetd.conf

/etc/ipfw.conf

/etc/make.conf

/etc/master.passwd

/etc/nsswitch.conf

/etc/ntp.conf

/etc/printcap

/etc/profile

/etc/rc.conf

/etc/resolv.conf

/etc/start_if.xl0

/etc/ttys

/etc/ppp/*

/etc/mail/aliases

/etc/mail/aliases.db

/etc/mail/hal9000.mc

/etc/mail/service.switch

/etc/ssh/*key*

/etc/ssh/*_config

/etc/X11/XF86Config-4

/var/cron/tabs/root

/var/files

/root/.profile

/boot/splash.bmp

/boot/loader.conf

/boot/device.hints ; do

cp -p ${f} ${DESTDIR}${f}

done

}

#

# Everything else you want to tune in the new system.

# NOTE: Do not install too many binaries here. With the old system running and

# the new binaries and headers installed you are likely to run into bootstrap

# problems. Ports should be compiled after you have booted in the new system.

#

all_remaining_customization () {

# Without the compat symlink the linux_base files end up on the root fs:

cd ${DESTDIR}

mkdir -m 755 usr/compat; chown root:wheel usr/compat; ln -s usr/compat

mkdir -m 755 usr/compat/linux; chown root:wheel usr/compat/linux

mkdir -m 555 usr/compat/linux/proc; chown root:wheel usr/compat/linux/proc

mkdir -m 755 boot/grub; chown root:wheel boot/grub

mkdir -m 755 linux 2k; chown root:wheel linux 2k

mkdir -m 755 src; chown root:wheel src

mkdir -m 755 share; chown root:wheel share

mkdir -m 755 dvd cdrom; chown root:wheel dvd cdrom

mkdir -m 755 home; chown root:wheel home

mkdir -m 755 usr/ports; chown root:wheel usr/ports

# My personal preference is to symlink tmp -> var/tmp. Optional.

cd ${DESTDIR}; rmdir tmp; ln -s var/tmp

# Make spooldirs for the printers in my /etc/printcap.

cd ${DESTDIR}/var/spool/output/lpd; mkdir -p as od ev te lp da

touch ${DESTDIR}/var/log/lpd-errs

# If you do not have /home on a shared partition, you may want to copy it:

# mkdir -p ${DESTDIR}/home

# cd /home; tar cf - . | (cd ${DESTDIR}/home; tar xpvf -)

case ${REVISION} in

4.*)

# 4.x without devfs: create non-standard devices to match your hardware.

cd ${DESTDIR}/dev

./MAKEDEV all

./MAKEDEV da0 da0s1h da0s2h da0s3h da0s4h

./MAKEDEV da1 da1s1h da1s2h da1s3h da1s4h

./MAKEDEV da2 da2s1h da2s2h da2s3h da2s4h

./MAKEDEV da3 da3s1h da3s2h da3s3h da3s4h

./MAKEDEV bktr0 cd1

if test -d /dev/vinum; then

# 'vinum makedev' can only create devices in /dev, thus use cpio.

cd /dev; find vinum -print | cpio -pv ${DESTDIR}/dev

fi

# Make the floppy group wheel writable.

chown root:wheel ${DESTDIR}/dev/fd0*

chmod g+w ${DESTDIR}/dev/fd0*

;;

5.*)

# Make the floppy group wheel writable.

printf '%s ' 'own fd0 root:wheel' >> ${DESTDIR}/etc/devfs.conf

printf '%s ' 'perm fd0 0660' >> ${DESTDIR}/etc/devfs.conf

;;

*)

printf '%s ' "REVISION ${REVISION} not supported"

exit 1

;;

esac

}

# vim: tabstop=2:expandtab:shiftwidth=2:syntax=sh:

# EOF $RCSfile: stage_1.conf.default,v $

Сгрузите stage_1.conf.default.

При работе этот скрипт устанавливает систему, которая при загрузке имеет:

· Унаследованные списки пользователей и групп.

· Подключение к Internet по Ethernet и PPP с использованием межсетевого экрана.

· Правильный временной пояс и NTP.

· Другие более мелкие конфигурационные параметры, например, /etc/ttys и inetd.

Другие функции готовы к настройке, но не будут работать, пока не будет завершён второй этап. Например, мы скопировали файлы для настройки печати и X11. Однако для печати, скорее всего, необходимы приложения, отсутствующие в базовом комплекте системы. X11 не будет работать, пока мы не откомпилируем сервер, библиотеки и программы.

5 Этап второй: Установка портов

Note: На этом этапе вместо компиляции портов возможна также установка (уже откомпилированных) пакаджей. В этом случае stage_2.sh будет представлять собой не более, чем перечень команд pkg_add. Я надеюсь, что вы сумеете написать такой скрипт. Здесь мы сосредоточимся на более гибком и традиционном способе с использованием портов.

Следующий скрипт stage_2.sh показывает, как я устанавливаю мои любимые порты. Он может быть запущен любое количество раз и будет пропускать все порты, которые уже установлены. Он поддерживает dryrun-параметр (-n) для только показа того, что будет выполнено. Вы запускаете его точно также, как stage_1.sh, с только одним аргументом, указывающим на конфигурационный файл, к примеру

# ./stage_2.sh default

который будет считывать перечень портов из stage_2.conf.default.

Список портов состоит из строчек с двумя или большим количеством слов, разделённых пробелами: категория и порт, за которыми опционально следует команда установки, которая будет компилировать и устанавливать порт (по умолчанию: make install). Пустые строки и строки, начинающиеся с символа #, игнорируются. В большинстве случаев в них указывается только название категории и порт. Однако некоторые порты могут быть тонко настроены при помощи указания make-переменных, к примеру:

www mozilla make WITHOUT_MAILNEWS=yes WITHOUT_CHATZILLA=yes install

mail procmail make BATCH=yes install

На самом деле вы можете указать некоторые команды оболочки, так что не ограничены простыми вызовами make:

java linux-sun-jdk13 yes | make install

news inn-stable CONFIGURE_ARGS="--enable-uucp-rnews --enable-setgid-inews" make install

Заметьте, что строка для news/inn-stable является примером одновременно задания переменной оболочки CONFIGURE_ARGS. Файл Makefile порта будет использовать это как начальное значение и определит некоторые другие необходимые аргументы. Разница в задании make-переменных в командной строке по команде

news inn-stable make CONFIGURE_ARGS="--enable-uucp-rnews --enable-setgid-inews" install

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

Убедитесь в том, что ваши порты не используют интерактивный режим установки, то есть не должны пытаться читать со стандартного устройства ввода ничего кроме того, что вы им подаёте на вход. Если это всё же происходит, то они будут считывать последующие строки из вашего перечня портов, описываемого в этом документе, и будут работать некорректно. Если скрипт stage_2.sh неожиданно пропустил порт или прекратил работу, причина может быть в этом.

Ниже приводится stage_2.conf.default. Для каждого установленного им порта создаётся файл протокола LOGDIR/category+port.

# vim: syntax=sh

# $Id: stage_2.conf.default,v 1.1 2004/01/03 14:07:53 toor Exp toor $

# $FreeBSD: doc/en_US.ISO8859-1/articles/fbsd-from-scratch/stage_2.conf.default,v 1.2 2004/01/21 19:39:26 schweikh Exp $

shells zsh

lang perl5 make install; use.perl port

archivers unzip

archivers zip

security sudo

x11-servers XFree86-4-Server

x11 wrapper

x11 XFree86-4-clients

x11 XFree86-4-documents

x11-fonts XFree86-4-font75dpi

x11-fonts XFree86-4-font100dpi

x11-fonts XFree86-4-fontScalable

x11-fonts urwfonts

x11-fonts webfonts make WITH_NETSCAPE_ALIASES=yes install

x11-toolkits open-motif

x11-wm ctwm

security openssh-askpass

astro xplanet

astro xephem

editors vim

print ghostscript-gnu make A4=yes BATCH=yes install

print psutils-a4

print a2ps-a4

print gv

print acroread5

print transfig

print teTeX

# NOTE: jdk14 needs linprocfs(5) mounted or it will hang indefinitely.

java linux-sun-jdk14 mount -a linproc; yes | make install

java jdk14 mount -a linproc; make -DNODEBUG install

www apache2

www weblint

www amaya

www mozilla-firebird

www mozilla make WITHOUT_MAILNEWS=yes WITHOUT_COMPOSER=yes WITHOUT_LDAP=yes WITHOUT_CHATZILLA=yes WITHOUT_XMLTERM=yes install

www checkbot

www privoxy

graphics xfig

graphics xv

multimedia xawtv

graphics graphviz

lang expect

lang gawk

lang TenDRA unset MAKEOBJDIRPREFIX; make install

news tin

net freebsd-uucp

net cvsup-without-gui

net pathchar make NO_CHECKSUM=yes install

net smokeping

ftp wget

ftp ncftp3

textproc ispell

german ispell-neu

german ispell-alt

textproc docproj make JADETEX=no HAVE_MOTIF=yes install

sysutils samefile

sysutils pstree

sysutils mkisofs

sysutils cdrtools

#sysutils grub currently (0.93) marked BROKEN

devel ddd

devel gindent

devel ctags

devel ElectricFence

devel strace

mail procmail make BATCH=yes install

mail metamail

mail mutt-devel

emulators mtools

sysutils portupgrade

news inn-stable CONFIGURE_ARGS="--enable-uucp-rnews --enable-setgid-inews" make install

misc figlet-fonts

textproc gmat

security gpa

mail spamoracle

multimedia mplayer make WITHOUT_RUNTIME_CPUDETECTION=yes WITH_GUI=yes BATCH=yes install

multimedia mplayer-fonts

audio wavplay

Сгрузите stage_2.conf.default.

6 Этап третий

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

Я решил реализовать третий этап в виде файла Makefile, потому что это позволяет легко выбирать то, что вы хотите конфигурировать, следующим простым вызовом:

# make -f stage_3.mk target

Как и в случае с stage_2.sh, убедитесь, что файл stage_3.mk после загрузки новой системы есть в наличии, поместив его на совместно используемый раздел либо скопировав его куда-нибудь в новую систему.

7 Ограничения

Автоматизированная установка порта может оказаться затруднена, если он является интерактивным и не поддерживает команду make BATCH=YES install. Для нескольких портов интерактивность означает не более, чем ввод yes в ответ на вопрос о принятии некоторого лицензионного соглашения. Если такой ввод считывается со стандартного устройства ввода, мы просто направляем соответствующие ответы на вход установочной команды (обычно make install; именно так я работал с java/linux-sun-jdk14 в stage_2.conf.default).

Такой подход, например, не работает с editors/staroffice52, который требует работы X11. Процедура установки включает достаточно большое количество нажатий мыши и набор, так что она не может быть автоматизирована так, как другие порты. Однако для меня сработал следующий трюк: сначала я создал пакадж staroffice на старой системе при помощи команды

# cd /usr/ports/editors/staroffice52

# make package

===> Building package for staroffice-5.2_1

Creating package /usr/ports/editors/staroffice52/staroffice-5.2_1.tbz

Registering depends:.

Creating bzip'd tar ball in '/usr/ports/editors/staroffice52/staroffice-5.2_1.tbz'

и на втором этапе я просто использовал следующее:

# pkg_add /usr/ports/editors/staroffice52/staroffice-5.2_1.tbz

Вы должны также принять во внимание вопросы обновления конфигурационных файлов. Вообще говоря, вы не знаете, когда и сменился ли вообще формат или содержимое конфигурационного файла. В файл /etc/group может быть добавлена новая группа, или в /etc/passwd может добавиться дополнительное поле. Всё это уже происходило в прошлом. Простое копирование конфигурационного файла из старой в новую систему может в большинстве случаев оказаться достаточным, но в этих случаях это не так. Если вы обновляете систему каноническим способом (путём перезаписывания старых файлов), вы должны использовать утилиту mergemaster для работы с изменениями, если вы хотите эффективно объединить вашу локальные настройки с потенциально новыми возможностями. К сожалению, mergemaster работает только с файлами базового комплекта системы, а не с любыми файлами, устанавливаемыми портами. Похоже, что стороннее программное обеспечение специально проектируется для того, чтобы я не дремал, и меняет конфигурационные файлы по два раза в месяц. Всё, что вы можете здесь сделать, это быть предупреждёнными, особенно при изменении старшего номера версии. В прошлом я переписывал или перенастраивал файлы для Web-серверов, серверов телеконференций и программ для их чтения. Любое активно разрабатываемое программное обеспечение является первым кандидатом на получение проблем с конфигурационными файлами.

Я использовал систему FreeBSD From Scratch несколько раз для обновления 5-CURRENT до 5-CURRENT, то есть я никогда не пытался установить 5-CURRENT из системы 4-STABLE и наоборот. Из-за количества изменений между релизами с разными старшими номерами я ожидаю, что этот процесс будет несколько более сложным. Использование FreeBSD From Scratch для обновления внутри 4-STABLE должно проходить безболезненно (хотя я ещё этого не пробовал делать.) Пользователи ветки 4-STABLE могут иметь в виду следующее:

Note: Если вы не используете файловую систему устройств, devfs(5), то можете создать устройства для некоторого вашего оборудования командой MAKEDEV(8) в процессе all_remaining_customization.

8 Файлы

Вот три файла, которые вам нужны кроме тех конфигурационных, что уже показаны выше.

Это скрипт stage_1.sh, который вы не должны модифицировать.

#!/bin/sh

#

# stage_1.sh - FreeBSD From Scratch, Stage 1: System Installation.

# Usage: ./stage_1.sh profile

# will read ./stage_1.conf.profile

# and write ./stage_1.log.profile

#

# Author: Jens Schweikhardt

# $Id: stage_1.sh,v 1.7 2004/01/03 13:50:41 toor Exp toor $

# $FreeBSD: doc/en_US.ISO8859-1/articles/fbsd-from-scratch/stage_1.sh,v 1.4 2004/01/21 19:39:26 schweikh Exp $

PATH=/bin:/usr/bin:/sbin:/usr/sbin

# Prerequisites:

#

# a) Successfully completed "make buildworld" and "make buildkernel"

# b) Unused partitions (at least one for the root fs, probably more for

# the new /usr and /var, to your liking.)

# c) A customized stage_1.conf.profile file.

if test $# -ne 1; then

echo "usage: stage_1.sh profile" 1>&2

exit 1

fi

# ---------------------------------------------------------------------------- #

# Step 1: Create an empty directory tree below $DESTDIR.

# ---------------------------------------------------------------------------- #

step_one () {

create_file_systems

# Now create all the other directories. Mandatory.

cd ${SRC}/etc; make distrib-dirs DESTDIR=${DESTDIR}

}

# ---------------------------------------------------------------------------- #

# Step 2: Fill the empty /etc directory tree and put a few files in /.

# ---------------------------------------------------------------------------- #

step_two () {

copy_files

# Delete mergemaster's temproot, if any.

TEMPROOT=/var/tmp/temproot.stage1

if test -d ${TEMPROOT}; then

chflags -R 0 ${TEMPROOT}

rm -rf ${TEMPROOT}

fi

export MAKEDEVPATH="/bin:/sbin:/usr/bin"

mergemaster -i -m ${SRC}/etc -t ${TEMPROOT} -D ${DESTDIR}

cap_mkdb ${DESTDIR}/etc/login.conf

pwd_mkdb -d ${DESTDIR}/etc -p ${DESTDIR}/etc/master.passwd

# Mergemaster does not create empty files, e.g. in /var/log. Do so now,

# but do not clobber files that may have been copied with copy_files.

cd ${TEMPROOT}

find . -type f | sed 's,^./,,' |

while read f; do

if test -r ${DESTDIR}/${f}; then

echo "${DESTDIR}/${f} already exists; not copied"

else

echo "Creating empty ${DESTDIR}/${f}"

cp -p ${f} ${DESTDIR}/${f}

fi

done

chflags -R 0 ${TEMPROOT}

rm -rf ${TEMPROOT}

}

# ---------------------------------------------------------------------------- #

# Step 3: Install world.

# ---------------------------------------------------------------------------- #

step_three () {

cd ${SRC}

make installworld DESTDIR=${DESTDIR}

# Install additional compatibility libraries (optional). Use this if you

# have programs dynamically linked against libc.so.4, i.e. if you see

# /usr/libexec/ld-elf.so.1: Shared object "libc.so.4" not found

cd lib/compat/compat4x.i386

make all install DESTDIR=${DESTDIR}

}

# ---------------------------------------------------------------------------- #

# Step 4: Install kernel and modules.

# ---------------------------------------------------------------------------- #

step_four () {

cd ${SRC}

# The loader.conf and device.hints are required by the installkernel target.

# If you have not copied them in Step 2, cp them as shown in the next 2 lines.

# cp sys/boot/forth/loader.conf ${DESTDIR}/boot/defaults

# cp sys/i386/conf/GENERIC.hints ${DESTDIR}/boot/device.hints

make installkernel DESTDIR=${DESTDIR} KERNCONF=${KERNCONF}

}

# ---------------------------------------------------------------------------- #

# Step 5: Install /etc/fstab and time zone info.

# ---------------------------------------------------------------------------- #

step_five () {

create_etc_fstab

# Setup time zone info; pretty much mandatory.

cp ${DESTDIR}/usr/share/zoneinfo/${TIMEZONE} ${DESTDIR}/etc/localtime

if test -r /etc/wall_cmos_clock; then

cp -p /etc/wall_cmos_clock ${DESTDIR}/etc/wall_cmos_clock

fi

}

# ---------------------------------------------------------------------------- #

# Step 6: All remaining customization.

# ---------------------------------------------------------------------------- #

step_six () {

all_remaining_customization

}

do_steps () {

echo "PROFILE=${PROFILE}"

echo "DESTDIR=${DESTDIR}"

echo "SRC=${SRC}"

echo "KERNCONF=${KERNCONF}"

echo "TIMEZONE=${TIMEZONE}"

echo "TYPE=${TYPE}"

echo "REVISION=${REVISION}"

echo "BRANCH=${BRANCH}"

echo "RELDATE=${RELDATE}"

step_one

step_two

step_three

step_four

step_five

step_six

}

# ---------------------------------------------------------------------------- #

# The ball starts rolling here.

# ---------------------------------------------------------------------------- #

PROFILE="$1"

set -x -e -u # Stop for any error or use of an undefined variable.

. ./stage_1.conf.${PROFILE}

# Determine a few variables from the sources that were used to make the

# world. The variables can be used to modify actions, e.g. depending on

# whether we install a 4.x or 5.x system. The __FreeBSD_version numbers

# for RELDATE are documented in the Porter's Handbook,

# doc/en_US.ISO8859-1/books/porters-handbook/freebsd-versions.html.

# Scheme is: <major><two digit minor><0 if release branch, otherwise 1>xx

# The result will be something like

#

# TYPE="FreeBSD"

# REVISION="4.9"

# BRANCH="RC" { "CURRENT", "STABLE", "RELEASE" }

# RELDATE="502101"

#

eval $(awk '/^(TYPE|REVISION|BRANCH)=/' ${SRC}/sys/conf/newvers.sh)

RELDATE=$(awk '/^[ ]*#[ ]*define[ ][ ]*__FreeBSD_version[ ]/ {

print $3

}' ${SRC}/sys/sys/param.h)

echo "=> Logging to stage_1.log.${PROFILE}"

do_steps 2>&1 | tee stage_1.log.${PROFILE}

# vim: tabstop=2:expandtab:shiftwidth=2:

# EOF $RCSfile: stage_1.sh,v $

Сгрузите stage_1.sh.

Это скрипт stage_2.sh. Вам может понадобиться изменить переменные в самом начале файла.

#!/bin/sh

#

# stage_2.sh - FreeBSD From Scratch, Stage 2: Ports Installation.

# Usage: ./stage_2.sh [-hnp] configname

#

# Author: Jens Schweikhardt

# $Id: stage_2.sh,v 1.5 2004/01/23 22:09:19 toor Exp toor $

# $FreeBSD: doc/en_US.ISO8859-1/articles/fbsd-from-scratch/stage_2.sh,v 1.4 2004/01/23 22:11:41 schweikh Exp $

DBDIR="/var/db/pkg"

PORTS="/usr/ports"

: ${PACKAGES:=${PORTS}/packages}

LOGDIR="/home/root/setup/ports.log"; mkdir -p ${LOGDIR}

PKG_PATH="/cdrom/packages/All:/dvd/packages/All"

PKG=

MYNAME="$(basename $0)"

usage () {

exec >&2

echo "usage: ${MYNAME} [-hnp] configname"

echo ""

echo " Options:"

echo " -h Print this help text."

echo " -n Dryrun: just show what would be done."

echo " -p Install a precompiled package if one can be found."

echo ""

echo " The config file (stage_2.conf.configname) is a list of"

echo " ports to install with one entry per line. Each line"

echo " consists of two or three space separated fields:"

echo " category, port, and optionally a build command."

echo ""

exit 1

}

# Look for a package in these locations in sequence.

# Returns as soon as the first is found. Result on stdout.

#

# ${PORTS}/${CATEGORY}/${NAME}

# ${PACKAGES}/All

# ${PACKAGES}/${CATEGORY}

# ${PKG_PATH}

#

find_package () {

echo "${PORTS}/${CATEGORY}/${NAME}:${PACKAGES}/All:${PACKAGES}/${CATEGORY}:${PKG_PATH}" |

tr : ' ' |

while read d; do

test -d "${d}" || continue

PKG=$(ls ${d}/${PKGNAME}.* 2>/dev/null)

test $? -eq 0 && echo "${PKG}" && return

done

}

#

# Parse command line arguments.

#

args=`getopt hnp $*`

if test $? != 0; then

usage

fi

set -- $args

DRYRUN=

CHKPKG=

for i; do

case "$i" in

-n) DRYRUN="yes"; shift;;

-p) CHKPKG="yes"; shift;;

--) shift; break;;

*) usage;;

esac

done

if test $# -eq 1; then

DATAFILE="$1"

else

usage

fi

#

# Loop over the ports list.

#

while read CATEGORY NAME CMD; do

case "${CATEGORY}" in

#*) continue;;

'') continue;;

esac

DIR="${PORTS}/${CATEGORY}/${NAME}"

if ! test -d "${DIR}"; then

echo "$DIR does not exist -- ignored"

continue

fi

cd ${DIR}

PKGNAME=`make -V PKGNAME`

if test -n "${CHKPKG}"; then

PKG=$(find_package)

else

PKG=""

fi

if test -d "${DBDIR}/${PKGNAME}"; then

echo "${CATEGORY}/${NAME} already installed as ${PKGNAME}"

continue

fi

LOG="${LOGDIR}/${CATEGORY}+${NAME}"

echo "===> Installing ${CATEGORY}/${NAME}; logging to ${LOG}"

test -n "${CMD}" || CMD="make install < /dev/null"

if test -n "${DRYRUN}"; then

if test -n "${PKG}"; then

echo pkg_add -v ${PKG}

else

echo "${CMD}"

fi

continue

fi

date "++++ Started %v %T +++" > ${LOG}

STARTED=$(date +%s)

(

if test -n "${PKG}"; then

echo "Found package ${PKG}"

pkg_add -v ${PKG}

else

echo "CMD: ${CMD}"

make clean

eval "${CMD}"

make clean # Uncomment if diskspace is tight under ${PORTS}.

fi

) 2>&1 | tee -a ${LOG}

FINISHED=$(date +%s)

DURATION=$(dc -e "${FINISHED} ${STARTED} - p")

date "++++ Finished %v %T after ${DURATION} secs +++" >> ${LOG}

done < stage_2.conf.${DATAFILE}

# vim: tabstop=4:

# EOF $RCSfile: stage_2.sh,v $

Сгрузите stage_2.sh.

Это мой файл stage_3.mk, который даст вам идею о том, как автоматизировать всю повторную конфигурацию.

# stage_3.mk - FreeBSD From Scratch, Stage 3: Ports Post-Configuration.

# Usage: make -f stage_3.mk all (config everything)

# or make -f stage_3.mk target (to just config target)

#

# Author: Jens Schweikhardt

#

# It is a good idea to make sure any target can be made more than

# once without ill effect.

#

# $Id: stage_3.mk,v 1.6 2004/01/10 19:33:07 toor Exp toor $

# $FreeBSD: doc/en_US.ISO8859-1/articles/fbsd-from-scratch/stage_3.mk,v 1.3 2004/01/21 19:39:26 schweikh Exp $

.POSIX:

message:

@echo "Please use one of the following targets:"

@echo "config_apache"

@echo "config_firebird"

@echo "config_inn"

@echo "config_javaplugin"

@echo "config_nullplugin"

@echo "config_privoxy"

@echo "config_sgml"

@echo "config_smokeping"

@echo "config_sudo"

@echo "config_TeX"

@echo "config_tin"

@echo "config_uucp"

@echo "all -- all of the above"

all:

config_apache

config_firebird

config_inn

config_javaplugin

config_nullplugin

config_privoxy

config_sgml

config_smokeping

config_sudo

config_TeX

config_tin

config_uucp

config_apache:

# 1. Modify httpd.conf.

perl -pi

-e 's/^s*ServerAdmin.*/ServerAdmin schweikh@schweikhardt.net/;'

-e 's/^s*Listen.*/Listen 127.0.0.1:80/;'

-e 's/^s*StartServers.*/StartServers 2/;'

-e 's/^s*MinSpareServers.*/MinSpareServers 2/;'

-e 's,/usr/local/www/cgi-bin/,/home/opt/www/cgi-bin/,;'

/usr/local/etc/apache2/httpd.conf

# 2. Restore symlinks to web pages.

cd /usr/local/www/data;

ln -fs /home/schweikh/prj/homepage schweikhardt.net;

ln -fs /home/opt/www/test .

# Test if the httpd.conf has changed.

@if ! cmp -s /usr/local/etc/apache2/httpd.conf httpd.conf; then

echo "ATTENTION: the httpd.conf has changed. Please examine if";

echo "the modifications are still correct. Here is the diff:";

diff -u /usr/local/etc/apache2/httpd.conf httpd.conf;

fi

if test -f /var/run/httpd.pid; then

/usr/local/etc/rc.d/apache2.sh restart;

else

/usr/local/etc/rc.d/apache2.sh start;

fi

config_firebird:

# Make this group wheel writable to allow extensions being installed.

chmod -R g+w /usr/X11R6/lib/firebird/lib/mozilla-1.5/chrome

config_inn:

pw usermod -n news -d /usr/local/news -s /bin/sh

mkdir -p /share/news/spool/outgoing

/share/news/spool/incoming

/share/news/spool/articles

/share/news/spool/overview

/share/news/spool/tmp

/share/news/db

chown -R news:news /share/news

# Give the news system its initial configuration.

cd /home/root/setup;

if test ! -f /share/news/db/active; then

echo "installing /share/news/db/active";

install -C -o news -g news -m 664 active /share/news/db;

fi;

if test ! -f /share/news/db/newsgroups; then

echo "installing /share/news/db/newsgroups";

install -C -o news -g news -m 664 newsgroups /share/news/db;

fi

# The innd.sh that comes with the port is broken, it

# checks for history.pag which does not exist.

cd /home/root/setup;

install -C -o root -g wheel -m 555 innd.sh /usr/local/etc/rc.d

# Configure storage method.

cd /home/root/setup;

printf "%s %s %s %s "

"method tradspool {"

" newsgroups: *"

" class: 0"

"}"

>storage.conf;

install -C -o news -g news -m 664 storage.conf /usr/local/news/etc

# Configure newsfeeds.

printf "%s %s "

"ME:*::"

"shuttle/news2.shuttle.de:!junk,!control:B32768/512,Tf,Wfb:"

>/usr/local/news/etc/newsfeeds

# Configure inn.conf.

perl -pi

-e 's/^#*s*(organization:s*).*/$$1"An Open Pod Bay Door"/;'

-e 's/^#*s*(pathhost:s*).*/$$1hal9000.schweikhardt.net/;'

-e 's/^#*s*(server:).*/$$1 localhost/;'

-e 's/^#*s*(domain:).*/$$1 schweikhardt.net/;'

-e 's/^#*s*(fromhost:).*/$$1 schweikhardt.net/;'

-e 's,^#*s*(moderatormailer:).*,$$1 \%s@moderators.isc.org,;'

-e 's,^#*s*(pathdb:s*).*,$$1/share/news/db,;'

-e 's,/usr/local/news/spool,/share/news/spool,;'

/usr/local/news/etc/inn.conf

# Create empty history, if none there.

# See post-install in /usr/ports/news/inn-stable/Makefile.

cd /share/news/db;

if test ! -f history; then

touch history;

chmod 644 history;

chown news:news history;

su -fm news -c "/usr/local/news/bin/makedbz -i";

for s in dir hash index; do

mv history.n.$${s} history.$${s};

done;

fi

# Configure send-uucp.

echo shuttle:shuttle >/usr/local/news/etc/send-uucp.cf

# Satisfy inncheck:

cd /usr/local/news/etc;

chown news:news *;

chmod 640 control.ctl expire.ctl nntpsend.ctl readers.conf

/usr/local/news/bin/inncheck

# Test if the inn.conf has changed.

@if ! cmp -s /usr/local/news/etc/inn.conf inn.conf; then

echo "ATTENTION: the inn.conf has changed. Please examine if";

echo "the modifications are still correct. Here is the diff:";

diff -u /usr/local/news/etc/inn.conf inn.conf;

fi

if ! test -f /usr/local/news/run/innd.pid; then

/usr/local/etc/rc.d/innd.sh start;

fi

config_javaplugin:

# Mozilla Firebird:

cd /usr/X11R6/lib/firebird/lib/mozilla-1.5/plugins;

ln -fs /usr/local/jdk1.4.2/jre/plugin/i386/ns610/libjavaplugin_oji.so

# Plain Mozilla:

cd /usr/X11R6/lib/mozilla/plugins;

ln -fs /usr/local/jdk1.4.2/jre/plugin/i386/ns610/libjavaplugin_oji.so

# Move the nullplugin out of the way. With a .mozilla/*/*/prefs.js entry of

# user_pref("plugin.display_plugin_downloader_dialog", false);

# this suppresses popup dialogs for unavailable plugins (flash, shockwave, ...)

NULLPLUGINS = /usr/X11R6/lib/mozilla/libnullplugin.so

/usr/X11R6/lib/mozilla/plugins/libnullplugin.so

config_nullplugin:

for p in $(NULLPLUGINS); do

if test -r $$p; then

mv $$p $$p.orig;

fi;

done

config_privoxy:

install -C -o root -g wheel -m 644 conf/privoxy/config

/usr/local/etc/privoxy

install -C -o root -g wheel -m 755 conf/privoxy/privoxy.sh

/usr/local/etc/rc.d

/usr/local/etc/rc.d/privoxy.sh restart

config_sgml:

cp -p /usr/local/share/gmat/sgml/ISO_8879-1986/entities/*

/usr/local/share/sgml/docbook/4.1

config_smokeping:

cp conf/smokeping/config conf/smokeping/basepage.html

/usr/local/etc/smokeping

/usr/local/etc/rc.d/smokeping.sh stop

/usr/local/etc/rc.d/smokeping.sh start

config_sudo:

if ! grep -q schweikh /usr/local/etc/sudoers; then

echo 'schweikh ALL = (ALL) NOPASSWD: ALL' >> /usr/local/etc/sudoers;

fi

config_TeX:

# textproc/docproj advises: to typeset the FreeBSD Handbook with JadeTeX,

# change the following settings to the listed values:

perl -pi

-e 's/^% original texmf.cnf/% texmf.cnf/;'

-e 's/^(hash_extras*=).*/$${1}60000/;'

-e 's/^(pool_sizes*=).*/$${1}1000000/;'

-e 's/^(max_stringss*=).*/$${1}70000/;'

-e 's/^(save_sizes*=).*/$${1}10000/;'

/usr/local/share/texmf/web2c/texmf.cnf

# Test if the texmf.cnf has changed.

@if ! cmp -s /usr/local/share/texmf/web2c/texmf.cnf texmf.cnf; then

echo "ATTENTION: the texmf.cnf has changed. Please examine if";

echo "the modifications are still correct. Here is the diff:";

diff -u /usr/local/share/texmf/web2c/texmf.cnf texmf.cnf;

fi

config_tin:

# Point tin to our files.

printf "%s %s %s "

"activefile=/share/news/db/active"

"newsgroupsfile=/share/news/db/newsgroups"

"spooldir=/share/news/spool/articles"

>/usr/local/etc/tin.defaults

config_uucp:

cd /etc/mail; make install SENDMAIL_MC=/etc/mail/hal9000.mc

# Make the uucp user's shell the correct uucico, so su(1) works.

chpass -s /usr/local/libexec/uucp/uucico uucp

# UUCP expects to find /usr/bin/rnews.

cd /usr/bin; ln -fs ../local/news/bin/rnews .

# Actual UUCP configuration.

echo nodename js2015 > /usr/local/etc/uucp/config

echo shuttle js2015 `cat uucp` > /usr/local/etc/uucp/call

printf 'port tcp type tcp ' > /usr/local/etc/uucp/port

printf "%s %s %s %s %s %s %s "

"call-login *"

"call-password *"

"time any"

"system shuttle"

"address mail.s.shuttle.de"

"commands rmail rnews"

"port tcp"

>/usr/local/etc/uucp/sys

cd /usr/local/etc/uucp; chown uucp:uucp *; chmod o-rwx *

# Trigger uucico after booting.

mkdir -p /usr/local/etc/rc.d; cp uucp.sh /usr/local/etc/rc.d

# vim: tabstop=4:

# EOF $RCSfile: stage_3.mk,v $

Сгрузите stage_3.mk.

Обновлено: 12.03.2015