Нужно было добиться загрузки Ubuntu в оперативную память компьютера и дальнейшей работы без носителя, с которого он был загружен. Решение получилось достаточно простым.
Вкратце идея такая: initrd.img
изменяется так, чтобы, после загрузки и старта ядра, с носителя в память копировался файл со сжатым образом файловой системы корневого раздела (SquashFS). Далее поверх корневого раздела монтируется aufs-tmpfs и стартует Ubuntu.
Ниже будет описание как создать загрузочный iso-образ и бутовую USB-флешку.
- Создаем директории
$ mkdir -p ~/ubuntu-ram/{etc,tmp,image,scripts}
- Устанавливаем необходимые пакеты
$ sudo aptitude install lilo mtools genisoimage debootstrap syslinux squashfs-tools
- Копируем настройки initramfs
Конфиги initramfs для iso-образа$ cp -a /etc/initramfs-tools ~/ubuntu-ram/etc/iso
Конфиги initramfs для iso-образа$ cp -a /etc/initramfs-tools ~/ubuntu-ram/etc/usb
- Настраиваем окружение загружаемой системы
$ export IMGROOT=~/ubuntu-ram/image
Входим в изолированное окружение
$ sudo -E -s
# debootstrap jaunty $IMGROOT http://mirror.ubuntu.optilink.ru/ubuntu/
# echo "aufs / aufs rw 0 0" > $IMGROOT/etc/fstab
# cp /etc/apt/sources.list $IMGROOT/etc/apt/
# cp /etc/resolv.conf $IMGROOT/etc/
# cat <<EOF > $IMGROOT/etc/hosts
127.0.0.1 localhost.localdomain localhost
127.0.1.1 hostname.domain hostname
EOF
# cat <<EOF > $IMGROOT/etc/network/interfaces
auto lo
iface lo loopback
EOF
# echo "hostname.domain" > $IMGROOT/etc/hostname
# mount -t proc none $IMGROOT/proc
# mount -o bind /dev $IMGROOT/dev
# mount -t devpts none $IMGROOT/dev/pts
# mount -t sysfs none $IMGROOT/sys# chroot $IMGROOT bash
Создаем аккаунт администратора и русскую локаль. Также разрешаем группеadm
использование командыsudo
# adduser --gecos 'System Administrator' demiurg
Устанавливаем ядро и требуемые утилиты
# usermod -a -G adm demiurg
# echo "@adm ALL=NOPASSWD: ALL" >> $IMGROOT/etc/sudoers
# locale-gen ru_RU.UTF-8# aptitude update
Настраиваем часовой пояс и консоль
# aptitude install linux-image-server grub aufs-tools squashfs-tools# dpkg-reconfigure tzdata
Далее система настраивается под себя (ставим дополнительные программы, правим конфиги под себя).
# dpkg-reconfigure console-setup
Выходим из изолированного окружения# aptitude clean
Отмонтируем файловые системы
# exit# umount $IMGROOT/proc
Выходим из режима суперпользователя
# umount $IMGROOT/dev/pts
# umount $IMGROOT/dev
# umount $IMGROOT/sys# exit
$ - Переходим к настройке конфигов initramfs для iso-образа
Создаём так называемый хук (hook) - скрипт, вызываемый утилитой initramfs$ cat <<EOF > $IMGROOT/../etc/iso/hooks/load_modules
- #!/bin/sh
- set -e
- PREREQ=""
- prereqs () {
- echo "$PREREQ"
- }
- case $1 in
- prereqs)
- prereqs
- exit 0
- ;;
- esac
- . /usr/share/initramfs-tools/hook-functions
- force_load squashfs
- force_load isofs
- force_load aufs
- exit 0
EOF
$ chmod +x $IMGROOT/../etc/iso/hooks/load_modules
Создаем скрипты, выполняющиеся во время загрузки initrd
Скрипт, закидывающий образ системы в память$ cat <<EOF > $IMGROOT/../etc/iso/scripts/init-premount/udev_into_ram
- #!/bin/sh
- PREREQ=""
- prereqs () {
- echo "$PREREQ"
- }
- case $1 in
- prereqs)
- prereqs
- exit 0
- ;;
- esac
- mknod /dev/loop0 b 7 0
- mkdir /disk
- WAIT_COUNT=15
- while [ ! -e /dev/scd0 ] && [ "$WAIT_COUNT" -gt 0 ]
- do
- tmp=$((WAIT_COUNT-=1))
- sleep 1
- done
- echo -n "Please wait... "
- mount -t iso9660 -o ro /dev/scd0 /disk
- cp /disk/root.sqfs /
- echo "done"
- umount /disk && rm -Rf /disk
EOF
$ chmod +x $IMGROOT/../etc/iso/scripts/init-premount/udev_into_ram
Скрипт, монтирующий файловую систему aufs$ cat <<EOF > $IMGROOT/../etc/iso/scripts/init-bottom/aufs_root
- #!/bin/sh
- #
- # https://help.ubuntu.com/community/aufsRootFileSystemOnUsbFlash
- #
- # Copyright 2008 Nicholas A. Schembri State College PA USA
- #
- # This program is free software: you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation, either version 3 of the License, or
- # (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program. If not, see
- # <http://www.gnu.org/licenses/>.
- # Thank you Voyage Linux for the idea, http://voyage.hk/ Great job on release 0.5
- #
- # Tested with 8.04.1
- #
- #
- # ****************************************************************************************
- #
- # Change log
- #
- # 2008.08.01 Added debugging comments in "drop to a shell" section. grub option aufs=tmpfs-debug will stop the init script.
- # reviewed *********** fix fstab on tmpfs ******************
- # rootaufs failed when system was booted with /dev/xxx and fstab had uuid= info.
- # BlaYO pointed out the best and simplest solution was to use grep -v. Grep replaces a sed one liner.
- # Add the comment block to fstab
- #
- #
- #
- case $1 in
- prereqs)
- exit 0
- ;;
- esac
- export aufs
- for x in $(cat /proc/cmdline); do
- case $x in
- root=*)
- ROOTNAME=${x#root=}
- ;;
- aufs=*)
- aufs=${x#aufs=}
- case $aufs in
- tmpfs-debug)
- aufs=tmpfs
- aufsdebug=1
- ;;
- esac
- ;;
- esac
- done
- if [ "$aufs" != "tmpfs" ]; then
- #not set in boot loader
- #I'm not loved. good bye
- exit 0
- fi
- # This is a simple overview of the steps needed to use aufs on the root file system and see the /rw and /ro branches.
- # initramfs init-botton script
- # move the root file system to aufs/unionfs readonly /ro
- # root is mounted on ${rootmnt}
- # create tmpfs on /rw
- # create a aufs using /ro and /rw
- # put some files on the tmpfs to fix mtab and fstab
- # move aufs to rootmnt to finish the init process.
- # No changes to the root file system are made by this script.
- #
- # Why!
- # This will allow you to use a usb flash drive and control what is written to the drive.
- # no need to rebuild the squashfs file just to add a program.
- # boot to single user mode. The system works the way you expect. boot aufs=tmpfs and no changes are written to the flash.
- # run ubuntu on an eeePC .
- # Install
- # Install ubuntu 8.04 Hardy. Hardy has aufs installed by default
- # apt-get update
- # apt-get dist-upgrade
- # apt-get install aufs-tools
- # echo aufs >> /etc/initramfs-tools/modules
- # put this file in /etc/initramfs-tools/scripts/init-bottom/rootaufs
- # chmod 0755 rootaufs
- # # clean up menu.lst
- # update-grub
- # update-initramfs -u
- # vi /boot/grub/menu.lst
- # add aufs=tmpfs to the default entry.
- # do not add this line to single user mode.
- # boot to single user mode in order to install software.
- # note: if your home account is on the root file system, your files are in ram and not saved.
- #
- echo
- echo " root-aufs: Setting up aufs on ${rootmnt} as root file system "
- echo
- modprobe -q --use-blacklist aufs
- if [ $? -ne 0 ]; then
- echo root-aufs error: Failed to load aufs.ko
- exit 0
- fi
- #make the mount points on the init root file system
- mkdir /aufs
- mkdir /rw
- mkdir /ro
- # mount the temp file system and move real root out of the way
- mount -t tmpfs aufs-tmpfs /rw
- mount --move ${rootmnt} /ro
- if [ $? -ne 0 ]; then
- echo root-aufs error: ${rootmnt} failed to move to /ro
- exit 0
- fi
- mount -t aufs -o dirs=/rw:/ro=ro aufs /aufs
- if [ $? -ne 0 ]; then
- echo root-aufs error: Failed to mount /aufs files system
- exit 0
- fi
- #test for mount points on aufs file system
- [ -d /aufs/ro ] || mkdir /aufs/ro
- [ -d /aufs/rw ] || mkdir /aufs/rw
- # the real root file system is hidden on /ro of the init file system. move it to /ro
- mount --move /ro /aufs/ro
- if [ $? -ne 0 ]; then
- echo root-aufs error: Failed to move /ro /aufs/ro
- exit 0
- fi
- # tmpfs file system is hidden on /rw
- mount --move /rw /aufs/rw
- if [ $? -ne 0 ]; then
- echo root-aufs error: Failed to move /rw /aufs/rw
- exit 0
- fi
- #*********** fix fstab on tmpfs ******************
- # test for /dev/sdx
- # this is not on the real file system. This is created on the tmpfs each time the system boots.
- # The init process will try to mount the root filesystem listed in fstab. / and swap must be removed.
- # the root file system must be mounted on /ro not on /
- if [ "$aufsdebug" -eq 1 ]; then
- echo " root-aufs debug: Remove the root file system and swap from fstab "
- echo
- echo
- echo " ROOTNAME $ROOTNAME "
- echo " resume $resume "
- echo
- echo ' BlaYO pointed out that grep can be used to quickly remove '
- echo ' the root file system from fstab. '
- echo
- echo ' Thank you BlaYO for the debug info.'
- echo
- fi
- # old code
- # I'm sure that sed can do this in one step but I want to correct on the rootname not matching the root in fstab.
- #cat /aufs/ro/etc/fstab|sed -e s/$ROOTNAME/\#$ROOTNAME/ -e s/$resume/\#$resume/ >/aufs/etc/fstab
- #Add the comment block to fstab
- cat <<EOF >/aufs/etc/fstab
- #
- # RootAufs has mounted the root file system in ram
- #
- # This fstab is in ram and the real fstab can be found /ro/etc/fstab
- # the root file system ' / ' has been removed.
- # All Swap files have been removed.
- #
- EOF
- #remove root and swap from fstab
- cat /aufs/ro/etc/fstab|grep -v ' / ' | grep -v swap >>/aufs/etc/fstab
- if [ $? -ne 0 ]; then
- echo root-aufs error: Failed to create /aufs/etc/fstab
- #exit 0
- fi
- # add the read only file system to fstab
- #ROOTTYPE=$(/lib/udev/vol_id -t ${ROOT})
- ROOTTYPE=$(cat /proc/mounts|grep ${ROOT}|cut -d' ' -f3)
- ROOTOPTIONS=$(cat /proc/mounts|grep ${ROOT}|cut -d' ' -f4)
- echo /dev/loop0 /ro squashfs ro,relatime 0 0 >>/aufs/etc/fstab
- # S22mount on debian systems is not mounting /ro correctly after boot
- # add to rc.local to correct what you see from df
- #replace last case of exit with #exit
- cat /aufs/ro/etc/rc.local|sed 's/\(.*\)exit/\1\#exit/' >/aufs/etc/rc.local
- echo mount -f /ro >>/aufs/etc/rc.local
- # add back the root file system. mtab seems to be created by one of the init proceses.
- echo "echo aufs / aufs rw,xino=/rw/.aufs.xino,br:/rw=rw:/ro=ro 0 0 >>/etc/mtab" >>/aufs/etc/rc.local
- echo "echo aufs-tmpfs /rw tmpfs rw 0 0 >>/etc/mtab" >>/aufs/etc/rc.local
- echo exit 0 >>/aufs/etc/rc.local
- #build remountrw
- echo \#!/bin/sh >/aufs/bin/remountrw
- echo mount -o remount,rw ${ROOT} >>/aufs/bin/remountrw
- chmod 0700 /aufs/bin/remountrw
- #build remountro
- echo \#!/bin/sh >/aufs/bin/remountro
- echo mount -o remount,ro ${ROOT} >>/aufs/bin/remountro
- chmod 0700 /aufs/bin/remountro
- # This should drop to a shell. (rewrite)
- if [ "$aufsdebug" -eq 1 ]; then
- echo
- echo " root-aufs debug: mount --move /aufs ${rootmnt} "
- echo
- echo ' root-aufs debug: init will stop here. '
- echo
- exit 0
- fi
- mount --move /aufs ${rootmnt}
- exit 0
EOF
$ chmod +x $IMGROOT/../etc/iso/scripts/init-bottom/aufs_root
На этом настройка initramfs заканчивается. - Создаём скрипт, создающий iso-образ и сохраняем его в файле «
~/ubuntu-ram/scripts/make-iso.sh
»
Делаем его исполняемым- #!/bin/sh
- WORKDIR=/path/to/ubuntu-ram
- SQUASHFS_ROOT=$WORKDIR/image/
- ISO_ROOT=$WORKDIR/tmp/
- rm -Rf $ISO_ROOT/*
- # Получаем версию ядра в окружении
- version=$(basename $(readlink $SQUASHFS_ROOT/initrd.img))
- version=${version#initrd.img-}
- mount -o bind $WORKDIR/etc/iso $SQUASHFS_ROOT/etc/initramfs-tools
- chroot $SQUASHFS_ROOT mkinitramfs -v -o /boot/initrd.img-$version $version
- umount $SQUASHFS_ROOT/etc/initramfs-tools
- mkdir $ISO_ROOT/isolinux
- cp $SQUASHFS_ROOT/boot/initrd.img-$version $ISO_ROOT/isolinux/initrd.gz
- cp $SQUASHFS_ROOT/boot/vmlinuz-$version $ISO_ROOT/isolinux/vmlinuz
- cp /usr/lib/syslinux/isolinux.bin $ISO_ROOT/isolinux/
- cat <<EOF > $ISO_ROOT/isolinux/isolinux.cfg
- DEFAULT server
- TIMEOUT 1
- LABEL server
- menu label ^Server
- kernel vmlinuz
- append initrd=initrd.gz root=/root.sqfs loop=/dev/loop0 rootfstype=squashfs aufs=tmpfs ro
- EOF
- #
- mksquashfs $SQUASHFS_ROOT $ISO_ROOT/root.sqfs \
- -e $SQUASHFS_ROOT/boot/* \
- $SQUASHFS_ROOT/initrd.img \
- $SQUASHFS_ROOT/vmlinuz
- # Создаём ISO
- mkisofs -o $WORKDIR/image.iso -r \
- -V "MYUSBSERVER" -v -no-emul-boot \
- -boot-load-size 4 -boot-info-table \
- -b isolinux/isolinux.bin \
- -c isolinux/isolinux.boot $ISO_ROOT
$ chmod +x ~/ubuntu-ram/scripts/make-iso.sh
После выполнения скрипта в директории «~/ubuntu-ram
» будет создан требуемый iso-образ. - Создание загрузочной USB флешки.
Создаём хук$ cat <<EOF > ~/ubuntu-ram/etc/usb/hooks/load_modules
- #!/bin/sh
- set -e
- PREREQ=""
- prereqs () {
- echo "$PREREQ"
- }
- case $1 in
- prereqs)
- prereqs
- exit 0
- ;;
- esac
- . /usr/share/initramfs-tools/hook-functions
- force_load usb_storage
- force_load squashfs
- force_load vfat
- force_load aufs
- exit 0
EOF
$ chmod +x ~/ubuntu-ram/etc/usb/hooks/load_modules
Копируем скрипт «etc/iso/scripts/init-bottom/aufs_root
» в «etc/usb/scripts/init-bottom/aufs_root
».
Пишем скрипт, загружающий систему из USB-флешки в оперативную память$ cat <<EOF > ~/ubuntu-ram/etc/usb/scripts/init-premount/udev_into_ram
- #!/bin/sh
- PREREQ=""
- prereqs () {
- echo "$PREREQ"
- }
- case $1 in
- prereqs)
- prereqs
- exit 0
- ;;
- esac
- mknod /dev/loop0 b 7 0
- mkdir /disk
- WAIT_COUNT=15
- while [ ! -e /dev/disk/by-label/MYUSBSERVER ] && [ "$WAIT_COUNT" -gt 0 ]
- do
- tmp=$((WAIT_COUNT-=1))
- sleep 1
- done
- echo -n "Please wait... "
- mount -t vfat -o ro /dev/disk/by-label/MYUSBSERVER /disk
- cp /disk/root.sqfs /
- echo "done"
- umount /disk && rm -Rf /disk
EOF
$ chmod +x $IMGROOT/../etc/usb/scripts/init-premount/udev_into_ram
Ниже приведён скрипт создающий бутовую USB-флешку. Скрипт сохраняется в файл «~/ubuntu-ram/scripts/make-usb.sh
»
Делаем скрипт исполняемым- #!/bin/sh
- WORKDIR=/path/to/ubuntu-ram
- SQUASHFS_ROOT=$WORKDIR/image/
- ISO_ROOT=$WORKDIR/tmp/
- rm -Rf $ISO_ROOT/*
- # Получаем версию ядра в окружении
- version=$(basename $(readlink $SQUASHFS_ROOT/initrd.img))
- version=${version#initrd.img-}
- mount -o bind $WORKDIR/etc/usb $SQUASHFS_ROOT/etc/initramfs-tools
- chroot $SQUASHFS_ROOT mkinitramfs -v -o /boot/initrd.img-$version $version
- umount $SQUASHFS_ROOT/etc/initramfs-tools
- mkdir $ISO_ROOT/isolinux
- cp $SQUASHFS_ROOT/boot/initrd.img-$version $ISO_ROOT/initrd.gz
- cp $SQUASHFS_ROOT/boot/vmlinuz-$version $ISO_ROOT/vmlinuz
- cat <<EOF > $ISO_ROOT/syslinux.cfg
- DEFAULT server
- TIMEOUT 1
- LABEL server
- menu label ^Server
- kernel vmlinuz
- append initrd=initrd.gz root=/root.sqfs loop=/dev/loop0 rootfstype=squashfs aufs=tmpfs ro
- EOF
- #
- mksquashfs $SQUASHFS_ROOT $ISO_ROOT/root.sqfs \
- -e $SQUASHFS_ROOT/boot/* \
- $SQUASHFS_ROOT/initrd.img \
- $SQUASHFS_ROOT/vmlinuz
- echo "Please insert USB flash drive and press Enter"
- read
- # /dev/sdX - Ваша USB-флешка
- lilo -M /dev/sdX
- lilo -A /dev/sdX 1
- mkfs.vfat /dev/sdX1
- syslinux -f /dev/sdX1
- mlabel -i /dev/sdX1 ::MYUSBSERVER
- mount -t vfat /dev/sdX1 /mnt
- cp -a $ISO_ROOT/* /mnt
- umount /mnt
- exit 0
$ chmod +x ~/ubuntu-ram/scripts/make-usb.sh
4 комментария:
а какой размер образа получился ?
Образ сжатой ФС после debootstrap — ~110MB. В памяти занимает столько же, т.к. не распаковывается.
А если материнская плата не поддерживает загрузку с USB то соответсвенно такой фокус не пройдет?
На этот случай можно загрузиться с CD-диска
Отправить комментарий