Ключевые слова:freebsd, boot, compress, zip, geom, geom_zip, (найти похожие документы)
From: Алексей Кеда (lissyara) <admin@lissyara.su.>
Date: Sun, 16 Feb 2008 17:02:14 +0000 (UTC)
Subject: Использование для загрузки FreeBSD сжатой файловой системы - geom_uzip
Оригинал: http://www.lissyara.su/?id=1359
Данный текст появился из моих развлечений, по работе - надо было
сделать загрузочную флэшку, которая после загрузки задавала пару тупых
вопросов, после чего разбивала диск, разворачивала сервер филиала,
втыкала в его в виндовый домен и меняла все данные в конфигах. Данная
задача трудностей не вызывала, были одни крупные грабли - при
разворачивании и генерации файла fstab, нужно было определить имя
диска с которым работаем. Поэтому, пришлось изгаляться с запихиванием
содержимого флэшки на диск в оперативке. Ну, а в процессе запихивания
родилось пару хороших идей по применению сделанному. Одна из них -
тонкие клиенты - когда-то я такое делал на FreeBSD4.11 - надо было
по работе, ну а теперь для развлечения повторю на 6.2 - просто чтобы
не забыть, что можно и как сделать.
Для начала, читаем man по mdconfig, и следуем последнему
примеру, в этом мане. Делаем файлик состоящий из нулей:
/usr/home/lissyara/>dd if=/dev/zero of=mfs_root.md bs=1m count=512
512+0 records in
512+0 records out
536870912 bytes transferred in 14.831406 secs (36198248 bytes/sec)
/usr/home/lissyara/>
Делаем виртуальный диск:
/usr/home/lissyara/>mdconfig -a -t vnode -f mfs_root.md -u 4
mdconfig: open(/dev/mdctl): Permission denied
/usr/home/lissyara/>su
ussr% mdconfig -a -t vnode -f mfs_root.md -u 4
Создаём директорию, куда будем монтировать диск:
ussr% mkdir mfs
Записываем на диск метку:
ussr% bsdlabel -w md4 auto
Создаём файловую систему:
ussr% newfs md4a
/dev/md4a: 512.0MB (1048560 sectors) block size 16384, fragment size 2048
using 4 cylinder groups of 128.00MB, 8192 blks, 16384 inodes.
super-block backups (for fsck -b #) at:
160, 262304, 524448, 786592
Монтируем:
ussr% mount /dev/md4a /usr/home/lissyara/mfs
ussr% df -h | grep md
/dev/md4a 496M 4.0K 456M 0% /usr/home/lissyara/mfs
ussr%
Собираем и устанавливаем мир, с указанием директории назначения -
наш диск в памяти:
[cpde=shell]make world DESTDIR=/usr/home/lissyara/mfs && \
? cd /usr/src/etc && make distribution DESTDIR=/usr/home/lissyara/mfs
[/code] После установки, смотрим чё получилось:
ussr% df -h | grep md
/dev/md4a 496M 150M 307M 33% /usr/home
/lissyara/mfs
ussr%
Занято 150 мегов. Неплохо - мы имеем полноценную систему, но ещё
надо установить софт - иксы и прочия. Собирать на этом диске - нету
никакого желания и времени, поэтому воспользуюсь софтом установленным
на моей машине - благо, у меня всё что необходимо уже установлено. Для
этого, создаём директорию, и в ней сохраняем все пакеты:
ussr% cd /usr/home/lissyara/
ussr% mkdir pkgs
ussr% cd pkgs
ussr% foreach pkg ( `ls /var/db/pkg/` )
foreach? pkg_create -b $pkg &
foreach? end
Можно идти курить. На моём двухядрёном AMD, с гигом памяти, это
заняло минут 20 (для 600 с копейками установленных пакетов). После
создания всех пакетов, монтируем директорию с ними, в директорию
внутри диска в файле. Для этого, юзаем nullfs:
ussr% mount_nullfs /usr/home/lissyara/pkgs /usr/home/lissyara/mfs/mnt
ussr% df -h | grep lissyara
/dev/md4a 496M 150M 307M 33% /usr/home/lissyara/mfs
/usr/home/lissyara/pkgs 72G 7.0G 59G 11% /usr/home/lissyara/mfs/mnt
ussr%
После чего топаем внутрь диска в файле, как в jail - будем
ставить пакеты:
ussr% jail /usr/home/lissyara/mfs ThinClients 1.1.1.1 /bin/csh
ThinClients#
ThinClients# df -h
Filesystem Size Used Avail Capacity Mounted on
/dev/md4a 496M 150M 307M 33% /
ThinClients# cd /mnt/
ThinClients# ls | wc -l
601
ThinClients#
Ставим пакеты:
ThinClients# pkg_add rdesktop-1.5.0_2.tbz
Running fc-cache to build fontconfig cache...
/usr/local/lib/X11/fonts: caching, 0 fonts, 1 dirs
/usr/local/lib/X11/fonts/local: caching, 0 fonts, 0 dirs
/root/.fonts: skipping, no such directory
/var/db/fontconfig: cleaning cache directory
/root/.fontconfig: not cleaning unwritable cache directory
fc-cache: succeeded
Spamming files in /etc...
==> Removing /usr/X11R6/etc/periodic from periodic setup...
==> Removing /usr/X11R6/man from MANPATH...
==> Removing /usr/X11R6 from rc sequence...
ThinClients#
ThinClients# pkg_add xorg-server-1.2.0_2,1.tbz
ThinClients# pkg_add xorg-drivers-7.2.tbz xorg-apps-7.2.tbz xorg-fonts-7.2.tbz
ThinClients# df -h
Filesystem Size Used Avail Capacity Mounted on
/dev/md4a 496M 259M 197M 57% /
ThinClients# pkg_info | wc -l
270
ThinClients# exit
Мдя... прилично... Однако, попробуем сжать всё это хозяйство, и
посмотрим что будет на выходе. Ждя этого заюзаем утилиту mkuzip -
она позволяет сжимать образы файловых систем, и, в дальнейшем, эти
сжатые образы можно втюхать лоадеру, который их загрузит в память. Ну,
а дальше - ядро будет использовать софт с этого диска. Сжимаем,
предварительно отмонтировав, и отключив диск - при проблемах на
отмонтировании/отключении - можно перезагрузиться:
ussr% umount /usr/home/lissyara/mfs
ussr% mdconfig -d -u 4
ussr% mkuzip -v mfs_root.md
padding data with 40 bytes so that file size is multiple of 512
compressed data to 124328448 bytes, saved 412542464 bytes, 76.84% decrease.
ussr% ls -alh | grep md
-rw-r--r-- 1 lissyara wheel 512M 11 июл 00:11 mfs_root.md
-rwxr-xr-x 1 lissyara wheel 119M 11 июл 19:55 mfs_root.md.uzip
Неплохо. Сжалось вдвое. Хотя, я рассчитывал на лучший результат -
ибо в 128 мегов памяти, и тем более в 64 - ну никак не вписываемся.
Поэтому, пробовать грузиться с этого я даже не стал, а полез изучать
маны - с целью ужать всё что можно и удалить ненужное. Для начала,
изучаем man make.conf, и добавляем в файл /etc/make.conf такие
строки:
# temporary - for thin clients
NO_KERBEROS= YES
NO_WPA_SUPPLICANT_EAPOL= YES
NO_BLUETOOTH= YES
NO_CVS= YES
NO_CXX= YES
NO_DICT= YES
NO_FORTRAN= YES
NO_GDB= YES
NO_GPIB= YES
NO_I4B= YES
NO_IPFILTER= YES
NO_PF= YES
NO_AUDIT= YES
NO_AUTHPF= YES
NO_TOOLCHAIN= YES
NO_INET6= YES
NO_ATM= YES
NO_USB= YES
NO_LPR= YES
NO_ACPI= YES
NO_MAILWRAPPER= YES
NO_MAN= YES
NO_NETCAT= YES
NO_NIS= YES
NO_NLS_CATALOGS= YES
NO_OBJC= YES
NO_OPENSSH= YES
NO_OPENSSL= YES
NO_SENDMAIL= YES
NO_SHAREDOCS= YES
NO_CRYPT= YES
NO_GAMES= YES
NO_INFO= YES
NO_LIBC_R= YES
NO_PROFILE= YES
NO_SHARE= YES
NO_BIND= YES
PPP_NO_NAT= YES
PPP_NO_NETGRAPH= YES
PPP_NO_RADIUS= YES
NO_RCMDS= YES
После чего повторяем набор действий по созданию диска в памяти, и
инсталляции на него системы. Тока диск делаем вдвое меньше:
ussr% dd if=/dev/zero of=/usr/home/lissyara/mfs_root_v2.md bs=1m count=256
256+0 records in
256+0 records out
268435456 bytes transferred in 7.642607 secs (35123546 bytes/sec)
ussr% mdconfig -a -t vnode -f mfs_root_v2.md -u 4
ussr% bsdlabel -w md4 auto
ussr% newfs md4a
/dev/md4a: 256.0MB (524272 sectors) block size 16384, fragment size 2048
using 4 cylinder groups of 64.00MB, 4096 blks, 8192 inodes.
super-block backups (for fsck -b #) at:
160, 131232, 262304, 393376
ussr% mount /dev/md4a /usr/home/lissyara/mfs
ussr%
ussr% df -h | grep md
/dev/md4a 248M 4.0K 228M 0% /usr/home/lissyara/mfs
ussr%
ussr% make world DESTDIR=/usr/home/lissyara/mfs && \
? cd /usr/src/etc && make distribution DESTDIR=/usr/home/lissyara/mfs
......... skipped ..........
ussr% df -h | grep md
/dev/md4a 248M 43M 185M 19% /usr/home/lissyara/mfs
ussr%
Результат неплох - меньше в 3.5 раза, и ещё ничё не пилили руками -
тока штатные средства. Ну а дальше началось интересное, что я уже не
документировал - ручная установка пакетов, доустановка файлов без
которых не запускался rdesktop (NO_CRYPT=yes - оказалась плохая идея
:)) удаление файлов, которые не нужны (почти всё в share и
local/share), ненужных зависимостей и прочего. Честно говоря - сильно
не изгалялся, но на выходе, уже к третьей версии, имел такое:
ussr% df -h | grep md
/dev/md4a 248M 88M 140M 39% /usr/home/lissyara/mfs
После сжатия, соответствено:
ussr% ls -alh mfs_root.md.uzip
-rwxr-xr-x 1 root wheel 42M 13 июл 00:24 mfs_root.md.uzip
ussr%
Осталось, рассмотреть запуск всего этого хозяйства. Вот тут меня
ждали грабли - как загрузить образ, вопросов не возникало - в
/boot/defaults/loader.conf есть примеры, и в моём случае это выглядело
так:
ussr% more boot/loader.conf
# uzip module
geom_uzip_load="YES"
# MFS image load
mfsroot_load="YES"
mfsroot_type="mfs_root"
# file compressed file system
mfsroot_name="/boot/mfs_root.md.uzip"
# other boot options
autoboot_delay="3"
loader_logo="beastie"
Однако, даже определив имя устройства - /dev/md0.uzipa, мне не
удалось его подмонтировать - точка, в fstab, считается спецсимволом.
Экранировать тоже никак не удалось. Финиш...
Вначале я было потерялся, потом вспомнил, что когда перводил
/boot/defaults/loader.conf, видел чё то на эту тему. Оказалось, да
- есть опция:
# where root FS
vfs.root.mountfrom="ufs:md0.uzipa"
С ней, удалось загрузиться с устройства. Однако, тут были новые
грабли - ввиду того, что файловая система доступна только для чтения,
фряха вываливалась в однопользовательский режим. Порывшись в ещё одном
дефолтовом конфигурационном файле - /etc/defaults/rc.conf - нашёл
соответстствующую опцию, и на выходе получил /etc/rc.conf такого
состава:
ussr% more etc/rc.conf
# added by xorg-libraries port
local_startup="/usr/local/etc/rc.d"
#moused_enable="YES"
#moused_port="/dev/ums0"
# filesystems in memory
varmfs="YES"
varsize="4m"
tmpmfs="YES"
tmpsize="2m"
# for root_fs read-only mount
root_rw_mount="NO"
# list network interfaces
# ls /boot/kernel/ | grep if | awk -F '.' '{print $1}' | awk -F '_' '{print $2}'
interface_array="an ar arl ath aue awi axe bce bfe bge \
cdce ce cm cp cs ct cue cx dc de disc \
ed ef el em en ep ex faith fatm fe \
fwip fxp gif gre harp hatm hme ic ie \
ipw iwi ixgb kue le lge lnc my ndis nge \
nve oltr patm pcn ppp ral ray re rl rue \
sbni sbsh sf sis sk sl sn sr ste stf \
stge tap ti tl tun tx txp udav ural vge \
vlan vr vx wb wi xe xl ifoff atmpif nfe"
for simple_iface in ${interface_array}
do
# first
export ifconfig_${simple_iface}0="DHCP"
# second
export ifconfig_${simple_iface}1="DHCP"
done
Про интерфейсы - умнее не придумал :). В дополнение, был написан
простенький стартовый скрипт, такого составу:
ussr% more usr/local/etc/rc.d/startx.sh
#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
export PATH
# moused's
/etc/rc.d/moused forcestart ums0 &
/etc/rc.d/moused forcestart psm0 &
# X
sleep 5 && /usr/local/bin/startx &
ussr%
Ну и создан файлик для указания иксам - чё и с какими параметрами
запускать:
ussr% more root/.xinitrc
exec /usr/local/bin/rdesktop -k en-us -f -b -N -z 77.73.24.66
ussr%
IP вполне реальный - у меня винды нет, поэтому я отсканил
произвольную сеть nmap`om на предмет машин с открытым RDP-портом,
первую попавшуюся и взял :). Далее, на машине с FreeBSD надо расшарить
по NFS диск:
more /etc/exports
# NFS filesystems
/shares/diskless -maproot=root -network 192.168 -mask 255.255.0.0
и настроить DHCP - я использую isc-dhcp3-server-3.0.5_2, получилось
примерно так:
more /usr/local/etc/dhcpd.conf
# main DHCP
subnet 192.168.254.0 netmask 255.255.255.0 {
range 192.168.254.1 192.168.254.199;
option routers 192.168.254.254;
option subnet-mask 255.255.255.0;
# DNS
option netbios-name-servers 192.168.254.254;
option netbios-dd-server 192.168.254.254;
option netbios-node-type 8;
option broadcast-address 192.168.254.255;
option ntp-servers 192.168.254.254;
option root-path "192.168.254.254:/shares/diskless";
next-server 192.168.254.254;
filename "/boot/pxeboot";
option domain-name "lissyara.int.otradno.ru";
option domain-name-servers 192.168.254.254;
}
Ну и всё. Пока, всё. Если надо будет, по работе например, или для
души, то допилю до окончательного варианта - в частности, можно
удалить 2/3 системных приложений, да и портов много лишних получилось
- тоже мона погрохать. Надо допилить скрипт из предыдущей статьи,
и найти как выцепить в уже запускающейся с диска в памяти системе -
откуда она загрузилась - ибо этих данных нигде нет. На эту тему есть
одна идея - надо добавить запрос опции "root-path" в
/etc/dhclient.conf, после чего она появится в
/var/db/dhclient.leases.${interface_name}, откуда её и можно будет
вытащить, распарсив этот файл. Ну а дальше всё просто - монтируем
указанный в ней путь, и с него запускаем скрипты и вытаскиваем
персональные конфиги клиентов - если необходимо.
P.S. Ядро, с лоадером, т.е. всё содержимое /boot - берётся с любой
машины, лучше GENERIC - тупо копируется.