Вы здесь

[РЕШЕНО] INITRD-строение - нужна помощь с udev в busybox

Добрый день!
У меня есть рабочая система, соптимизированая и с нужным софтом. Хочу избавиться от лишнего на винте, может даже разместить систему на флешке (cf). Читал, что портежам можно задать собрать пакет(ы) в определенный каталог. Разумно ли это использовать? Если я, например, сделаю emerge -e system && emerge -e world в определенный каталог, скопировать туда /boot, чего там еще понадобится? или я не правильным путем направляюсь, и просто нужно удалить distfiles?

1. Создаю на новом винчестере нужные разделы и монтирую их куда-нибудь во временный каталог.
2. Копирую всё содержимое исходной системы в этот каталог, исключая (просто создаю эти каталоги пустыми):
- /dev
- /proc
- /sys
- /mnt
- /media
- /usr/portage/distfiles
- /usr/portage/packages (если есть)
- /var/tmp/ccache (и, возможно, прочие каталоги в /var/tmp
- возможно, что-то ненужное в /var/log
Распаковываю в /dev содержимое аналогичного каталога в stage3.
Устанавливаю загрузчик в новый /boot, редактирую /etc/fstab.
Вроде бы всё.

Цитата:
Распаковываю в /dev содержимое аналогичного каталога в stage3.

достаточно только console, null, zero. их можно тупа из /dev/ скопировать. остальное udev создаст :)

P.S.: Linux - это красная таблетка :-) Windows - синяя...

Вполне адекватный вариант. Еще можно использовать chroot на флэшку - в некоторых ситуациях так будет даже удобнее. Но вообще если указать ROOT=/mnt/flash emerge blabla - то это аналогично чруту будет даже, с тем исключением, что не нужно разворачивать портаж внутри флэхи (что позволит вырезать большое количество ненужных системных пакетов). Одна проблема - /var/db/ тоже будет взят оттуда, поэтому, чтобы сделать emerge -e @system, вам сначала придется скопировать содержимое (и, возможно, почистить) /var/lib/portage на флэшку.

Всем спасибо. Экспериментирую. Еще вопрос:
Раз уж решил ставить ось на флешку, то хочу защитить флеху от лишних перезаписей. Привычка делать се радикально, и поэтому хочу не просто вытолкать /var в рамдиск, а вообще заставить машину работать из рамдиска. Одна проблема - как это сделать. Читал про GNAP и LiveCD - по-моему немного не то. По сути, вижу задачу примерно так: при загрузке, ось с флехи катается на рамдиск, и после этого машина грузится уже с рамдиска. Интересно, средствами GRUB можно такое сделать?

Мне кажется, это бессмыслено, т.к. обычно при работе идет запись только в /var(немного) и /home все остальное только чтение. Или попробуйте unionfs, я не юзал, но слышал, что с помощью нее можно сделать так: файлы остаются на флэшке, а при попытке записи изменения пишутся на диск в оперативке, а в конце работы можно все сбросить на флэшку.

Спасибо, почитаю про unionfs.
А что касается записи - тут есть еще преимущества - рамдиск, в отличие от флешки, доступен на высокой скорости.
Может есть еще варианты?

Гугл говорит, что нужно смотреть в сторону initrd.

Насколько я знаю, не совсем так. Портежи и прочие зависимости сборки вытяутся по зависимостям. Нужно еще указать SYSROOT=/ чтобы build dependences ставились в основной корень, а то, что нужно в ROOT.

Вобщем, почитал еще, понял, что нужно все-таки использовать метод LiveCD. То есть squashfs образ системы ro и работа в рамдиске. Нашел кучу статей и блогов по построению своего livecd/usb но нигде нет подробного описания какие конфиги можно покрутить чтобы определить что держать в squashfs, а что в ram. Из этого материала вообще не понятно как система в итоге оказывается в ramdisk.
Подскажите кто знает :)

посмотри в сторону catalyst. он собирает LiveCD и где-то было как сделать загрузочную флэшку из LiveCD и syslinux

посмотрите в сторону sysresccd.org - там довольно-таки подробная инструкция как настроить образ под себя с добавлением необходимых программ.

хоть изначально у них используется xfce, но, думаю, не проблема заменить на то, что нравится

что-то добрый я сегодня ....

Для этого служит initrd. В нем находится ядро, минимальный набор программ - mount, cat, chroot etc., и скрипт, которому передает управление ядро после загрузки. Этот скрипт и делает всю работу - монтирует разделы, копирует все что нужно и передает управление дальше.
В инете есть масса информации по этому вопросу.
У меня была такая задача - грузить с flash диска систему удаленного терминала. В терминале стоит VIA Epia mini-ITX c 128mb RAM, ЖК монитор 17" с тачскрином, usb wifi и компортовый сканнер штрихкода. В качестве flash диска использовал Compact Flash 256Mb через переходник на IDE.

Я использовал такой метод - разбил CF на три раздела:
sda1 - с grub, ядром, initrd и var.tar.gz, home.tar.gz на ext2 (/boot) - 10Mb
sda2 - все содержимое /etc на ext2 - 20Mb
sda3 - раздел, где лежит root squashfs - остальное
На sda3 образ squashfs заливаю при помощи dd.

Принцип работы.
Грузится ядро, передает управление в initrd. Там производится несколько действий:
Монтируется sda3 с root squashfs во временный каталог /mnt.
Создаются tmpfs, в них распаковываются var.tar.gz, home.tar.gz и эти tmpfs монтируются /mnt/var и /mnt/home.
Создается tmpfs, туда копируется содержимое sda2 (/etc) и эта tmpfs монтируется в /mnt/etc.
Создается tmpfs и монтируется в /mnt/tmp.
Дальше перемешаем root (chroot в /mnt && pivot_root) и стартуем реальный init из root squashfs.

Таким образом в RAM находятся только /etc, /home, /tmp и /var, а root squashfs работает прямо с CF в режиме только для чтения.
Почему я не использовал unionfs - захотел использовать только штатные средства, без модификации ядра.
Размер root squashfs с установленными xorg, firefox и rdesktop не превышает 130Mb.
Весь процесс создания initrd можно автоматизировать при помощи скрипта.

Для livecd делается все очень похоже. Необходимы только initrd и root squashfs.

MVG написал:
Для этого служит initrd. В нем находится ядро, минимальный набор программ - mount, cat, chroot etc., и скрипт, которому передает управление ядро после загрузки. Этот скрипт и делает всю работу - монтирует разделы, копирует все что нужно и передает управление дальше.

В инете есть масса информации по этому вопросу.
У меня была такая задача - грузить с flash диска систему удаленного терминала. В терминале стоит VIA Epia mini-ITX c 128mb RAM, ЖК монитор 17" с тачскрином, usb wifi и компортовый сканнер штрихкода. В качестве flash диска использовал Compact Flash 256Mb через переходник на IDE.

Хендбук я уже изучил.

MVG написал:
Я использовал такой метод - разбил CF на три раздела:
sda1 - с grub, ядром, initrd и var.tar.gz, home.tar.gz на ext2 (/boot) - 10Mb
sda2 - все содержимое /etc на ext2 - 20Mb
sda3 - раздел, где лежит root squashfs - остальное
На sda3 образ squashfs заливаю при помощи dd.

Принцип работы.
Грузится ядро, передает управление в initrd. Там производится несколько действий:
Монтируется sda3 с root squashfs во временный каталог /mnt.
Создаются tmpfs, в них распаковываются var.tar.gz, home.tar.gz и эти tmpfs монтируются /mnt/var и /mnt/home.
Создается tmpfs, туда копируется содержимое sda2 (/etc) и эта tmpfs монтируется в /mnt/etc.
Создается tmpfs и монтируется в /mnt/tmp.
Дальше перемешаем root (chroot в /mnt && pivot_root) и стартуем реальный init из root squashfs.

Таким образом в RAM находятся только /etc, /home, /tmp и /var, а root squashfs работает прямо с CF в режиме только для чтения.
Почему я не использовал unionfs - захотел использовать только штатные средства, без модификации ядра.

Дада - это мне и надо. Правда, нужна еще возможность командой сохранить изменения, но это легче.

MVG написал:
Весь процесс создания initrd можно автоматизировать при помощи скрипта.

А может след где остался от Ваших действий?
Я вот нагуглил: http://www.iakovlev.org/index.html?p=4697&m=1&l1=3 Упомянаются конструкторы initrd, но нету их в портежах.
man mkinitrd не просветил как наваять баш скрипт, кидающий и монтирующий что нужно, и как заставить его исполняться при загрузке initrd.

Я еще не сильно наследил в сети :)

На самом деле я использую целый набор небольших скриптов. Они помогают мне развернуть базовую систему из stage3, собрать все необходимое, создать initrd, создать root squashfs, и сделать резервную копию системы.

Cкрипт, который создает initrd, называется очень оригинально - build_initrd.sh ;)
В качестве источника, он использует каталог, где развернута собранная система.
Обратите внимание на переменную LIVEDIR. Если LIVEDIR="/mnt/test", то ваша система, для которой вы хотите получить initrd, должна лежать в /mnt/test/source. Это связано с тем, что я выношу некоторые каталоги - /usr/portage, /usr/src ... вне source, чтобы они не попали затем в root squashfs. Так же, у вас должен быть создан каталог /mnt/test/boot. В нем будет лежать результат работы скрипта - готовый initrd.

Собственно сам скрипт:

#!/bin/sh

# Каталог для сборки системы
LIVEDIR="/mnt/test"

# Временный каталог для сборки initrd
INITRD_DIR="/tmp/initrd_temp"

# Размер initrd в Mb
INITRD_SIZE="4"

cd ${LIVEDIR}/boot
dd if=/dev/zero of=initrd bs=1M count=${INITRD_SIZE}
mke2fs -q -F -m0 initrd
mkdir ${INITRD_DIR}
mount -o loop initrd ${INITRD_DIR}
chroot ${LIVEDIR}/source <<- EOF
mkdir /mnt/initrd/
cd /mnt/initrd/
mkdir bin etc dev lib proc temp mnt
touch linuxrc
chmod +x linuxrc
touch etc/mtab
touch etc/fstab
mknod dev/console c 5 1
mknod dev/null c 1 3
mknod dev/sda b 8 0
mknod dev/sda1 b 8 1
mknod dev/sda2 b 8 2
mknod dev/sda3 b 8 3
mknod dev/tty c 5 0
mknod dev/tty0 c 4 0
mknod dev/loop0 b 7 0
cp /bin/cat bin
cp /bin/cp bin
cp /bin/chroot bin
cp /bin/gzip bin
cp /bin/mount bin
cp /bin/mkdir bin
cp /bin/ps bin
cp /bin/sh bin
cp /bin/tar bin
cp /bin/umount bin
cp /sbin/pivot_root bin
cp /lib/ld-linux.* lib
find bin -type f | xargs ldd | grep '/lib/' | awk '{print \$3}' | sort -n | uniq | xargs -i, cp , lib/.
EOF
cp -a ${LIVEDIR}/source/mnt/initrd/* ${INITRD_DIR}
rm -Rf ${LIVEDIR}/source/mnt/initrd
rmdir ${INITRD_DIR}/lost+found

# Создаем linuxrc прямо из скрипта
cat >> ${INITRD_DIR}/linuxrc << EOF
#!/bin/sh

BOOT=/dev/sda1
ETC=/dev/sda2
ROOT=/dev/sda3

# Нам нужен доступ к исполняемым файлам в initrd
export PATH=/bin:/sbin

# Получить командную строку ядра из загрузчика
mount -t proc none /proc
CMDLINE=\`cat /proc/cmdline\`
umount /proc

# монтировать squashed / файловую систему
mount -t squashfs \$ROOT /mnt
echo "[ ok ]   / successfully mounted !"

# распаковать в tmpfs и примонтировать /mnt/var
mount -r \$BOOT /temp
mount -t tmpfs -o size=4M none /mnt/var
cd /mnt/var
tar xzpf /temp/var.tar.gz
umount /temp
echo "[ ok ]   /var successfully extracted !"

# распаковать в tmpfs и примонтировать /mnt/home
mount -r \$BOOT /temp
mount -t tmpfs -o size=10M none /mnt/home
cd /mnt/home
tar xzpf /temp/home.tar.gz
umount /temp
echo "[ ok ]   /home  successfully extracted !"

# скопировать в tmpfs и примонтировать /mnt/etc
mount \$ETC /temp
mount -t tmpfs -o size=4M none /mnt/etc
cp -a /temp/* /mnt/etc
umount /temp
echo "[ ok ]   /etc successfully copied !"

# монтировать tmpfs в /mnt/temp
mount -t tmpfs -o size=4M none  /mnt/tmp
echo "[ ok ]   /tmp successfully mounted !"

# Переместить root и стартовать реальный init
cd /mnt
pivot_root . mnt/temp
exec chroot . sh -c 'umount /mnt/temp; blockdev --flushbufs /dev/ram0; \
  exec /sbin/init \${CMDLINE}' <dev/console >dev/console 2>&1
EOF

umount ${INITRD_DIR}
rm -R ${INITRD_DIR}
cd ${LIVEDIR}/boot/
gzip initrd

Что он делает, понятно из коментариев.
Скорее всего вам понадобится модифицировать этот скрипт для ваших целей.
Обработка ошибок в linuxrc не реализована, поэтому иногда сложно понять, если что то не сработало. Допишу в будущем, возможно.
Если что то непонятно - задавайте вопросы.

Спасибо, вопросы будут :)

Еще раз большое спасибо MVG, который терпеливо отвечал на шквал вопросов в IM.
Итак, возник еще один вопрос - задача, к кторой пока не найду как подступиться.
Есть в initrd программа mount , которая вполне себе работает вот так:
mount /dev/sda1 /mnt
А когда я хочу, чтобы в initrd монтировался роаздел по label:
mount -L label /mnt
то пишет partition not found и kernel panic как следствие.
в нормально занруженной системе команда исполняется и монтирует собственно нужный раздел куда нужно.
Кто разбирается, подскажите пожалуйста куда копать:
1. либо надо найти и добавить в initrd еще либу, чтобы использовать опцию -L, то подскажите как найти эту либу,
2. Может быть на этой стадии загрузки ядра, ядро не видит меток (label)?

1) есть подозрения, что моунт из бузибикса не умеет лабелы - заскриптуйся с blkid (e2fsprogs)
2) посмотри, что там насоздавал mdev ( в стандартном инирд - параметр debug) - может есть смысл перейти на удев ( он давно должен собиратся с uClibc)

Compute:
Bosch M2.8.1 -> custom Bosch M2.8.3 clone from Russia.
Speed about 260 km,Ram 2 pers.,HDD - 70 kg,210 FLOPS ;)

бизибокс я не использовал, руками создавал initrd, скопировал нужные проги из /bin, libы из /lib, init скрипт тоже написан вручную Только что попробовал монтирование по uuid - тоже не хочет

trscod написал:
бизибокс я не использовал, руками создавал initrd, скопировал нужные проги из /bin, libы из /lib, init скрипт тоже написан вручную Только что попробовал монтирование по uuid - тоже не хочет

т.е вручную ?? ты хоть lddtree.sh чекал ?
blkid в инитрд что кажет ?

Compute:
Bosch M2.8.1 -> custom Bosch M2.8.3 clone from Russia.
Speed about 260 km,Ram 2 pers.,HDD - 70 kg,210 FLOPS ;)

slepnoga написал:
может есть смысл перейти на удев ( он давно должен собиратся с uClibc)

Udev - он запускается гораздо позже и не решает мои задачи, к сожалению

trscod написал:
slepnoga написал:
может есть смысл перейти на удев ( он давно должен собиратся с uClibc)

Udev - он запускается гораздо позже и не решает мои задачи, к сожалению

удев/мдеев, балин, тот который в инитрд, а не тот, который в системе
покажи листинг файлов и директорий в твоем инирд

Compute:
Bosch M2.8.1 -> custom Bosch M2.8.3 clone from Russia.
Speed about 260 km,Ram 2 pers.,HDD - 70 kg,210 FLOPS ;)

ls
bin dev etc lib linuxrc loopfs mnt proc sda1 squash sysroot temp
А как туда udev засунуть?

А вообще, есть хорошая дока по initramfs:
http://en.gentoo-wiki.com/wiki/Initramfs
Как-то я ее сразу не нашел.
В принципе, все получилось, но наполовину.
Использую busybox и mdev для определения разделов (флешки). Определяются разделы и метки и монтируются.
Если воткнуть вторую флешку, то первая, бывшая в одиночетсве /dev/sda, становится /dev/sdb и в упор не видится ядром. Вернее ядром то видится до запуска init скрипта initramfs. Создаю ноды для разделов в /dev , но все равно команда mount говорит что такого раздела не существует.
А задача то в этом и заключается, чтобы сколько флешек там небыло воткнуто - грузилось всегда с нужной.
Короче, нагуглил пока что есть в busybox udev. А как его использовать?

trscod написал:
Создаю ноды для разделов в /dev , но все равно команда mount говорит что такого раздела не существует.

Udev не понадобился. man mknod !

Мы сами создаем себе трудности, и мы сами их героически преодолеваем - мы Армянские Комсомольцы.

монтируй по UUID - темя избита и перетерта сто тыщь раз

Compute:
Bosch M2.8.1 -> custom Bosch M2.8.3 clone from Russia.
Speed about 260 km,Ram 2 pers.,HDD - 70 kg,210 FLOPS ;)