红联Linux门户
Linux帮助

LFS系统安装镜像制作

发布时间:2017-04-10 10:40:57来源:linux网站作者:houjian914
这篇文章介绍如何将已完成的LFS系统制作成安装镜像的一种方式。
 
概述
简介
将制作好的LFS系统制作成安装镜像的方式:
将整个Linux文件系统打包,解压到安装机器的磁盘分区,然后安装内核和Grub引导程序就行了。
这个过程通常需要在一个宿主环境中进行,所以可以使用一个LiveCD启动机器,然后执行这个操作。
这个LiveCD必须提供必要的分区工具和Grub引导程序。
可以使用Ubuntu提供的方法定制一个简单的LiveCD镜像,将LFS系统封装在镜像内部,LiveCD启动后自动执行一段脚本程序自动安装LFS系统。
 
制作环境
本次制作过程所使用的环境情况如下:
VMware Workstation 11.1.2
Ubuntu 14.04.5 LTS
在VMware中安装Ubuntu系统作为制作环境,所有操作均在这个Ubuntu系统中进行。
 
基本流程
1.构建一个基本系统,这个系统为LiveCD启动之后的最终系统
2.为LiveCD最终系统做一些个性化的定制、压缩成squashfs文件系统格式
3.配置ISO镜像、引导程序isolinux、封装所需文件到ISO中
4.装载镜像文件测试
 
LiveCD最终系统制作
创建chroot环境
首先进入Ubuntu系统,打开终端。
为了方便起见以下操作全部在root用户下操作,请先切换到root用户:
su -
定义一个环境变量WORK,指向本次实验的工作目录:
export WORK=/opt/work
debootstrap是一个用来构建基本系统的程序,使用这个命令会自动下载一个系统,
这个系统包括Linux文件系统所要求的基本目录结构,我们基于此系统来制作LiveCD的最终系统。
首先安装debootstrap程序:
apt-get install debootstrap
使用debootstrap下载系统,--arch=amd64指定下载64位,trusty为Ubuntu 14.04代号,
chroot为保存目录,最后跟上镜像源地址,
可以更换为较为快速的下载源。
mkdir -pv $WORK/chroot
cd $WORK
debootstrap --arch=amd64 trusty chroot http://mirrors.tuna.tsinghua.edu.cn/ubuntu/
如果想安装基于图形界面的环境,请挂载系统的/dev到chroot环境:
mount --bind /dev $WORK/chroot/dev
复制系统中的网络配置、软件包源到chroot环境,以便切换到chroot后能正常安装软件包
cp /etc/hosts $WORK/chroot/etc/hosts
cp /etc/resolv.conf $WORK/chroot/etc/resolv.conf
cp /etc/apt/sources.list $WORK/chroot/etc/apt/sources.list
导入软件源后还需导入密钥,否则进入chroot环境后无法安装软件。
可以使用apt-key exportall导出本机系统所有密钥到文件中,
进入chroot后再用apt-get add导入这个文件中的密钥。
apt-key exportall > $WORK/chroot/key
准备工作差不多了,现在可以从Ubuntu切到chroot环境中了,使用命令:
chroot $WORK/chroot
现在你已经进入了一个虚拟环境中了,请挂载必须的文件系统,定义环境变量:
mount none -t proc /proc
mount none -t sysfs /sys
mount none -t devpts /dev/pts
export HOME=/root
export LC_ALL=C
导入刚才从主机导出来的密钥文件,成功后就可以将密钥文件删除,然后你就能够使用apt-get命令了:
apt-get add key
rm -f key
更新虚拟环境中的软件包,为后续自定义安装过程做一些准备:
apt-get update
apt-get install --yes dbus
dbus-uuidgen > /var/lib/dbus/machine-id
dpkg-divert --local --rename --add /sbin/initctl
ln -s /bin/true /sbin/initctl
如果你愿意,你也可以在此从软件源更新一下软件包信息:
apt-get --yes upgrade
安装Live System所需要的包:
apt-get install --yes ubuntu-standard casper lupin-casper
apt-get install --yes discover laptop-detect os-prober
apt-get install --yes linux-generic
根据自己的需要安装或卸载一些包,例如安装Vim,删除头文件等等,可选
apt-get install --yes vim
apt-get purge --yes linux-header-3.13.0-96
apt-get autoremove
 
清理chroot环境
所需软件都安装好了,下面开始清理环境,执行清理痕迹、删除垃圾等操作。
如果你安装过软件包,请确保执行命令:
rm /var/lib/dbus/machine-id
rm /sbin/initctl
dpkg-divert --rename --remove /sbin/initctl
虚拟环境中更新操作可能会导致/boot目录下存有多份linux内核文件、
可以通过以下命令移除旧的linux-kernels包,只保留新的。
ls /boot/vmlinuz-3.13.**-**-generic > list.txt
sum=$(cat list.txt | grep '[^ ]' | wc -l)
if [ $sum -gt 1 ]; then
dpkg -l 'linux-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d' | xargs sudo apt-get -y purge
fi
rm list.txt
根据自己的需要精简一些文件,比如mirrors源信息,man手册、doc文档等,可选
rm -rf /var/lib/apt/lists/mirrors.*
rm -rf /usr/share/man/*
rm -rf /usr/share/doc/*
退出之前清理垃圾:
apt-get clean
rm -rf /tmp/*
rm /etc/resolv.conf
卸载所挂载的文件系统,然后退出虚拟环境:
umount -lf /proc
umount -lf /sys
umount -lf /dev/pts
exit
现在又回到Ubuntu系统中了,如果你之前挂载过系统的/dev目录,现在要卸载掉:
umount $WORK/chroot/dev
 
CD镜像与配置
安装制作镜像文件所需的程序包
apt-get install syslinux squashfs-tools genisoimage
创建镜像目录结构,最中会压缩image目录中的内容到ISO镜像中
cd $WORK
mkdir -p image/{casper,isolinux,install}
复制内核与initrd文件到镜像目录中:
cp $WORK/chroot/boot/vmlinuz-3.13.**-**-generic $WORK/image/casper/vmlinuz
cp $WORK/chroot/boot/initrd.img-3.13.**-**-generic $WORK/image/casper/initrd.gz
复制Ubuntu系统的isolinux引导程序到镜像目录中:
cp /usr/lib/syslinux/isolinux.bin image/isolinux/
cp /boot/memtest86+.bin image/install/memtest
 
启动界面
splash.rle图片用来在LiveCD启动的时候显示,splash.jpg图片用来在菜单选择界面当背景显示,
splash.rle文件格式使用如下命令生成:
bmptoppm splash.bmp > splash.ppm
ppmtolss16 '#ffffff=7' < splash.ppm > image/isolinux/splash.rle
cp splash.jpg image/isolinux/
创建boot.msg文件,用来在启动时显示的提示信息,注意第一个字符写入一个特殊字符\x18,
用来指示接下来的字符是一个图片文件名。
printf "\x18" > image/isolinux/boot.msg
然后使用追加模式添加如下提示信息,这样splash.rle图片就能显示了:
cat >> image/isolinux/boot.msg << "EOF"
splash.rle
******************************************************
This is an Ubuntu Remix Live CD.
For the default live system, enter "live". To run memtest86+, enter "memtest"
******************************************************
EOF
 
Boot-loader配置文件
LivdCD通过isolinux.bin文件引导启动,然后根据isolinux.cfg配置文件中的内容来加载启动项,
下面创建启动配置文件,关于
cat > image/isolinux/isolinux.cfg << "EOF"
default vesamenu.c32
prompt 0
timeout 100
display boot.msg
menu background splash.jpg
menu title Welcome to Ubuntu LiveCD!
menu color border 0 #ffffffff #00000000
menu color sel 7 #ffffffff #ff000000
menu color title 0 #ffffffff #00000000
menu color tabmsg 0 #ffffffff #00000000
menu color unsel 0 #ffffffff #00000000
menu color hotsel 0 #ff000000 #ffffffff
menu color hotkey 7 #ffffffff #ff000000
menu color scrollbar 0 #ffffffff #00000000
label lfs
menu label ^Install LFS system
menu default
kernel /casper/vmlinuz
append boot=casper install-lfs initrd=/casper/initrd.gz quiet --
label live
menu label ^Start Ubuntu Remix LiveCD
kernel /casper/vmlinuz
append boot=casper initrd=/casper/initrd.gz quiet --
label check
menu label ^Check CD for defects
kernel /casper/vmlinuz
append boot=casper integrity-check initrd=/casper/initrd.gz quiet --
label memtest
menu label ^Memory test
kernel /install/memtest
append -
label local
menu label ^Boot from first hard disk
localboot 0x80
append -
EOF
上面用到的vesamenu.c32文件,你可以从其它镜像中提取,然后拷贝过来即可
cp vesamenu.c32 image/isolinux/
 
清单文件
创建清单文件,用来记录系统中所安装的软件信息列表:
chroot chroot dpkg-query -W --showformat='${Package} ${Version}\n' | tee image/casper/filesystem.manifest
cp -v image/casper/filesystem.manifest image/casper/filesystem.manifest-desktop
REMOVE='ubiquity ubiquity-frontend-gtk ubiquity-frontend-kde casper lupin-casper live-initramfs user-setup discover1 xresprobe os-prober libdebian-installer4'
for i in $REMOVE
do
sed -i "/${i}/d" image/casper/filesystem.manifest-desktop
done
 
压缩chroot文件系统
压缩chroot系统成squashfs文件系统格式,忽略掉boot目录可以节省一点存储空间:
mksquashfs $WORK/chroot image/casper/filesystem.squashfs -e boot
校验目录大小:
printf $(du -sx --block-size=1 chroot | cut -f1) > image/casper/filesystem.size
 
diskdefines文件
创建diskdefines文件,定义了一些变量对镜像进行描述
cat > image/README.diskdefines << "EOF"
#define DISKNAME  Ubuntu 14.04 Remix
#define TYPE  binary
#define TYPEbinary  1
#define ARCH  amd64
#define ARCHamd64  1
#define DISKNUM  1
#define DISKNUM1  1
#define TOTALNUM  0
#define TOTALNUM0  1
EOF
 
额外信息
添加一些记录额外信息的文件和目录,让某些USB设备识别这个镜像
touch image/ubuntu
mkdir image/.disk
cd image/.disk
touch base_installable
echo "full_cd/single" > cd_type
echo "Ubuntu Remix 14.04" > info
echo "http//your-release-notes-url.com" > release_notes_url
cd ../..
 
封装LFS系统
镜像所需要的文件都已经准备完成,下面来定制一些安装LFS相关的操作。
将现有的LFS文件系统打包成rootfs.tar.gz,/boot下的内核文件打包成boot.tar.gz。
同时准备一个安装脚本install.sh,下面是一个安装脚本示例:
#!/bin/bash
echo "
**********************************************
*   install start *
**********************************************
"
PACKAGE=/home/ubuntu/package
# find the disk
DISK=$(fdisk -l 2>/dev/null | grep "^Disk /dev/[shv]d[a-z]" | cut -c6-13 | head -1)
if [ "$DISK" = "" ]; then
echo "Disk not founded"
exit 0
else
echo "Disk is $DISK"
fi
SWAP=$(cat /proc/swaps | grep "$DISK" | awk '{print $1}')
for s in $SWAP; do
swapoff $s
done
# format disk
echo "format disk $DISK"
dd if=/dev/zero of=$DISK bs=512 count=1 > /dev/null 2>&1
# partition
echo \
"n
p
1
+100M
n
p
2
+2G
n
p
3
w
" | fdisk $DISK > /dev/null 2>&1
sync
BOOT_NUM=1
SWAP_NUM=2
ROOT_NUM=3
DISK_SWAP=${DISK}${SWAP_NUM}
DISK_BOOT=${DISK}${BOOT_NUM}
DISK_ROOT=${DISK}${ROOT_NUM}
# init swap partition
mkswap $DISK_SWAP
# swapon $DISK_SWAP
# init root partition
mkfs -t ext4 $DISK_ROOT > /dev/null 2>&1
mkdir -p /mnt/lfs
mount $DISK_ROOT /mnt/lfs
cd /mnt/lfs
tar zxf $PACKAGE/rootfs.tar.gz
echo "Install Root finished"
# init boot partition
mkfs -t ext4 $DISK_BOOT > /dev/null 2>&1
mkdir -p /mnt/lfs/boot
mount $DISK_BOOT /mnt/lfs/boot
cd /mnt/lfs/boot
tar zxf $PACKAGE/boot.tar.gz
echo "Install Boot finished"
grub-install --root-directory=/mnt/lfs ${DISK}
# init fstab
echo \
"${DISK_ROOT} / ext4 defaults 1 1
${DISK_BOOT} /boot ext4 defaults 1 1
${DISK_SWAP} swap swap pri=1 0 0
proc /proc proc nosuid,noexec,nodev 0 0
sysfs /sys sysfs nosuid,noexec,nodev 0 0
devpts /dev/pts devpts gid=5,mode=620 0 0
tmpfs /run tmpfs defaults 0 0
devtmpfs /dev devtmpfs mode=0755,nosuid 0 0
" > /mnt/lfs/etc/fstab
# init grub.cfg
echo \
"set default=0
set timeout=5
set root=(hd0,${BOOT_NUM})
menuentry \"GNU/Linux, Linux 3.19-lfs-7.7\" {
linux /vmlinuz-3.19-lfs-7.7 root=${DISK_ROOT} ro
}
" > /mnt/lfs/boot/grub/grub.cfg
# check ip address
check_ip() {
echo $1 | grep "^\(\(25[0-5]\|2[0-4][0-9]\|1[0-9]\{2\}\|[1-9][0-9]\|[0-9]\)\.\)\{3\}\(25[0-5]\|2[0-4][0-9]\|1[0-9]\{2\}\|[1-9][0-9]\|[0-9]\)$" > /dev/null
if [ $? -ne 0 ]; then
return 1
fi
ipaddr=$1
a=$(echo $ipaddr | awk -F'.' '{print $1}')
b=$(echo $ipaddr | awk -F'.' '{print $2}')
c=$(echo $ipaddr | awk -F'.' '{print $3}')
d=$(echo $ipaddr | awk -F'.' '{print $4}')
for n in $a $b $c $d; do
if [ $n -gt 255 ] || [ $n -lt 0 ]; then
return 2
fi
done
return 0
}
# init ip address
NETCARD=$(cat /proc/net/dev | grep "eth" | sed -e "s/^\s*\(eth.*\)\:.*$/\1/")
for NET in $NETCARD; do
IP=; read -p "Input IP address for $NET: " IP
check_ip $IP
while [ $? -ne 0 ]; do
read -p "Invalid input. ReInput IP address for $NET: " IP
check_ip $IP
done
GATEWAY=; read -p "Input GATEWAY address for $NET: " GATEWAY
check_ip $GATEWAY
while [ $? -ne 0 ]; do
read -p "Invalid input. ReInput GATEWAY address for $NET: " GATEWAY
check_ip $GATEWAY
done
BROADCAST=$(echo "$GATEWAY" | sed -e "s/^\([0-9]\{1,3\}\.[0-9]*\.[0-9]*\)\.[0-9]*$/\1.255/")
echo \
"ONBOOT=yes
IFACE=$NET
SERVICE=ipv4-static
IP=$IP
GATEWAY=$GATEWAY
PREFIX=24
BROADCAST=$BROADCAST
" > /mnt/lfs/etc/sysconfig/ifconfig.$NET
mkdir -p /mnt/lfs/etc/sysconfig/network-scripts
ln -s ../ifconfig.$NET /mnt/lfs/etc/sysconfig/network-scripts/ifcfg-$NET
echo "Init $NET ip finished"
done
# reset MAC address
rm -f /mnt/lfs/etc/udev/rules.d/70-*
cd /
umount /mnt/lfs/boot
umount /mnt/lfs
echo "
**********************************************
*   install finish   *
**********************************************
The System Will Reboot...
"
sleep 2
reboot
将安装脚本、LFS文件系统、内核文件到复制到镜像目录中:
cd $WORK
mkdir -pv image/packages/package
cp -a ~/install.sh image/packages/
cp -a ~/rootfs.tar.gz image/packages/package/
cp -a ~/boot.tar.gz image/packages/package/
解压image/casper/目录下面的initrd.gz文件,这是一个经过gzip压缩的CPIO格式的归档文件,
解压开来也是一个Linux文件系统,它是Linux系统启动过程中的辅助系统,其根目录下有一个init脚本,内核启动后会执行这个脚本,来初始化系统运行环境,然后将最终系统挂载到/目录下,
最终系统就运行起来了。
cp -a image/casper/initrd.gz ./
gunzip initrd.gz
mkdir build
cd build
cpio -div < ../initrd
rm -f ../initrd
修改init执行流程中的一个脚本程序,添加上我们自己的初始化过程。
scripts/casper-bottom/ORDER文件记录了脚本的执行顺序,
我们在最后追加自己的脚本:
cat >> scripts/casper-bottom/ORDER << "EOF"
/scripts/casper-bottom/99custom_init
[ -e /conf/param.conf ] && . /conf/param.conf
EOF
下面来创建99custom_init这个文件:
cat > scripts/casper-bottom/99custom_init << "EOF"
#!/bin/sh
RCFILE=/root/cdrom/packages/rc.local
if grep -q install-lfs /proc/cmdline; then
if [ -f $RCFILE ]; then
cp -af $RCFILE /root/etc/
fi
fi
EOF
chmod a+x scripts/casper-bottom/99custom_init
99custom_init所做的工作很简单,仅仅是判断一下用户是否选则的菜单项是否是安装LFS系统,
如果是就把镜像中的rc.local拷贝到/etc下。
LiveCD启动后image目录会被挂载到/root/cdrom。
重新压缩initrd.gz文件:
find .|cpio -o -H newc|gzip -9 > ../image/casper/initrd.gz
cd ..
这样做的好处是以后不用解压文件系统了,可以直接修改image/packages下的脚本程序就能修改初始化过程了。
分别创建rc.local和.profile文件,在其中添加安装LFS前的初始化操作
cat > image/packages/rc.local << "EOF"
cp -af /cdrom/packages/* /home/ubuntu/
cat /cdrom/packages/.profile >> /home/ubuntu/.profile
exit 0
EOF
chmod a+x image/packages/rc.local
cat > image/packages/.profile << "EOF"
if [ -f ~/install.sh ]; then
sudo sh ~/install.sh
fi
EOF
packages/.profile里的内容被追加到用户家目录下的.profile中,这样用户一登陆就能够执行了。
 
生成镜像
计算MD5
pushd image
find . -type f -print0 | xargs -0 md5sum | grep -v "\./md5sum.txt" > md5sum.txt
popd
 
创建LiveCD镜像
pushd image
mkisofs -r -V "LiveCD-x86_64" -cache-inodes -J -l -b isolinux/isolinux.bin \
-c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table \
-o ../LiveCD-x86_64.iso .
popd
 
至此LiveCD镜像文件制作完毕,使用虚拟机测试一下。
 
本文永久更新地址:http://www.linuxdiyf.com/linux/29875.html