利用宿主系统制作bootcd
1. 先确定宿主系统是否安装了cdrtools和cpio的支持,这是在生成bootcd的iso时会需要的工具,如果没有安装的话先下载安装:
源码链接:
cdrtools: http://www.linuxfromscratch.org/blfs/view/stable/multimedia/cdrtools.html
cpio: http://www.linuxfromscratch.org/blfs/view/svn/general/cpio.html
2. 设置环境变量:
export WORK=/mnt/bootcd
mkdir -pv $WORK/tmpfs
3. 生成制作bootcd的脚本:
#!/bin/sh
cd $WORK/tmpfs
find . | cpio -H newc -o | gzip > $WORK/iso/boot/initramfs.igz
#create bootcd.iso
cd $WORK
mkisofs \
-R \
-J \
-b boot/grub/g2ldr \
-no-emul-boot \
-boot-load-size 4 \
-boot-info-table \
-o $WORK/Keqi-OS-BootCD.iso \
$WORK/iso
#upload bootcd.iso
#ftp ftpserver
这里有个问题就是,在grub2中,g2ldr是不存在的,需要手动的来生成g2ldr这个文件,方法是:
mkdir -pv /tmp/iso/boot/grub/
cp /usr/lib/grub/i386-pc/* /tmp/iso/boot/grub/
cd /tmp/iso/boot/grub
grub-mkimage -o core.img biosdisk iso9660 ext2 fat
cat cdboot.img core.img > g2ldr
4. 在这个bootcd的引导系统中所需要的命令要复制过来,以及所依赖的库文件,通过ldd来实现,但是如果对每个bin文件都手动来实现的话,绝对可以让你发疯,因此,用下面的简单perl脚本kbs.pl(keqi-OS binary search)来这个过程:
#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long;
my %opts;
$opts{target} = 'tmpfs';
usage(), exit -1
if ( not GetOptions( \%opts, 'import=s', 'verbose', 'target|t=s' )
);
usage(), exit -1
if ( ( not @ARGV ) xor ( defined $opts{import} ) );
sub usage {
print <<EOU;
Usage:
$0 file1 [file2...fileX] [-t DIR] [-v]
or
$0 -i list [-t DIR] [-v]
Options:
-i, --import=FILE Process files listed in FILE
-t, --target=DIR Use DIR as root. (Default ./initrd)
-v, --verbose Be verbose.
EOU
return;
}
## files to process
my @files;
{
my @filess;
{
## files in @ARGV
if ( not defined $opts{import} ) {
push @filess, @ARGV;
last;
}
## import list
open my $fh, '<', $opts{import}
or die "$!\n";
@filess = (<$fh>);
@filess = map { chomp; $_ } @filess;
close $fh;
}
print "File to process: (! means file NOT found.)\n";
foreach (@filess) {
print " ! $_ \n" and next if not -f $_;
push @files, $_;
print " $_\n";
}
}
## parse libs to copy
my @libs;
{
print "\n";
foreach (@files) {
my $ldd = qx{/usr/bin/ldd $_};
chomp $ldd;
print "$ldd\n\n" if defined $opts{verbose};
my @files = split /\s+/, $ldd;
push @libs, grep { -f $_ } @files; ## check for existence
}
## Unified them
my %h = map { ( $_, 1 ) } @libs;
@libs = sort keys %h;
if ( defined $opts{verbose} ) {
print "Libraries to copy:\n";
print " $_ => $opts{target}$_\n" foreach @libs;
}
}
## Do the real work
print "\n";
{
print "Copying files, please wait...\n";
## Add those files in the original list
push @libs, @files;
if ( not -d $opts{target} ) {
print "Creating directory $opts{target}\n";
system qq{ mkdir -p $opts{target} };
}
my $v = $opts{verbose} ? 'v' : '';
foreach (@libs) {
if (/^\//) {
## Absolute path
s/^\///;
system
qq{ tar -C / -hpmcf - $_ | tar -C $opts{target} -pmx$v -f - };
} else {
## Opposite path
system
qq{ tar -hpmcf - $_ | tar -C $opts{target} -pmx$v -f - };
}
}
}
5. 安装grub
cd $WORK
#install grub
mkdir iso/boot/grub -p
cp /usr/lib/grub/i386-pc/stage2_eltorito iso/boot/grub
#create menu.lst
cat > iso/boot/grub/grub.cfg << EOF
set default=0
set timeout=5
set menu_color_normal=white/black
set menu_color_highlight=cyan/black
menuentry “Keqi-OS-BootCD” {
set root=(hd)
linux /boot/kernel
initrd /boot/initramfs.igz
}
#install kernel
cp /boot/yourkernelname iso/boot/kernel
6. 现在可以执行./mkbootcd来查看下iso的进度了.
7. 复制所有需要的命令:
cat > $WORK/lddfiles.dat << EOF
/bin/bash
/bin/bzip2
/bin/cat
/bin/cp
/bin/echo
/bin/grep
/bin/ls
/bin/mkdir
/bin/mount
/bin/mountpoint
/bin/ps
/bin/rm
/bin/stty
/bin/tar
/bin/umount
/sbin/agetty
/sbin/fdisk
/sbin/init
/sbin/mkfs
/sbin/mkfs.ext2
/sbin/mkfs.ext3
/sbin/mkswap
/sbin/swapon
/sbin/udevtrigger
/sbin/udevsettle
/sbin/udevd
/usr/bin/less
/usr/bin/vi
/usr/sbin/chroot
EOF
cd $WORK
./gld.pl -i lddfiles.dat
ln -s bash tmpfs/bin/sh
8. 内存模式下kernel加载后会执行/init,现在建立这个文件:
cd $WORK/tmpfs
ln -s sbin/init
9. 配置init会调用的一些信息:
生成/etc/inittab文件
mkdir $WORK/tmpfs/etc
cat > $WORK/tmpfs/etc/inittab << EOF
# Begin /etc/inittab
id:3:initdefault:
si::sysinit:/etc/rc.d/init.d/rc sysinit
ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now
1:2345:respawn:/sbin/agetty -n tty1 9600
2:2345:respawn:/sbin/agetty -n tty2 9600
3:2345:respawn:/sbin/agetty -n tty3 9600
4:2345:respawn:/sbin/agetty -n tty4 9600
5:2345:respawn:/sbin/agetty -n tty5 9600
6:2345:respawn:/sbin/agetty -n tty6 9600
# End /etc/inittab
EOF
生成/bin/login文件:
cat > $WORK/tmpfs/bin/login << EOF && chmod +x $WORK/tmpfs/bin/login
#!/bin/sh
echo "Press Enter to activate this console..."
read ENTER
exec /bin/bash --login
EOF
生成/etc/profile文件:
cat > $WORK/tmpfs/etc/profile << 'EOF'
# Begin /etc/profile
NORMAL="\[\e[0m\]"
RED="\[\e[1;31m\]"
GREEN="\[\e[1;32m\]"
export PATH=/bin:/usr/bin:/sbin:/usr/sbin
export TERM=xterm
export HISTSIZE=20
export PS1="$RED[ $NORMAL\w $RED]$GREEN\$?$RED# $NORMAL"
alias ls="ls --color"
alias ll="ls -lh"
alias la="ll -a"
cd ~
# End /etc/profile
EOF
生成rc启动脚本:
cp /etc/udev $WORK/tmpfs/etc/ -a
mkdir -p $WORK/tmpfs/etc/rc.d/init.d
cp -a /etc/rc.d/init.d/{functions,mountfs,mountkernfs,rc,udev,udev_retry} \
$WORK/tmpfs/etc/rc.d/init.d/
mkdir -p $WORK/tmpfs/etc/rc.d/rcsysinit.d
cp -a /etc/rc.d/rcsysinit.d/{S00mountkernfs,S10udev,S40mountfs,S50udev_retry} \
$WORK/tmpfs/etc/rc.d/rcsysinit.d/
mkdir -p $WORK/tmpfs/etc/sysconfig
cp -a /etc/sysconfig/rc $WORK/tmpfs/etc/sysconfig/rc
10. 创建相应的挂载目录:
mkdir -pv $WORK/tmpfs/{proc,sys,media/cdrom}
11. 生成/etc/fstab文件:
cat > $WORK/tmpfs/etc/fstab << EOF
/dev/root / ext2 defaults 0 0
/dev/cdrom /media/cdrom iso9660 defaults 0 0
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
devpts /dev/pts devpts defaults 0 0
EOF
然后,将/dev/cdrom链接起来:
mkdir -p $WORK/tmpfs/lib/udev
cp -a /lib/udev/devices $WORK/tmpfs/lib/udev/
mkdir -p $WORK/tmpfs/etc/udev/rules.d
cat > $WORK/tmpfs/etc/udev/rules.d/75-cd-aliases-generator.rules << EOF
SYSFS{device/media}=="cdrom", SYMLINK+="cdrom"
EOF
12.然后执行./mkbootcd脚本,生成最终的bootcd的iso.这样,用于引导系统的的很迷你的操作系统就生成好了.