LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 8540|回复: 18

原来U盘Linux还可以这么做!!!

[复制链接]
发表于 2007-6-22 15:42:59 | 显示全部楼层 |阅读模式
[color="Red"]如果转载,请标明出处和作者
[color="Blue"]如果你照着这个做成功了,请顶一下贴,以示鼓励

经过几天折腾,终于将系统转移到U盘上了。

1、给U盘分区并创建文件系统(1G的U盘)
为了简单起见,我只给U盘分了一个区(/dev/sda1),并激活了该分区
mkfs.ext3 /dev/sda1  (我偏爱ext3文件系统)

2、复制现有的系统文件到U盘上
mkdir /mnt/sda1 /mnt/tmp
mount /dev/sda1 /mnt/sda1
mkdir /dev/hda2 /mnt/tmp (我原来的系统是/dev/hda2,而且所有的文件都在此分区上)
cp -a /mnt/tmp/* /mnt/sda1 (将原系统中的所有文件复制到U盘上)
[color="Red"]注:将原文件系统挂载到一个临时目录的原因,是因为现在的/分区下面可能挂载了别的文件系统(比如/dev /proc /sys /tmp .... ),这些都是系统运行后自动挂载的,与原文件系统无关。

3、安装启动管理器(我偏爱grub)
grub
grub> root (hd1,0)  #我的系统只有一个硬盘,外加准备迁移的U盘,因此U盘的编号就是1
grub> setup (hd1)

4、修改menu.lst和fstab
default 0
timeout 5
title USB
   root (hd0,0)
   kernel /boot/vmlinuz-2.6.18-4-686 root=/dev/sda1 ro
   initrd /boot/initrd.img-2.6.18-4-686

因为已经迁移到U盘上,因此/etc/fstab中的文件是需要修改的,我没有用swap,因此原文件中的swap就需要去掉,为了在系统启动后,还能够正确挂载根文件系统,我使用的UUID
# /etc/fstab: static file system information.
#
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
proc            /proc           proc    defaults        0       0
#/dev/hda2       /               ext3    defaults,errors=remount-ro 0       1
[color="Blue"]UUID=4f1a87c0-b065-44d8-a6bf-2bb3d4a0c63a /     ext3    defaults,errors=remount-ro      0       1
[color="Red"]其中的UUID是我通过blkid这个程序获取的U盘分区的UUID,因为如果在新的系统中启动的时候,如果有scsi硬盘或者sata或pata硬盘的话,有可能会发生顺序偏差,为了稳妥起见,就用UUID来挂载了

5、准备initrd.img-2.6.18-4-686 ([color="Red"]这一步可是关键,否则就会受到 Kernel Panic的困扰了)
[color="Blue"]因为initrd.img只是系统启动的一个虚拟磁盘而已,系统启动完成后就没有用处了,因此,我决定用busybox来完成一些必要的启动工作(用的是busybox-1.5.1,配置文件如下)
cd /tmp
mkdir initrd
cd initrd
mkdir dev proc sys lib mnt
mkdir -p lib/modules/kernel/{drivers,fs}
mkdir -p lib/modules/kernel/drivers/{ide,scsi,usb}
mkdir -p lib/modules/kernel/drivers/usb/{core,host,input,storage}
mkdir -p lib/modules/kernel/fs/{ext2,ext3,jbd}
[color="Magenta"]注:复制内核模块有一些讲究,经过分析,要用U盘启动,必须要有sd_mod usb-storage内核模块才能让内核认出U盘,通过分析/lib/modules/`uname -r`/modules.dep这个文件可以发现:
usb-storage 依赖scsi_mod、usbcore和ide-core这三个模块,但是没有说明依赖usb/host/下面的模块,但是,只有将drivers/usb/host/下面的模块加载以后,内核才能识别USB设备,因此,drivers/usb/host/目录下的模块是需要复制的
sd_mod 依赖scsi_mod
因为我的U盘上的文件系统是ext3的,因此还需要复制fs/ext3下的所有内核模块(为了稳妥,我同时复制了fs/ext2下的模块)
ext3 依赖 mbcache 和 jbd 模块
这么查找后,已经分析清楚U盘启动的时候需要哪些模块了
/lib/modules/`uname -r`/kernel/drivers/ide/ide-core.ko
/lib/modules/`uname -r`/kernel/drivers/scsi/scsi_mod.ko
/lib/modules/`uname -r`/kernel/drivers/scsi/sd_mod.ko
/lib/modules/`uname -r`/kernel/drivers/usb/core/usbcore.ko
/lib/modules/`uname -r`/kernel/drivers/usb/host/ehci-hcd.ko
/lib/modules/`uname -r`/kernel/drivers/usb/host/ohci-hcd.ko
/lib/modules/`uname -r`/kernel/drivers/usb/host/uhci-hcd.ko
/lib/modules/`uname -r`/kernel/drivers/usb/storage/usb-storage.ko
/lib/modules/`uname -r`/kernel/drivers/usb/input/usbhid.ko #加载这个模块是为了支持USB键盘,如果在启动过程中,如果出现无法找到root的时候,会进入一个临时的shell,因此可能需要一些简单的调试,如果是USB键盘的话,就必须要加载这个模块了
/lib/modules/`uname -r`/kernel/fs/ext2/ext2.ko
/lib/modules/`uname -r`/kernel/fs/ext3/ext3.ko
/lib/modules/`uname -r`/kernel/fs/jbd/jbd.ko
/lib/modules/`uname -r`/kernel/fs/mbcache.ko
将这些文件按照目录结构复制到lib/modules/kernel下,我省略了`uname -r`,是为了简化脚本,以便在有新的内核的时候不需要修改启动脚本。

创建设备文件
mknod dev/console c 5 1
mknod dev/null c 1 3

复制可执行文件
cp -a /usr/local/src/busybox-1.5.1/_install/{bin,sbin} .

生成init文件([color="Red"]注,用不同格式的initrd就需要不同名字的启动文件,这个是我爬了一周的网后得出的结果,如果是ASCII cpio archive (SVR4 with no CRC)格式的initrd文件,那么就应该使用init,否则,就使用linuxrc,具体可参看linuxocumentation/initrd.txt,只是ramdisk的启动方式比较复杂,而initramfs的方式比较简单,因此我选择用initramfs的方式)
cat > init <<EOFINIT
#!/bin/sh
#
#  Utility functions
#
PATH="/bin:/sbin"

#
# Setting up mounts
#
mount -nt sysfs sysfs /sys
mount -nt proc proc /proc

ro=-r
INIT=/sbin/init
ROOTDELAY=10
ROOT=/dev/sda1

for i in $(cat /proc/cmdline)
do
        case "$i" in
        rootdelay=*)
                ROOTDELAY=${i#rootdelay=}
                ;;
        root=/dev/*)
                ROOT=${i#root=}
                ;;
        init=*)
                INIT=${i#init=}
                ;;
        ro)
                ro=-r
                ;;
        rw)
                ro=
                ;;
        esac
done

#load needed modules
insmod /lib/modules/kernel/fs/mbcache.ko
insmod /lib/modules/kernel/fs/jbd/jbd.ko
insmod /lib/modules/kernel/fs/ext2/ext2.ko
insmod /lib/modules/kernel/fs/ext3/ext3.ko

insmod /lib/modules/kernel/drivers/ide/ide-core.ko
insmod /lib/modules/kernel/drivers/scsi/scsi_mod.ko
insmod /lib/modules/kernel/drivers/usb/core/usbcore.ko
insmod /lib/modules/kernel/drivers/usb/input/usbhid.ko
insmod /lib/modules/kernel/drivers/usb/host/ehci-hcd.ko
insmod /lib/modules/kernel/drivers/usb/host/ohci-hcd.ko
insmod /lib/modules/kernel/drivers/usb/host/uhci-hcd.ko
insmod /lib/modules/kernel/drivers/usb/storage/usb-storage.ko
insmod /lib/modules/kernel/drivers/scsi/sd_mod.ko

echo "wait root ..."
sleep $ROOTDELAY

mdev -s

[ -b $ROOT ] || (echo "not find root";/bin/sh)


mount -n $ro -o errors=remount-ro $ROOT /mnt

echo "Switching root ..."
umount -n /sys
umount -n /proc
exec switch_root /mnt $INIT "$@"
EOFINIT

生成initrd
[color="Blue"]find . | cpio -o [color="Magenta"]-H newc | gzip > /mnt/sda1/boot/initrd.img-2.6.18-4-686
([color="Red"]注:-H newc 是必须的,否则内核会认为是ramdisk,而不是initramfs,因为这个,我重新启动电脑N次(N>20))

6、设置CMOS,让U盘的位置位于其他硬盘的前面
(注:有些机器可以在开机的时间按一个键,然后选择从哪个盘启动,在这种方式下,可能导致U盘不能正确启动,因此,必须在CMOS中设置让U盘出现在硬盘的前面,然后直接启动,而不是进入启动菜单后选择U盘启动)

busybox-1.5.1的配置文件

CONFIG_HAVE_DOT_CONFIG=y
CONFIG_NITPICK=y
CONFIG_FEATURE_BUFFERS_USE_MALLOC=y
CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exec"
CONFIG_STATIC=y
CONFIG_INSTALL_NO_USR=y
CONFIG_INSTALL_APPLET_SYMLINKS=y
CONFIG_PREFIX="./_install"
CONFIG_PASSWORD_MINLEN=6
CONFIG_MD5_SIZE_VS_SPEED=2
CONFIG_FEATURE_EDITING_HISTORY=
CONFIG_CAT=y
CONFIG_ECHO=y
CONFIG_FEATURE_FANCY_ECHO=y
CONFIG_MKNOD=y
CONFIG_SLEEP=y
CONFIG_TEST=y
CONFIG_INSMOD=y
CONFIG_FEATURE_CHECK_TAINTED_MODULE=y
CONFIG_FEATURE_2_6_MODULES=y
CONFIG_MDEV=y
CONFIG_MOUNT=y
CONFIG_FEATURE_MOUNT_FLAGS=y
CONFIG_SWITCH_ROOT=y
CONFIG_UMOUNT=y
CONFIG_FEATURE_LESS_MAXLINES=
CONFIG_FEATURE_SH_IS_ASH=y
CONFIG_ASH=y
CONFIG_ASH_BUILTIN_ECHO=y
CONFIG_ASH_BUILTIN_TEST=y
CONFIG_ASH_OPTIMIZE_FOR_SIZE=y
CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=
发表于 2007-6-22 17:14:11 | 显示全部楼层
啥也不说了。
先顶帖支持一下。
回复 支持 反对

使用道具 举报

发表于 2007-6-29 13:57:26 | 显示全部楼层
google到这个帖子,顶一下,再照着做了
回复 支持 反对

使用道具 举报

发表于 2007-7-1 12:05:20 | 显示全部楼层
我不太喜欢用 ramdisk,还是喜欢用 rootdelay 省却麻烦

Btw,春风兄什麽时候也成了 LFSer 一族了?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-7-1 16:42:50 | 显示全部楼层
Post by d00m3d
我不太喜欢用 ramdisk,还是喜欢用 rootdelay 省却麻烦

Btw,春风兄什麽时候也成了 LFSer 一族了?


我用的是ramfs,而不是ramdisk,就是因为讨厌ramdisk的复杂(其实,是我搞不明白该怎么做

其实,我以前就做过LFS,只是没有深入。


如果使用rootdelay的话,要么就是把U盘相关的功能编译进内核,要么就是在initrd中加载(我采取的是在initrd中加载,不过,也可以在kernel启动的时候设置rootdelay,我在initrd中设置的缺省rootdelay是10秒,对于大多数U盘这个数值足够了)
回复 支持 反对

使用道具 举报

发表于 2007-7-4 08:57:29 | 显示全部楼层
春风辛苦了 小弟顶下 学习去
回复 支持 反对

使用道具 举报

发表于 2007-7-19 13:51:57 | 显示全部楼层
如何才能在启动后拔掉U盘,系统照样工作?
回复 支持 反对

使用道具 举报

发表于 2007-7-19 19:13:45 | 显示全部楼层
拔掉 U 盘後系统照样工作一般是 LiveUSB 的做法,不是真正 Linux 系统(不论是否装在 U 盘上)的做法

在真实系统里,U 盘(硬盘亦如是)的 / 分区被系统挂载成 rw 了,你是不能把 umount 的;在 LiveUSB 或 LiveCD,挂载的是 cloop、squashfs 之类的压缩映像文件,它只能是 ro,虽然有 unionfs 或 aufs 等方式使 / 好像能写入,但是两者概念完全不同

简单一点说,若果你能使硬盘安装好的 Linux 启动後把它拔掉而能继续工作的话,你的问题就解决了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-7-20 10:59:03 | 显示全部楼层
如果用的是initrd,而且基本系统都是安装在initrd中,那么就相当于把系统全部加载到内存中了,因此是可以拔U盘的

我上面所用的,只是能够驱动U盘并挂载U盘上的根文件系统的initrd,因此启动后是不能拔U盘的
回复 支持 反对

使用道具 举报

发表于 2007-7-23 16:33:38 | 显示全部楼层
没说的,顶,学习中
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表