LINUX.ORG.RU
ФорумAdmin

squashfs as root file system


2

1

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

есть образ squashfs, в котором основная файловая система и есть initrd, в котором я скачиваю этот образ по сети, дальше я его монтирую как loop0, а дальше монтирую для чтения и записи как unionfs, тепорь собственно вопрос, можно ли сделать смонтированную сустему корневой файловой системой.

собственно проблема в том, что смонтированная система это пользовательский процесс, имеющий открытые файлы, если я делаю что-нибудь типа switch_root или pivot_root, то процес просто не найдет файлов в частности не найдет директорию ro и rw и не сможет большпе работать, соответственно после switch_root или pivot_root unionfs больше не сможет работать и вызов switch_root или pivot_root выдадут ошибку.

я пробовал сделать так, чтобы rw.fs и ro.ws оставались в той же директории, что и точка монтирования unionfs, но ничего не получилось.

смотрел на дебиановский скрипт live-boot, там вообе нет ни pivot_root ни switch_root ни chroot. разобраться,как там монтируется squashfs у меня времени не хватило.

в общем, если у кого есть подобный опыт, поделитесь пожалуйста.

★★★

Вот кусок из моего init сценария initramfs, используемого для загрузки системы, в которой корень в squashfs:

...
for i in livemnt/memory livemnt/squashfs livemnt/media
do
  mkdir -p /${i}
done

...

mount $(findfs LABEL=<LABEL>) /livemnt/media -o ro -n || rescue_shell
mount /livemnt/media/system.sq /livemnt/squashfs -o ro -n
mount none -t tmpfs /livemnt/memory -n
mount rootfs -t aufs /mnt/root/ -o udba=reval,br:/livemnt/memory:/livemnt/squashfs

for i in livemnt/memory livemnt/squashfs livemnt/media
do
  mkdir -p /mnt/root/${i}
  mount -n --move /${i} /mnt/root/${i}
done
...
umount /proc
umount /sys

exec switch_root /mnt/root /sbin/init -c /dev/tty1

Для вас имеет практическую ценность 'mount -n --move /${i} /mnt/root/${i}'

kostik87 ★★★★★ ()
Последнее исправление: kostik87 (всего исправлений: 2)
Ответ на: комментарий от kostik87

то есть в сущьности вы делаете все то, что пытался сделать я.

монтируете некий носитель, с него монтируете образ sq, затем делаете его доступным для чтения с помощью tmpfs и aufs

а во втором цикле вы просто переносите все содержимое /live в /mnt/root/live

а смонтированная aufs так и остается в /mnt/root при этом пути до файлов, которые нужны aufs после switch_root не меняются!!!

это именно то, чего я добивался.

большое спасибо, обязательно попробую

IvanR ★★★ ()
Ответ на: комментарий от IvanR

Вы внимательно прочитали код, который я написал ?

1. Я создаю точки монтирования в корне initrd, куда предварительно будут смонтированы необходимые файловые системы.

for i in livemnt/memory livemnt/squashfs livemnt/media
do
  mkdir -p /${i}
done
/livemnt/media - сюда монтируется файловая система, на которой лежит образ squashfs.
mount $(findfs LABEL=<LABEL>) /livemnt/media -o ro -n || rescue_shell
/livemnt/memory - будет смонтирована файловая система, доступная на запись, в данном случае tmpfs, на которую при каскадном монтировании, у меня aufs, на unionfs аналогично, будут писаться изменения.
mount none -t tmpfs /livemnt/memory -n
/livemnt/squashfs - будет смонтирована файловая система, доступная только на чтение, образ squashfs, она будет каскадно монтироваться вместе с предыдущей через aufs, у вас unionfs.
mount /livemnt/media/system.sq /livemnt/squashfs -o ro -n
Ключ '-n' исключает отображение этих файловых систем в /proc/mounts

Собственно осуществляю каскадное монтирование в /mnt/root образа файловой системы, доступной только для чтения и файловой системы, доступной на запись в /mnt/root, в эту директорию я затем буду выполнять 'switch_root'

mount rootfs -t aufs /mnt/root/ -o udba=reval,br:/livemnt/memory:/livemnt/squashfs

Далее я создаю аналогичный директории в /mnt/root для переноса точек монтирования в новый корень, читайте внимательно код, вторая команда собственно и осуществляет перенос точек монтирования с /livemnt/memory, /livemnt/squashfs и /livemnt/media в /mnt/root/livemnt/memory, /mnt/root/livemnt/squashfs и /mnt/root/livemnt/media

for i in livemnt/memory livemnt/squashfs livemnt/media
do
  mkdir -p /mnt/root/${i}
  mount -n --move /${i} /mnt/root/${i}
done

Отмонтирование /proc и /sys и собственно смена корня

umount /proc
umount /sys

exec switch_root /mnt/root /sbin/init -c /dev/tty1

kostik87 ★★★★★ ()
7 февраля 2013 г.
Ответ на: комментарий от IvanR

Я читал этот документ. Хотелось бы увидеть, что нибудь самодельное, т.к. у меня ситуация не совсем стандартная.

anonymous ()
Ответ на: комментарий от anonymous

в убунте и в дебиане, а так же в арче по моему есть пакет, называется live-boot, он создает init скрипт почти для всех стандартных и не очень ситуаций, так же пересобирает initrd и добавляет туда все необходимые модули, программы и библиотеки.

вот мой скрипт, я его не особо оформлял, так как надобность внем отпла, но он работал.

http://pastebin.com/n5bshFhn

IvanR ★★★ ()
Ответ на: комментарий от nuxster

Можно просто загрузившись с LiveCD зажать целиком весь корневой раздел, точнее просто всю систему, со всеми смонтированными /var, /usr, /opt и прочим, если они вынесены на отдельные разделы.

mkdir /mnt/system
mount /dev/sdXY /mnt/system
mksquashfs /mnt/system /<path_to_save_squashfs_image>/system.sq -comp xz

Положить образ на какую-нибудь файловую систему.

И указать в init сценарии initramfs монтировать эту файловую систему и образ на ней:


rescue_shell() {
    echo "Something went wrong. Dropping you to a shell."
    busybox --install -s
    setsid cttyhack sh
    exec sh
}


mount -t proc none /proc
mount -t sysfs none /sys

echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s


mount $(findfs LABEL=<метка файловой системы>) /livemnt/media -o ro -n || rescue_shell
mount /livemnt/media/system.sq /livemnt/squashfs -o ro -n
mount none -t tmpfs /livemnt/memory -n
mount rootfs -t aufs /mnt/root/ -o udba=reval,br:/livemnt/memory:/livemnt/squashfs

for i in livemnt/memory livemnt/squashfs livemnt/media
do
  mkdir -p /mnt/root/${i}
  mount -n --move /${i} /mnt/root/${i}
done

mv /fstab /mnt/root/etc/fstab

echo -e "\ntmpfs\t/\t\ttmpfs\t\trw\t0 0\n" >> /mnt/root/etc/fstab

umount /proc
umount /sys

exec switch_root /mnt/root /sbin/init -c /dev/tty1

Файл fstab так же помещается в initramfs, он пустой:

# /etc/fstab: static file system information.
#
# The root filesystem should have a pass number of either 0 or 1.
# All other filesystems should have a pass number of 0 or greater than 1.
#
# See the manpage fstab(5) for more information.
#

# <fs>                  <mountpoint>    <type>          <opts>          <dump/pass>


Или можно убрать вывод в fstab, заранее отредактировав /etc/fstab перед запаковкой в squashfs образ:

# /etc/fstab: static file system information.
#
# The root filesystem should have a pass number of either 0 or 1.
# All other filesystems should have a pass number of 0 or greater than 1.
#
# See the manpage fstab(5) for more information.
#

# <fs>                  <mountpoint>    <type>          <opts>          <dump/pass>

tmpfs		/		tmpfs			rw		0 0
/dev/sdXY	/home		<typefs>		defaults,rw	0 0

Вместо LABEL=<метка файловой системы> можно указать UUID=<UUID>

Естественно этот параметр и имя squashfs образа можно сделать передающимися через параметры, которые вы передаёте ядру и которые обрабатывает сценарий init в initramfs.

kostik87 ★★★★★ ()
Последнее исправление: kostik87 (всего исправлений: 3)
20 июня 2013 г.
Ответ на: комментарий от kostik87

Спасибо! Очень полезно!!! Может вы мне сможете подсказать такую вещь: небольшой initrd-образ загружается по pxe и запускает скрипт, по результатам отработки скрипта продолжает загрузку с локального винта либо перезагружается. Как я могу реализовать передачу загрузки с локального винта после отработки скрипта? Может есть пример подобного init-скрипта?

nuxster ()
Ответ на: комментарий от nuxster

по результатам отработки скрипта продолжает загрузку с локального винта либо перезагружается.
...
Как я могу реализовать передачу загрузки с локального винта после отработки скрипта?

Т.е. вы хотите загрузить по сети мини Linux систему, выполнить некоторые проверки и уже затем по результатам этих проверок загружать с локального диска некоторую операционную систему, так ?
Т.е. загруженное по сети ядро и initrd не являются частью системы, которую вы хотите грузить с локального диска ?

Тогда вариант, скорее всего один, т.к. в вашем случае ПК настроены на загрузку по сети, а не с жёсткого диска напрямую, то у вас по сети каждый раз загружается загрузчик pxelinux.0, после чего он загружает с tftp сервера свой конфигурационный файл и на его основе загружает вашу мини Linux систему, которая выполняет проверки. Значит вам нужно менять конфигурационный файл загрузчика pxelinux.0 на tftp сервере, что бы в этом файле было указано, что нужно передать управление загрузчику на локальном диске.

При старте pxelinux.0 в начале осуществляется проверка наличия на tftp сервере конфигурационного файла, имя которого привязано к mac адресу сетевой карты ПК, на котором запущен загрузчик pxelinux.0 (осуществляется загрузка по сети). Этого нам достаточно. Вам нужно поднять NFS сервер и посредством протокола NFS предоставить доступ к директории pxelinuc.cfg, в которой лежат конфигурационные файлы. В ней нужно будет создать два файла:
pxelinuc.cfg/default - в этом файле у вас будет указана конфигурация для загрузки вашей мини Linux системы, которая осуществляет проверку.
pxelinuc.cfg/localboot - в этом файле будет указана конфигурация для вызова загрузчика с локального диска.

В init сценарии initrd вашей мини системы вам нужно выполнить ваши проверки и в случае, если нужно, что бы далее произошла загрузка с жёсткого диска, то нужно смонтировать по NFS директорию pxelinux.cfg, в которой находятся конфигурационные файлы pxelinux.0 и создать символьную ссылку вида:

aa-bb-cc-dd-ee-ff -> localboot
где aa-bb-cc-dd-ee-ff - MAC адрес сетевой карты ПК.

После чего размонтировать NFS ресурс и отправить ПК на перезагрузку. В случае, если загрузку с локального диска производить не нужно просто отправить на перезагрузку.

Для того, что бы при последующих запусках ПК опять с сети загружалась ваша мини Linux система вам нужно создать в cron правило удалять символьные ссылки в директории pxelinux.cfg, например раз в 5 минут.

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

find /var/tftpd/pxelinux.cfg/ -type l -exec rm {} \;

Вот примерное содержание конфигурационного файла localboot .

DEFAULT 0
TIMEOUT 0
PROMPT 0
LABEL BOOT_LOCAL
localboot 0
Так же вместо localboot 0 можно указывать localboot 0x80, обе строчки вызывают загрузчик с первого жёсткого диска.

kostik87 ★★★★★ ()
Ответ на: комментарий от nuxster

Если по какой-то причине простой вызов 'localboot 0' или 'localboot 0x80' не сработает или хотите создать лполнительную защиту, то можно создать образ дискеты с grub-0.97 (grub-legacy) и настроить загрузчик на дискете для вызова загрузчика с раздела жёсткого диска, в этому случае в mbr даже не нужно размещать загрузчик операционной системы, оставить только загрузчик на разделе, что бы систему можно было загрузить только с grub в этой дискете.

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

kostik87 ★★★★★ ()
Последнее исправление: kostik87 (всего исправлений: 1)
Ответ на: комментарий от kostik87

В этом пока нет необходимости, но всеравно спасибо!

nuxster ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.