I have been working on JUST this. A livecd-to-usb setup wasn't working very well for me. I have created a modified version of the "local" script for ubuntu server 11.04. After applying the patch (or hand editing local with the changes of course) you only need update-iniramfs -u, and boot linux with a "ramboot" kernel argument, and your system will boot a normal linux system fully into ram. Making persistent changes is as easy as rsync'ing the ramdisk filesystem onto the boot-device. In my case, a usb-pen, but it could easily be any suitable bootable block device. You can, of course, just reboot without the "ramboot" argument and make changes, as you will be back on the block device, then reboot into ramboot again, but there is no need, except it makes it very clear when you're in which state.
0) "sudo su"
(you don't have to do this step, but then you will need to make sure you sudo everything that might require it) I tend to just "sudo su" when I'm doing this type of systems modifications.
1) download or copy/paste the contents of this patch to a file:
"/usr/share/initramfs-tools/scripts/ramboot.patch" --couldn't include pastebin, newbie.
included at end
2) cd /usr/share/initramfs-tools/scripts; cp local local.bak #just in case
3) patch local ramboot.patch
This applies the changes defined in ramboot.patch, to your local script. /usr/share/initramfs-tools/scripts/local is the normal bootup script configurator which configures the rootmount function for init. The patch was created by "diff local local.modified > ramboot.patch"
4) cp /bin/busybox /usr/lib/initramfs-tools/bin/busybox
This makes your initramfs.img file slightly larger then it would be normally, but the difference is about 1.5 megabytes, not major. I wanted the human readable output from df -h, which the stripped down busybox's df doesn't support. If you care about keeping the 300k version of busybox around, make sure to cp /usr/lib/initramfs-tools/bin/busybox /small_busybox, then return it to it's former name/location after step 5.
5) update-initramfs -u
6) optional you will most likely want to create a /etc/grub.d/06_custom, with the kernel argument "ramboot" included, and a title that implies that.
(or 40_custom if you want the ramboot menu entry to be at the end of the list, instead of at the top)
e.g. 06_custom -- couldn't include pastebin link, newbie here.
you will need to fill in your correct kernel-version and initrd.img-verion and also the filesystem uuid of your root device into this 06_custom file or else it will not work.
you can find the kernel/initrd.img information by just looking in /boot/ with "ls /boot" and the following command should output your root filesystem uuid:
blkid|grep `df /|grep dev|cut -d ' ' -f1`|cut -d '"' -f2
Once your 06_custom has the correct uuid, kernel and initrm.img paths and file names, you can update-grub, and try it out!
7) update-grub to add the custom entries to your /boot/grub/grub.cfg file.
Note: I have a small system with the root partition only including about 1.2g of data to copy into ram. If your system doesn't have enough spare memory, this script will safely boot normally (or at least try!) I found remastersys, and persistent usb-casper installs to not exactly be suitable for my needs.
This is used on a scst-iscsi server currently, and it's only real weakness is that if you don't save changes to the system, and lose power, or some other mistake (init 0, oh no, I forgot to check in my work back to subversion! disaster!) then the ramdisk system doesn't make anything persistent. I don't have a ton of air-time on this config yet, but since I had looked around for this type of information, found lots of ways that were not exactly suitable, or just plain confusing to me, I thought I'd put this out there. perhaps it will save someone a little teeth pulling *8^)
remastersys and the root-ro scripts helped me to this point. they are both useful but different projects. remastersys packages your running system, to both deploy/clone, or just run as a live.iso version of the system, or backup I guess. root-ro is a dual-ramdisk blockdevice-filesystem mounted union-style, with the ramdisk writeable, and the blockdev read-only. then to sync you can just remount the blockdev rw, rsync once branch to the other, and remount it ro. This was almost perfect, but I wanted the usb-pen to be unmounted/able to be removed and the system would maintain it's state, which this solution does.
root-ro bottom of the page -- https://help.ubuntu.com/community/aufsRootFileSystemOnUsbFlash
remastersys -- http://www.geekconnection.org/remastersys/ubuntu.html
You can easily rsync or copy -r from the ramboot (mounted on /) and the disk/device which it came from originally when running in ram, to make that change "persistent".
I save the uuid of the device that the ramboot booted from, so you can always find it afterwards. It is in /.bootdisk_byuuid on the ramdisk, and you could easily set a script to mount this device somewhere, do the rsync, and umount it again, and call that script "ramtodisk" or whatever.
NB! you may want to back up your /boot/initrd.img file so in case something goes wrong, your system is still bootable. I saved mine to /boot/initrd while doing work on this. when I had glitches with grub/init, I just edited my initrd to point to the backup /boot/initrd file and got back to debugging. anyways, I am guessing that this is more guidelines not cookbook. have fun! it takes my 1.2gig system 9:30ish to boot on usb 1.1, 1:30-45 on usb 2.0, and ~=35 seconds on usb 3.0 to load into ram. more and more juicy every year! *8^)
here's ramboot.patch
2a3,13
> parse_cmdline() {
> RAM=""
> for x in $(cat /proc/cmdline); do
> case $x in
> ramboot)
> RAM="Yes" ;;
> quiet)
> quiet=y ;;
> esac
> done
> }
66c77
<
---
> parse_cmdline
90,91c101,164
< # Mount root
< mount ${roflag} ${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} ${rootmnt}
---
> # Mount root - custom ramboot.patch
> # By: Justin Perkins -- 4/25/12 Email: justin.perkins@vm-labs.com
> if [ -z "${RAM}" ]; then
> mount ${roflag} ${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} ${rootmnt}
> else
> mkdir /ramboot
> mount ${roflag} -t ${FSTYPE} ${ROOTFLAGS} ${ROOT} /ramboot
> log_begin_msg "Detecting system resources"
> size=$(df|grep ramboot|tr -s ' '|cut -d ' ' -f3)
> datasize=${size}
> size=$(expr ${size} + ${size} / 20 ) #5% more to be sure
> freespace=$(awk '/^MemFree:/{f=$2} /^Cached:/{c=$2} END{print f+c}' /proc/meminfo)
> log_end_msg
> if [ "${freespace}" -lt "${size}" ] ; then
> echo "Not enough system RAM, ${freespace}k > ${size}k."
> echo "Attempting normal rootmount."
> mount ${roflag} ${FSTYPE:+-t ${FSTYPE} }${ROOTFLAGS} ${ROOT} ${rootmnt}
> else
> if [ "$quiet" != "y" ] ; then
> tstart_min=$(date|cut -d ' ' -f4|cut -d : -f2)
> tstart_sec=$(date|cut -d ' ' -f4|cut -d : -f3)
> mount -t tmpfs -o size=100% none ${rootmnt}
> cd ${rootmnt}
> size=$(df -h|grep ramboot|tr -s ' '|cut -d ' ' -f3) #reuse size
> echo "System size: ${size} (${datasize}k) this may take a couple of minutes."
> log_begin_msg "Copying system files into RAM"
> echo -e -n "\b"
> cp -rfa /ramboot/* ${rootmnt} &
> pid=$!
> while [ ! ${pid} == "done" ] ; do
> alive=$(ps -o pid,args|grep -E ${pid}|grep -v grep)
> alive=$(echo ${alive}|cut -d ' ' -f1)
> if [ -z ${alive} ] ; then pid="done" ; fi
> printf "."
> sleep 1
> done
> log_end_msg
> echo ${ROOT} > ${rootmnt}/.bootdisk_byuuid
> tend_min=$(date|cut -d ' ' -f4|cut -d : -f2)
> tend_sec=$(date|cut -d ' ' -f4|cut -d : -f3)
> if [ ${tend_sec} -lt ${tstart_sec} ] ; then
> tend_sec=$(expr ${tend_sec} + 60)
> tend_min=$(expr ${tend_min} - 1)
> fi
> if [ ${tend_min} -lt ${tstart_min} ] ; then
> tend_min=$(expr ${tend_min} + 60)
> fi
> tduration_min=$(expr ${tend_min} - ${tstart_min})
> tduration_sec=$(expr ${tend_sec} - ${tstart_sec})
> echo "Copy complete, duration: $tduration_min minutes $tduration_sec seconds."
> freespace=$(awk '/^MemFree:/{f=$2} END{print f}' /proc/meminfo)
> freespace=$(expr ${freespace} + 425000) #this accounts for the temporal settling issue
> echo "You have approximately ${freespace}k free RAM after loading the ramboot."
> if [ ${freespace} -lt "502400" ] ; then echo "Warning! you have critically low system RAM free after ramboot." ; fi
>
> else
> cp -rfa /ramboot/* ${rootmnt}
> echo ${ROOT} > ${rootmnt}/.bootdisk_byuuid
> freespace=$(awk '/^MemFree:/{f=$2} END{print f}' /proc/meminfo)
> if [ ${freespace} -lt "102400" ] ; then echo "Warning! you have critically low system RAM free after ramboot." ; fi
> fi
> fi
> umount /ramboot
> fi #end custom ramboot.patch
06_custom
#!/bin/sh
exec tail -n +3 $0
# This file provides an easy way to add custom menu entries. Simply type the
# menu entries you want to add after this comment. Be careful not to change
# the 'exec tail' line above.
#uuid_<placeholder>, and vmlinuz-<placeholder>, and initrd.img-<placeholder> and
#set root='(hd0,2)' need to be replaced with your system's values, although, if you
#get the hd0,2 wrong, but the uuid correct, grub will grep around and find it anyhow.
menuentry "Ubuntu, with Linux Custom-Ramboot" {
recordfail
set root='(hd0,2)'
search --no-floppy --fs-uuid --set=root uuid_placeholder
linux /boot/vmlinuz-<placeholder> root=UUID=<uuid-placeholder> ro ramboot
initrd /boot/initrd.img-<placeholder>
}
docache
parameter).