Linux发行版制作指南
摘要
此文档着重介绍了Linux发行版制作过程中的各个步骤。(2002-10-08 13:20:09)
1 2 3 下一页
By Coolee
1.项目整体分析
制作Linux发布的目的是为了在系统中能够快速,正确地建立Linux系统环境。制作
Linux发布的主要工作是决定各种软件的去留,因为有了RPM(RedHat Package
Manager)包对其提供优良的管理能力,所以以目前比较成熟的RedHat 7.1(Linux Kernel Version
2.4.2-12)Linux发布程序作为蓝本,以RPM包作为基本的制定单元,以需求为原则对其进行取舍,得到适合实际需要的Linux系统。
由此,项目自然而然的以分析RedHat Linux的光盘安装系统为起点,在掌握了其结构和行为的基础上,在包一级(结构部分)和代码一级(行为部分)进行修改,同时建立相应的测试环境,以便对修改进行及时的规范。
2.项目分步骤实施细节
2.1对Linux光盘安装系统的分析
●结构部分
在安装光盘中,主要的目录结构和文件大致如下:
images/ 此目录下包含了制作启动盘的映像文件(文件后缀img),
其中boot.img是当安装介质为CD-ROM时负责引导系统的映像文件
bootnet.img是当安装介质为FTP,NFS等时负责引导系统的映像文件
driver.img是由一些特殊设备驱动程序模块组成的映像文件,在当前内核不支持这些设备的情况下,提供了对它们进行访问的一种方法
其中,boot.img映像文件中主要包含以下文件:
boot.img
|----vmlinuz Linux内核
|----ldlinux.sys 引导Linux的系统文件
|----syslinux.cfg Linux内核引导参数配置文件
|----initrd.img 内存虚拟文件系统映像文件
|----*.msg文件 引导时的各种提示信息文件
其中,initrd.img为Linux ext2文件系统,构成如下:
initrd.img
|----/bin
|----/dev
|----/etc
|----/module
|----/sbin ------ loader
安装程序装载器
|----/tmp
|----/var
可执行文件/sbin/loader的任务是判断安装介质的有效性,并从中执行安装程序。
其实正是boot.img,在系统启动时被执行,经解析之后在内存建立起了Linux内核,并根据配置文件syslinux.cfg装载虚拟文件系统,形成了完整的Linux System,为后续的工作提供了必要的操作系统环境。Boot.img映像的文件系统类型为msdos,而其中的initrd.img映像的文件系统类型必为Linux系统自己的ext2,所以对于它们的解析操作是不同的,具体请参考附录A 。
RedHat/ 此目录是RedHat Linux发布的核心目录,主要的目录结构都在这里,其中
RPMS/ 包含了RedHat Linux发布的主要部分,即以RPM包的形式将Linux系统中的二进制可执行文件,配置文件,文档等等组织在一起,形成能完成一定功能的比较独立的软件包(文件后缀rpm)。这个目录就是把这些软件包都集合在一起,形成了RedHat Linux发布。
base/ 包含了在安装过程中要用到的描述组织结构和安装行为的所有文件,其中comps,hdlist和hdlist2是描述RPM包组织结构的文件。
comps 此文件把各个RPM包按一定的原则组织成若干组,即components,这样在安装过程中就不必对每一个包做出取舍,而以组为单位。comps文件为简单文本格式,它的结构如下所示:
4 表示RPM包的版本号,当前为4
1 base { }
base是此component名,{…}中是此component中所包含的RPM包
的名称列表,1表示在安装中默认为选中,即默认安装。
0 –hide IDS sensor{
snort
libpcap
}
表示IDS sensor组中包含有snort和lipcap这两个RPM包。0表示
这个组在安装中默认为不选中即默认不安装,并且由—hide指出
不在用户界面上显示此组。
hdlist和hdlist2 这两个文件维护从RPM包名到真实包文件名的映射过程,例如从snort这个RPM包名到真实包文件名snort-1.8.1-1.1.2.i386.rpm的映射。这两个文件是用特殊的程序生成的,无法用简单的方法察看其中的内容和结构。具体的生成方法请参考附录D。
stage2.img , hdstg1.img , hdstg2.img , netstg1.img 和netstg2.img 是描述安装行为的映像文件,其中
stage2.img 是当安装介质为CD-ROM时的安装程序映像文件
hdstg1.img 是当安装介质为HardDisk时的安装程序映像文件
hdstg2.img 是当安装介质为HardDisk时的安装程序映像文件
netstg1.img 是当安装介质为FTP,NFS时的安装程序映像文件
netstg2.img 是当安装介质为FTP,NFS时的安装程序映像文件
这里主要讨论stage2.img的内容
stage2.img
|----/etc
|----/modules
|----/proc
|----/usr----/bin----anaconda
安装程序主执行文件
|
|------/lib-----/anaconda
安装程序脚本文件目录
| |----/installclasses
| |----/iw
| |----/texttw
| |----*.py
|
|------/share---/anaconda
安装程序资源文件目录
| |----/help
| |----/pixmaps
如上所示,stage2.img映像文件中的主要部分是安装程序anaconda,它的主执行体是/usr/bin下的anaconda,由其调用的大量例程分布在/usr/lib/anaconda下,而安装过程中要用到的资源文件分布在/usr/share/anaconda下。stage2.img 的解析方法请参考附录B。
●行为部分
RedHat 7.1的安装程序被命名为anaconda。如前所述,当boot.img所代表的启动介质被系统引导之后,在内存中就建立了一个完整的Linux系统(包括Linux内核和一个内存虚拟文件系统),之后便执行文件系统中存在的loader命令,从适当的介质中执行安装程序(例:安装介质是CD-ROM,就解析CD-ROM上的stage2.img,并从中执行安装程序),即执行anaconda,完成Linux系统的安装任务。
此次利用RedHat 7.1的安装程序源代码的SRPM包形式:anaconda-7.1-5.src.rpm来获得anaconda的源程序,经解包后在/usr/src/redhat/SOURCES/anaconda-7.1形成了源代码树。
anaconda-7.1
|-------------------/bootdisk
启动盘目录
|-------------------/docs
文档目录
|-------------------/help
安装过程帮助系统目录
|-------------------/installclasses
安装类型分类目录
|-------------------/iw
安装各步骤响应目录
|-------------------/loader
安装程序装载器目录
|-------------------/pixmap
图形资源目录
|-------------------/utils
工具目录
|-------------------*.py
各Python脚本文件
分析如下:
anaconda安装程序主要用Python语言写成,它是一种解释性的,面向对象的脚本语言。源文件后缀为.py,也可生成可执行的字节码,后缀为.pyc或.pyo。其中:
installclasses/ 子目录中各文件定义了在安装过程中用户可选择的安装类型,通常由四个文件workstation.py , server.py , laptop.py和custom.py来描述workstation(工作站)安装类型,server(服务器)安装类型,laptop(膝上型电脑)安装类型和custom(自定义)安装类型。每个脚本文件的内部,则是根据自己安装类型的特点对安装步骤,分区策略以及包的取舍做出了不同的方案。
iw/ 子目录中各文件定义了在图形界面安装状态时各步骤对Next(下一步)和Prev(上一步)的响应函数。
loader/ 安装程序装载器的源代码目录,用C语言写成。
pixmap/ 图形资源目录,包括安装过程中使用到的所有位图,图标。
utils/ 安装程序实用工具目录。
anaconda 是安装程序的主执行文件,它建立了Python语言的运行环境,提供了程序的入口点并以模块的方式将各个子系统结合在一起。
gui.py 定义了安装程序图形界面使用的各种窗口类,包括MessageWindow,ProgressWindow,WaitWindow,ExeceptWindow等,和控制这些窗口及图形界面行为的InstallInterface, InstallControlWindow, InstallControlState类。总之,控制gui。
todo.py 定义了安装程序的各种行为函数,它是图形界面背后真正进行各项操作的函数集合。
harddrive.py 定义了当安装介质为硬盘时,系统该如何找到安装程序的光盘映像,并从中执行程序。
安装程序源代码的编译由make和make install组成,完成后在/usr/src/RedHat目录下形成了如下目录结构:
instimage
|------/etc
|------/usr
|------/bin
|------/sbin
|------/lib
| |------/anaconda
| | |------installclasses
| | |------iw
| | |------texttw
| | |------*.py
| |
| |------/anaconda-runtime
| |------/boot/loader
|
|------/share------/anaconda
|------/help
|------/pixmaps
此目录结构基本与stage2.img的文件结构相同。
2.2调试环境的建立:
●对源程序的修改
在分析完安装程序的基本构成之后,就要建立相应的调试环境。建立此环境的目的是为了可以方便地对修改过的安装程序及裁减后的RPM包进行随时的确认。显然,可以选用CD-ROM或本地硬盘作为调试介质,下表比较了两者的差别:
CDROM 硬盘
对应的安装界面 图形界面 菜单界面
对应的映像文件 stage2.img *.iso中的hdstg1.img , hdstg2.img
优点 图形界面,直接使用映像文件stage2.img 随改随调,调试周期短,效率高
缺点 每次改动都要求刻盘,调试效率低 菜单界面,每次调试都要求提供光盘映像文件*.iso,效率上打折扣
在两者各有优缺点的情况下,考虑折衷的方案,即为了首先保证调试的效率,采用硬盘作为调试介质,但对应的映像文件选取stage2.img,这样能达到效率最大化,同时调试界面采取图形方式。采用此方案时,须修改源代码,以达到预期的效果。
从前面对安装系统的分析,可以看出在initrd.img中的/sbin/loader程序负责判断安装介质的有效性,并从中执行安装程序。所以要首先修改它的源代码文件loader.c,从中找出硬盘安装时默认读出光盘映像文件*.iso的函数setupIsoImages,并注释掉其中在硬盘目录中寻找映像文件*.iso的相关操作,具体对应Line 582 至 Line590行中包含sprintf和if(){}循环的语句,以避免打开子目录,并在其后加入mountLoopback("/tmp/hdimage/RedHat/base/stage2.img","/mnt/runtime", "loop0");一句以便实现直接使用stage2.img的目的,并注释掉其后从errno=0开始的代码,经过整个while循环到closedir(dir),但保留umount(“/tmp/hdimage”);注释掉if(!net) return NULL;一句。以上操作目的是防止程序读出光盘映像文件*.iso。在loader.c的主函数main()中的结尾部分,注释掉if (!FL_TESTING(flags)) { 和 }的条件判断的两条语句,让程序毫无疑问地执行硬盘上的安装程序。至此,对loader.c修改完毕。
同时还要对Python脚本的一些相关文件进行修改以保证对stage2.img文件的支持。具体的,在harddrive.py的类class HardDriveInstallMethod中,注释掉函数 mountMedia(self, cdNum)中的所有内容并加Pass语句的方法使此函数失效,同样方法处理umountMedia函数,mountDirectory函数和umountDirectory函数,为了保险起见,在其他函数中注释掉有关上面函数的调用。并在类的构造函数(初始化)中的# Go ahead…语句之前加self.tree=”/tmp/hdimage/”语句,并注释掉后面的所有语句。这样做仍然是要保证废弃iso映像转而对stage2.img实现控制。不仅如此,最好还注释掉todo.py中的Line1781至Line1783调用self.method.systemMounted一段,以确保不出差错。接着进行make和make install,重新编译程序,使修改生效,并把新的loader程序从编译的目标目录中copy到boot.img
Hacking Red Hat Kickstart
By Brett Schwarz on Tue, 2003-04-01 02:00. Software
How to create a single CD for fast and easy customized installation.
Installing
Linux is a relatively easy task. However, I was faced with the task of
installing it on multiple machines repeatedly, which is time consuming
and prone to errors. This problem affected our whole group and other
groups that relied on us. So I started using Red Hat Kickstart to
automate the installs. This helped, but there still was room for
improvement. What I ultimately wanted was an automated installation that
would fit on one CD, dynamically partition the hard drives and contain
all of the updated packages. I wanted to be able to start an
installation then walk away from the machine, returning only when it was
done. To accomplish this, I supplemented Kickstart with a customized
version of the Red Hat installation program, Anaconda.
Although not
officially supported, Red Hat has made available several tools and
documentation to assist in customizing an installation. I describe a few
of the possible ways to do this here, which should give the reader
enough information to get started.
The following topics are covered
in this article: replacing packages with updates, reducing the
installation size to fit on one CD, utilizing Kickstart in the custom
installation and creating a custom message screen.
The reader should
have a good understanding of Linux installations in general. I also
assume that no esoteric hardware is being used, as other customizations
may be needed to accommodate such hardware.
Setting Up the Build Machine
The
first step is to prepare the build computer. Because the installer
tools are specific to a particular release, the build computer needs to
have the same Red Hat release as the one used on the target(s). For our
example, Red Hat 8.0 is being used. There are some differences between
Red Hat 8.0 and previous versions, and you need to investigate them if
you use a previous version.
Once the build computer has the correct
release installed, the Anaconda packages need to be installed. These
usually are not installed by default, so they need to be manually
installed. They are located on the second CD of the standard Red Hat
distribution and are named anaconda, anaconda-runtime and anaconda-help
(optional).
The next step is to create a directory structure where
the installation files will be located. The partition should have
adequate space available, approximately 3GB. The actual location is
based on your preference; for this article, the base directory is
located at /RH80. Under this directory, we create directories for each
of the CDs:
mkdir -p /RH80/CD{1,2,3}
We are not concerned with the source packages, so CD4 and CD5 are not included.
We make an additional directory where we can create the custom installation:
mkdir /RH80/ONE_CD
Now we can copy the contents of the CDs to the respective directories. Mount the first CD, then issue this command:
cp -a /mnt/cdrom/* /RH80/CD1/
Repeat this step for CD2 and CD3.
Copy
the contents of the CD directories to the ONE_CD directory, but hard
link them instead of actually copying the files. This saves space and is
quicker:
cd /RH80
cp -al CD1/* ONE_CD/
cp -al CD{2,3}/RedHat/RPMS/* ONE_CD/RedHat/RPMS/
You'll get an overwrite TRANS.TBL message; you can answer no.
Selecting the Packages
Next
we trim down the contents of the ONE_CD directory so it fits on one CD.
I assume the CD size to be 700MB. I will not go into detail on how to
do this, as the list of files to remove from the distribution is
different from one installation to another. However, here are some tips
for trimming down the distribution:
? Don't include the source RPMs.
? Remove the dosutils directory, as these will be automated installs.
?
Remove any unnecessary packages. This can be complicated, because you
need to make sure that the dependencies are still intact.
You should
keep a record of the files that were removed. You can use this list in
case you need to back out, and you will need it later if you edit the
comps.xml file.
For the package selection, I logged to a file all of
the base and core group packages with their dependencies (according to
the comps.xml file). In order to find this information, I used the
script getGroupPkgs.py (see Resources):
cd /RH80/ONE_CD/RedHat/base
getGroupPkgs.py comps.xml > /RH80/pkglist
Any
additional package names can be appended to the end of this file. After
my list was complete, I removed the packages not on the list by using
the syncRpms.py script (see Resources). The arguments are the package
directory and the list of packages is generated from getGroupPkgs.py.
This script removes the packages not listed in the package list and
prints out the package names. We redirect that to a file so we have a
log:
cd /RH80
syncRpms.py ONE_CD/RedHat/RPMS/ pkglist > pkgs_rem
We
can monitor the installation size by using the du command. The -h
option displays the result in human readable format, and the -s option
gives a summary of the whole directory tree:
du -hs /RH80/ONE_CD
The
hdlist files actually decrease in size after they are regenerated (see
below), because we removed many of the packages. This in turn reduces
the size of the CD image.
The tricky part about removing packages is
they may break dependencies. Even though getGroupPkgs.py resolved the
dependencies base on the comps.xml file, they are not guaranteed to be
accurate. Adding additional packages may break dependencies as well. One
way to verify their accuracy is to create a temporary RPM database, and
then do a test install on that database with the packages you have
selected:
cd /RH80/ONE_CD/RedHat/RPMS
mkdir /tmp/testdb
rpm --initdb --dbpath /tmp/testdb
rpm --test --dbpath /tmp/testdb -Uvh *.rpm
Look
for any error messages regarding failed dependencies. If any appear,
resolve the dependencies by either adding or removing files that caused
the discrepancy, and repeat the above test.
Once the package
dependencies have been resolved, you can download the package updates
pertinent for your installation. Put these files under a separate
directory:
mkdir -p /RH80/updates/RPMS/
Remove the old files
from the build directory and then link the updated files to the build
directory. Do this for each updated package (where old_rpmfile is the
previous version of the package):
cd /RH80/ONE_CD/RedHat/RPMS/
rm
# ... remove each old rpm
cd /RH80/updates/RPMS/
cp -l
# ... do this for each rpm
You
should keep a record of the updated packages, in case you need to back
them out. It's also a good idea to check the dependencies and size one
more time, in case they changed after the packages were updated.
Next, we check the internal checksum of each package with the -K option to rpm. First we need to import the key:
cd /RH80/ONE_CD/RedHat/RPMS
rpm --import /usr/share/rhn/RPM-GPG-KEY
rpm -K *.rpm | grep "NOT *OK"
This isn't strictly necessary, but because we downloaded package updates, this verifies they are valid.
Preparing the Installation Files
Once
all of the packages have been updated, we need to regenerate the hdlist
files. They contain only the headers of the packages, which allows
Anaconda to retrieve the header information more quickly. Because we
updated packages, we need to regenerate these files with the genhdlist
tool, which is part of the anaconda-runtime package:
/usr/lib/anaconda-runtime/genhdlist /RH80/ONE_CD/
Next
we need to handle the comps.xml file. This file defines package groups
and package dependencies (although they are not guaranteed). The file
structure was changed in Red Hat 8.0 to be XML-based; in previous
releases it was only a simple text file with some obscure tags. We need
to ensure that packages defined within groups are included in our
installation. We need to be concerned only with groups we are
installing. If packages are missing (or if packages were added), we need
to edit the comps.xml file (see Resources). Because we chose all of the
packages in the Core and Base groups, however, we don't need to edit
this file. We simply need to specify those groups under the %packages
directive in the Kickstart file. See Listing 1 for an excerpt from the
Kickstart file.
Listing 1. Excerpt from the Kickstart File
Technically,
we can leave out the @Core and @Base groups, as they are installed by
default. They are included here for illustrative purposes.
Creating a Custom Message Screen
We
also want to create a custom message screen to give the user special
instructions. The message screens are kept in the boot.img file (for
CD-ROM installs) under the images directory. This is a DOS filesystem,
so we can mount it to get to the contents:
cd /RH80/ONE_CD/images
mount -o loop -t msdos boot.img /mnt/boot
Looking
in /mnt/boot, you see six message files: boot.msg, options.msg,
general.msg, param.msg, rescue.msg and snake.msg. We create our own
message file and call it custom.msg, an arbitrary name. Because
snake.msg isn't really used, we replace that entry within syslinux.cfg
with custom.msg. Edit syslinux.cfg in /mnt/boot and replace F7 snake.msg
with F7 custom.msg.
A few other modifications were made to the
syslinux.cfg file; refer to Listing 2. The default entry was changed
from linux to ks. If the timeout occurs or if the user presses Enter at
the boot prompt, then the ks label is used. Additionally, the timeout
value was decreased from 600 to 60, so the installation can start sooner
if there is no input from the user. The display entry was changed as
well. Instead of boot.msg being the initial message screen, we wanted
our custom message to be displayed. For the append line under the ks
label, we added two things. The first is the keyword text, to enable
text-based installs. Then we changed the keyword ks to ks=cdrom:/ks.cfg.
This hard codes the Kickstart location so the user doesn't have to
specify it at the boot prompt.
Listing 2. Modified syslinux.cfd File
Next
we create our custom.msg file. Listing 3 shows our custom.msg. The
contents of the file can be marked up, such as adding color around
words. For example, ^O09Custom^O02 changes the color of Custom to blue,
and ^O02 changes it back. See the syslinux reference in the Resources
section for more information.
Listing 3. Custom Message
Once we have composed the custom message, we need to umount the boot image:
umount /mnt/boot
Building the CD
Before
actually creating the CD, you may want to test it by doing a network
install. See the Red Hat Kickstart documentation on how to do this.
We
want this custom installation to be automated, so we put the Kickstart
file on the CD itself. You can create the Kickstart file with any text
editor, or you can use the GUI tool called Kickstart Configurator.
In
the %pre section, add a shell script to probe the hard drives and
dynamically create the partition information based on the number of
drives. We take advantage of the fact that Kickstart executes the %pre
section and then re-reads the Kickstart file. When it reads it for the
second time, it includes the /tmp/partinfo file where the %include
directive is located (see Listing 1). The /tmp/partinfo file is the
output from the script. We use the list-harddrives command, which lists
the available hard drives and their sizes. Having the partition created
dynamically frees us from having to create multiple Kickstart files that
hard code the partition information.
Once the Kickstart file is
created, name it ks.cfg and place it in the root directory of our
installation tree (/RH80/ONE_CD/). It is possible to create more than
one Kickstart file and place all of them on the CD. Different Kickstart
files might address different hardware configurations.
We can now
create the ISO image. From our previous steps, the distribution should
be small enough to fit on one CD and contain all of the updated
packages. The mkisofs program creates the image, and then we can copy
the image to the CD. The command to create the ISO image is:
cd /RH80/ONE_CD
mkisofs -r -T -J \
-V "My Custom Installation CD" \
-b images/boot.img \
-c images/boot.cat \
-o /RH80/mydist.iso \
/RH80/ONE_CD
Refer to Table 1 for a description of the options.
Table 1. Options Used for mkisofs
The
last parameter to mkisofs is the source directory of the contents that
need to be included in the image file (e.g., our custom installation
directory). Several other parameters are available that you may want to
use. For example, the -A, -P and -p options add additional labeling
information to the image. The -m and -x options also allow you to
exclude certain directories and file patterns from the image. See the
mkisofs man page for additional information.
Next, add a checksum to
the ISO image. This is not strictly necessary, but it provides a way for
end users to check the integrity of the CD. The tool to add a checksum
to the ISO image is called implantisomd5. To add a checksum to the ISO
image, use the following command:
implantisomd5 /RH80/mydist.iso
A companion tool, checkisomd5, can be used to verify the checksum for you:
checkisomd5 /RH80/mydist.iso
The CD also can be verified during the installation. After booting from the CD, the user can issue this command:
linux mediacheck
Now
we can burn the image to the CD. I assume the CD writer is already set
up on your system. We use cdrecord below, but you can use other programs
as well. The command is invoked as:
cdrecord -v speed=4 dev=0,0,0 /RH80/mydist.iso
The
speed and dev options depend on your system. The device for the dev
argument can be determined by using the -scanbus option to cdrecord:
cdrecord -scanbus
Using the CD
Once
the image is burned onto the CD, insert the CD into the target machine
and boot the machine. You should get the custom message that you created
earlier. At this point, you can either press Enter at the boot prompt
or let it timeout. When it times out it uses the default label, which we
specified as ks (Kickstart).
If we did everything right, the
installation should proceed without user interaction. In my experience,
the installation takes approximately ten minutes. This may differ
depending on your exact configuration.
Conclusion
With a
combination of Kickstart and a customized Anaconda, a powerful and
flexible installation can be created. This installation greatly improved
cycle time and reduced errors for my project. I was able to install
multiple machines, multiple times almost effortlessly. In this article, I
touched on only a few ways to take advantage of Kickstart and Anaconda,
but there are many other possibilities. I encourage those interested to
read the documentation in the Resources section and to join the
Kickstart and Anaconda mailing lists for further information.
Resources
1、 Distribution Hacking 101: disecting anaconda
2、Editing comps.xml
3、Burning a RedHat CD HOWTO
4、The (unofficial) RedHat 7 Customised Installer mini-HOWTO
5、 Customized RedHat Linux Kickstart Installation Cdrom
你可以看下面这篇文章,我记得几年以前好像还有一个从头做起的howto。你还可以找找中文的。我也看到过。 最近我也想搞自己的一个发行版,针对没用过电脑的,或不想学电脑的。不过今天看到这个才发现已经有很多人搞了,我放弃了。我现在只想贡献点子。
原文:
http://molinux.blog.51cto.com/2536040/548247
阅读(1724) | 评论(0) | 转发(1) |