第一章 简介
事情是如何进行的?
我们将利用一个已经安装好的Linux发布例如:Debian, SuSe, Slackware, Mandrake,
RedHat等等来创建LFS系统。这里不需要任何类型的启动磁盘。我们将使用一个已有的Linux系统作为基础(因为在制作LFS时我们需要编辑器、链
接器、文本编辑器等等工具)。
一旦你已经下载了必要的软件包来创建LFS系统,你就需要创建一个新的Linux主(native)分区来安装LFS系统。
下一步,也就是第五章,将讨论很多软件包的安装,它们将被静态地链接和安装在LFS分区之上。这些软件包组成了一个基本的开发套件被用来安装实际的系统。
第六章讨论如何安装实际的基本系统。我们是用chroot系统来启动一个新的shell,其根(root)目录将被设置为LFS分区。这其实和重
新启动系统将lFS分区作为根文件系统并没有区别。我们不采用重新启动系统,而使用chroot的方法是因为使用这种方法,你可以仍然使用老的系统。当软
件被安装时,你可以简单地转换到以恶果不同的VC(虚拟控制台)或X桌面来继续使用计算机。
当所有的软件被安装第七章将设立启动脚本,第八章将设置Linux启动加载器,这时候你就可以最后重起系统进入LFS系统了。最后一步,在重新启动系统以后是设立网络工具和启动脚本。当完成最后一步,你的LFS系统就可以正常使用了。
这里讨论的是基本的步骤,各个步骤的细节信息将各个章节中讨论,如果这里有些东西你不是完全理解,不要着急。最后这些问题都会变得非常清楚。
细心阅读第二章,因为该章解释了在正式开始着手之前你需要了解的一些重要问题。
本书版本
本书版本为LFS-BOOK-INTEL ver 20010512 dated May 12th, 2001。如果该版本老于一个月,也许一个新的版本已经在LFS站点出版供下载。
下面是到2001年4月12号为止的HTTP和FTP镜象站点。这个列表也许已经不大精确,最新的信息可以在我们的站点得到。
HTTP镜象
Columbus, Ohio, United States -
United States -
Canmore, Alberta, Canada -
Braunschweig, Germany -
Vienna Univ. of Technology, Austria -
Bistrita, Romania -
Oslo, Norway -
Brisbane, Australia -
FTP镜象
Columbus, Ohio, USA [FTP]-
Columbus, Ohio, USA [HTTP]-
Canmore, Alberta, Canada [FTP] -
Canmore, Alberta, Canada [HTTP] -
Vienna Univ. of Tech., Austria [FTP] -
Vienna Univ. of Tech., Austria [HTTP] -
Oslo, Norway [FTP] -
Brisbane, Australia -
致谢
我将感谢下列用户和组织,没有它们无私的帮助LFS工程将不可能开展和发展起来。
Bryan Dumm 提供了运行linuxfromscratch.org的硬件和带宽。
DREAMWVR.COM 它们即将为LFS和相关的子项目捐赠各种资源。
Jan Niemann 提供作为134.169.139.209的镜象。
Johan Lenglet 在运行法语版本的镜象。 .
Michael Peters 致力于苹果的PowerPc版本的LFS系统。
VA Linux Systems 其代表Linux.com为该项目捐赠VA Linux 420(先前是StartX SP2)。
Jesse Tie Ten Quee 捐赠了一个Yamaha CDRW 8824E CD-RW。
Jesse Tie Ten Quee 提供了quasar.highos.com作为的镜象。
O'Reilly捐赠SQL和PHP方面的书。
Robert Briggs捐赠linuxfromscratch.org和linuxfromscratch.com两个域名。
Torsten Westermann运行lfs.linux-provider.net的HTTP和FTP镜象站点。
Dag Stenstad为运行挪威镜象提供了硬件和带宽,Ian Chilton维护了该镜象。
无数其他来自于LFS邮件列表的人们提出了各种建议、测试和提供bug报告。
本书版本修改记录
如果第五章某处进行了修改,一般这就意味着对于其他体系结构版本的同一处地方进行了同样的修改。
20010512 - May 12th, 2001
将SGML格式的文本转换为XML。
第四章:告诉用户使用cfdisk,而不再使用fdisk。fdisk的man文档中推荐使用cfdisk因为cfdisk更加稳定一些。
第四章:对描述语言进行修改以更具有通用性。例如ext2不再是唯一的文件系统选择,Reiserfs现在也逐渐得到广泛的应用。
第四章:更新目录列表以使其兼容于FHS。这主要为了添加opt目录而去掉/usr/tmp和/usr/local/tmp目录。
第五章:添加静态的mawk,texinfo和部分gettext以帮助将Glibc从第五章搬移到第六章。
第五章:添加Makedev到第五章。这里我们并没有创建设备文件,仅仅是拷贝MAKEDEV脚本并创建被用来创建设备文件的一个暂时拷贝。第二
个文件(MAKEDEV-temp)并不包含用户名和组名,而是用户ID和组ID。我们需要一小部分的设备文件来安装Glibc。但是在安装Glibc以
前用户和组名并不被识别,只能使用数字ID来替代。这需要对AKEDEV脚本进行少量的修改,这可以通过对原来的脚本进行打补丁实现。找个补丁在第五章中
完成。同时对两次makedev安装进行了解释。
第五章:推荐以root身份安装所有软件。
第五章:简化了ln命令。
第五章:从tar的make安装中去掉了prefix=$LFS/usr定义。
第五章:现在拷贝内核include目录而不是建立对其的链结。如果需要升级内核,这样从理论上更安全一些。
第五、六章:去掉了fileutils-patch。现在使用升级的fileutils-4.1,补丁不再需要。
第五、六章:添加了fileutils-4.0补丁,其在基于Glibc-2.2的系统上编译fileutils包时是需要的。
第五、六章:从某些软件(bash, diffutils, gzip, sed, m4)安装中去掉了不再需要的--disalble-nls。
第五、六章:从cd dir && make" 修改为"make -C dir" (gettext-static, sysvinit)。
第五章:优化了mawk的静态链结过程。
第五、六章:升级gcc-2.95.2到gcc-2.95.2.1。
第五章:修改在gcc-installation是创建的链结使其指向 $LFS/usr/bin/cpp。
第五、六章:将Glibc从第五章搬移到第六章。
第五、六章:针对使用glibc-2.0.x的原始发布,重新添加了如何拷贝/删除老的NSS库文件。
第五章:添加了关于老版本的install-info的注意信息。
第五章:删除了静态gettext的安装。
第六章:在fileutils一节中将libexecdir=/usr/bin修改为libexecdir=/bin。
第六章:更新Glibc安装命令。创建configparms文件的命令被删除。不需要挑选是使用本身Linux系统的编译器还是LFS的编译器。现在已经是在chroot环境下使用LFS的编译器。
第六章:仅仅拷贝ld.so包中拷贝man页面。不再需要ldconfig和ldd程序。Glibc-2.2.1本身带有了能正常工作的版本。
第六章:将procps安装从使用sed的方式修改为更加容易的方法。
第六章:添加lex符号链结到flex的安装中。
第六章:在bison安装中将yacc脚本中的"$*" 修改为"$@"。"$@"允许使用带用空格的引用的参数。
第六章:在console工具安装时对man页面进行安装时进行了修补。
第六章:当进入chroot环境时,$TERM环境变量被正确的设置。这通过chroot ... -i HOME=/root TERM=$TERM ...命令来实现。
第六章:将inittab文件中的多个不同的sulogin合并为一行。
第六章:修改所有的"rm file && ln -s dest file"为"ln -sf file"。(在glibc、bzip2和gzip的安装中)。
第六章:添加sed来修补在glibc安装时的一个问题。pt_chown不能以setuid root被安装,因为glibc还不能识别root用户。
第六章:修改consoledata/tools为kbd,其目前更加成熟一些,会少出一些安装问题。
第六章:在bing86的安装中将"make PREFIX=/usr install"修改为"make INSTALL_OPTS="-m
755" PREFIX=/usr
install",这能实现防止使用-s进行install命令安装。这可能出现错误是因为有些安装的文件是shell脚本而不是二进制程序。
第六章:去掉ld.so那一部分。一文我们仅仅使用man,所以将其作为安装man页面的一个补丁。
第七章:在funcitong脚本中修改kilproc函数中的延迟问题。现在的实现方法是杀掉进程以后首先检测PID,若需要则休眠两秒钟。更多的细节可以通过阅读该脚本的注释。
第七章:添加在使用LFS时运行级别和启动过程的解释。
第十章:添加这一张。其包含"谢谢,祝好运"的注释并建议创建/etc/lfs-3.0-pre2文件。
第七、八章:搬移/etc/fstab的创建到第八章。
附录A:添加关于Netkit-base和Net-tools包的注释。
附录A:添加findutils-4.1软件包中的frcode,code和bigram的描述。
任何地方:添加了很多FHS兼容性提示,如果希望创建出兼容于FHS的系统就需要听从这些提示。
邮件列表和存档资料
linuxfromscratch.org服务器提供了一下公开的邮件列表:
lfs-discuss
lfs-apps
lfs-announce
lfs-security
alfs-discuss
alfs-docs
alfs-ipc
alfs-profile
alfs-backend
lfs-discuss
lfs-discuss
lfs-discuss邮件列表讨论内容严格地限制于LFS-BOOK。向该邮件列表只能发送关于该书出现的问题,例如报告bug,提供改进该书的建议等等。
任何其他的邮件都应该被发送到lfs-apps邮件列表。
lfs-apps
lfs-apps邮件列表处理除了适合lfs-discuss以外的所有问题。
lfs-announce
该列表是一个单项列表,你可以订阅该列表,但是不能在该列表中张贴任何信息。该列表是用来通告新的稳定发布的。lfs-discuss同时发布一
些关于开发版本的信息。如果一个用户订阅了lfs-discuss邮件列表,那么他就没有必要再订阅该记录因为发到该邮件列表的邮寄同时会发送到lfs-
discuss邮件列表一份。
lfs-security
该邮件列表的讨论安全相关问题。LFS使用的软件包的安全相关或安全问题应该在该邮件列表中讨论。
alfs-discuss
该列表讨论ALFS(Automated Linux From Scratch)系统的开发。该项目的目标是开发一个安装工具能自动安装一个LFS系统。它的主要目标是加速编译过程而无需手工键入命令进行配置、安装软件包。
alfs-docs
该列表是ALFS文档工程,其维护所有的ALFS文档资料。
alfs-ipc
该列表讨论ALFS进程间通信相关问题。
alfs-profile
该列表讨论开发ALFS的XML格式的配置文件和DTD格式文档。
alfs-backend
该邮件列表高论关于ALFS后端相关内容。
邮件列表存档
所有的这些邮件列表存档都可以从下列地址在线阅读:
如何订阅邮件列表?
上面提到的邮件列表都能通过向发送邮件进行订阅,需要将"subscribe listname"作为标题进行订阅。
可以通过一封信件同时订阅多个邮件列表。可以通过将邮件标题设置为空,将所有的命令都放在邮件体中。邮件看上去就是这样的:
To:
Subject:
subscribe lfs-discuss
subscribe lfs-apps
subscribe alfs-discuss
在email被发送以后,Listar程序将回复一封订阅确认信。一旦订阅信被回复,Listar将再次发送一封说明用户已经订阅邮件列表及该邮件列表的简单介绍的信件。
如何退定邮件列表?
为了退定邮件列表需要向发送一封邮件,以"unsubscribe listname"作为邮件主体。
多个列表也可以使用一封电子邮件退定,通过将邮件主体置空,而在邮件正文中包含所有命令,例如:
To:
Subject:
unsubscribe lfs-discuss
unsubscribe lfs-apps
unsubscribe alfs-discuss
Listar将回复一封退定请求确认信,一旦该确认信被回复,Listar将发送一封邮件来通知用户其已经从邮件列表中删除。
其他列表模式
用户可以设置的模式需要通过向发送新建来设置。模式本身通过在邮件主体部分提供适当的命令来进行设置。
Set命令用来设置模式。Unset命令用来取消某个模式。在下面的例子中listname需要被将要设置模式的邮件列表名来替代。如果希望在一个邮件中设置多个模式(对一个列表或多个列表),可以通过将邮件主体置空,而在邮件正文中包含模式命令:
摘要模式
设置命令:set listname digest
取消命令:unset listname digest
所有的邮件列表都可以设置摘要模式,用户在订阅某个邮件列表以后可以设置摘要模式。摘要模式将使用户停止接收邮件列表的单个消息,而是每天只向用户发送一次消息,其包含全天的邮件列表消息。
用户还有一个digest2的摘要模式可以设置,在该模式下用户不但接收邮件列表的单个邮件而且接收每天的摘要。设置digest2的模式和设置digest模式是一样的,只需要将digest替换为digest2。
假期模式
Set command: set listname vacation
Unset command: unset listname vacation
当一个用户出差一段时间或者休假一段时间,而希望停止接收邮件列表消息,但是不希望退定,用户就可以设置一个vocation模式。它同退定一样的效果,但是不需要通过退定过程,最后再通过subscribe过程回复订阅。
联系信息
建议发送所有的邮件到lfs-discuss邮件列表。
如果希望私人地和Gerard联系,可以发送电子邮件到。
第二章 重要信息
关于$LFS环境变量
请仔细阅读下面的下面的信息:本书整个将频繁的使用变量$LFS。$LFS的值必须设置为包含LFS系统的分区加载路径。如何创建及在哪里加载该分区的详细信息将在第四章中讨论。在本书示例中LFS分区被加载在目录/mnt/lfs下。
例如当书中指示运行命令"./configure --prefix=$LFS",你实际上需要运行命令"./configure
--prefix=/mnt/lfs"。重要的是本书中任何地方都需要进行这样的替换,无论是在shell〕中键入的命令还是在创建或编辑修改的文件中。
一个可能的解决方法是设置环境变量LFS,这样在安装系统时就可以直接使用$LFS而无需直接输入/mnt/lfs。这可以通过运行
"export LFS=/mnt/lfs"来实现。如果书中指定使用命令"./configure
--prefix=$LFS",现在就可以直接这么输入命令,shell将自动将$LFS替换为/mnt/lfs。
如果你计划使用$LFS,不要忘记设置环境变量$LFS。若该变量没有被正确设置而在命令中使用,$LFS将被忽略,shell将执行忽略$LFS以后的命令。例如类似这样的命令
echo "root:x:0:0:root:/root:/bin/bash" > $LFS/etc/passwd
就会变为
echo "root:x:0:0:root:/root:/bin/bash" > /etc/passwd
这可能导致系统的passwd文件被覆盖。
一个确保$LFS总是被设置的方法是添加对$LFS的定义到/root/.bash_profile或/root/.bashrc中。这样每次作为root用户登录时或su为root用户时,$LFS变量将被正确设置。
如何下载软件
整个书中都依照惯例将所有下载的软件存放在目录$LFS/usr/src/sources中。在该目录中拥有目录0-9和a-z,所有软件都根据
首字母放置在对应的目录,例如软件sysvinit-2.78.tar.gz将被存放在$LFS/usr/src/sources/s/中;软件bash
-2.04.tar.gz将被存放在目录$LFS/usr/src/sources/b/中。这种安排子目录的方式并不是必须的,只是出于管理方便考虑这
么存放的。最好将软件源代码不要直接存放在$LFS/usr/src下,而应该定义下一级子目录而存放其中。
下一章包含所有需要被下载的软件包的列表,但是由于用户包含LFS系统的分区还没有创建,因此可以将这些文件暂时存放在其他目录中,在LFS分区创建并加载以后将软件拷贝到LFS分区的相应目录。
如何安装软件
在真正开始安装软件包之前首先需要对软件包进行解包。软件包文件常常是tar+bzip2和tar+gzip的包压缩格式。在后面的内容中将不在每个软件包的安装中都讨论如何解压缩,而是在这一部分来讨论如何对软件包进行解压缩。
首先转换到$LFS/usr/src目录中:
cd $LFS/usr/src
若文件是tar+gzip格式,则使用下面的命令进行解压缩:
tar xvzf filename.tar.gz
tar xvzf filename.tgz
若文件为tar+bzip2格式,则需要使用下面的命令解压缩:
bzcat filename.tar.bz2 | tar xv
某些版本的tar命令(但不是全部)是能直接处理bzip2格式文件,这就要在tar命令中使用-I或者-y选项,类似于tar命令处理gzip格式的文件时的-z选项。但是上面的命令则总是能解压tar+bzip2格式的软件。
若某个文件仅仅是tar格式,则通过下面的命令来解包:
tar xvf filename.tar
当一个存档文件被解开,则在当前目录下都会创建一个新的目录(本书假设存档文件在$LFS/usr/src目录中被解包)。在进行进一步安装以
前,首先进入这个新创建的目录,然后继续进行安装。本书后面在讨论关于安装软件的内容时将不设计如何解压源代码存档文件,应该由读者自己完成这一步并进入
新创建的软件目录。
常常你可能处理单个文件,例如补丁文件。这些文件一般都是经过gzip或bzip2压缩的。在使用这些文件之前,首先需要对它们进行解压缩:
gunzip filename.gz
若文件仅仅是被bzip2压缩,则通过下面命令解压缩:
bunzip2 filename.bz2
一旦软件包被安装,还必须做两项工作:包含源代码的目录或者可以被删除或者可以被保持。如果它被保持,而且在随后又需要该软件包,该目录则需要被删除然后重新解包。否则前次安装的配置可能影响到第二次安装。仅仅使用make clean并不能一定消除影响。
因此为了减少麻烦,每次在安装结束以后应该将该源代码目录删除。但是有一个例外是不要删除内核源代码目录,因为很多程序都要使用内核头文件,否则很多程序都不能成功编译。
下载启动脚本
键入第七盒第九章的启动脚本可能是一个非常冗长和无聊的工作,而且容易出现错误,为了节省用户时间,可以从网上现在启动脚本:
或
下载LFS命令
LFS命令是一个tar格式的存档文件,其中包含本书中所有软件安装命令的文件。
这些文件也被用来快速查找在不同的lFS版本之间哪些命令被修改过。下载本书的LFS命令打包文件和以前版本的LFS命令打包文件,然后运行
diff命令来察看不同之处。这个方法可以察看哪些软件包更新了安装命令。因此任何你可以根据版本变化导致到LFS命令变化来选择是否重新安装某个软件
包。
虽然有些文件需要被修改(例如当kbd被安装时需要选择键盘布局文件),这些文件还是可能导致的一个边缘效果是它们可能被用来输出到shell中
来安装软件包。但是请记住这些文件并不一定完全保证其正确性、完整性等等。在文件中可能存在bug,因为这些文件都是手工键入的,所以不要盲目信任这些文
件。
若决定使用这些文件当做脚本,那么不要将这些文件存放在软件包所在目录,例如不要将LFS命令包中的autoconf文件存放在autoconf
目录中。这些文件可能会影响实际的软件源代码目录中的同名文件。autoconf是一个例子:若在autoconf源代码目录中存在有autoconf文
件则configure脚本将不会产生新的autocof文件。那么autoconf配置结束以后,/usr/bin/autoconf可能包含的是
LFS命令包中的autoconf安装指令文件而不是autoconf的真正perl脚本文件。也许有其他的软件有同样的问题,因此不要将LFS命令文件
存放在软件源代码目录中。
可以从下面的地址下载LFS命令包文件:
或
第三章 需要下载的软件包
简介
下面是为创建基本系统需要下载的软件包的列表。其中软件名中的版本号都是基于本书测试通过的、能工作的版本。若出现不能解决的问题(若你使用了更新的版本),那么最好下载本书建议的版本号。
若不能连接到packages.linuxfromscratch.org,那么请尝试连接镜象服务器。镜象站点的地址可以参考第一章的本书版本一节内容。
在附录C的"官方正式下载地址"中我们还提供了各个软件包的官方正式下载站点地址。LFS的FTP服务器仅包含本书推荐使用版本的软件。你能根据
附录C中的地址来查看是某个软件是否当前有新的版本。如果你下载了新版本并成功编译,那么我们将非常高兴听到你使用新版本的软件安装成功的消息。
需要注意的是从LFS的FTP站点下载的软件都是bzip2压缩的格式。若你不知道如何处理bzip2压缩文件格式,参考第二章-如何安装软件一节。
下面的列表的产生时间是:2001.4.2。
需要下载的软件列表
FTP方式浏览软件列表地址:
HTTP方式浏览软件列表地址:
你也可以下载包含所有软件的单个存档包方式,大小为74,140KB,下载地址为:
或者从下面地址单独下载各个软件:
Bash (2.05) - 1,360 KB:
Binutils (2.11) - 7586.95 KB:
Bzip2 (1.0.1) - 410 KB:
Diff Utils (2.7) - 247 KB:
File Utils (4.1) 1217.29 KB:
GCC (2.95.2.1) 9,551 KB:
Linux Kernel (2.4.4) 20,859.16 KB:
Grep (2.4.2) 382 KB:
Gzip (1.2.4a) 178 KB:
Gzip Patch (1.2.4a) 0.49 KB:
Make (3.79.1) 794 KB:
Sed (3.02) 221 KB:
Sh-utils (2.0) 824 KB:
Shellutils Patch (2.0) 0.75 KB:
Tar (1.13) 730 KB:
Tar Patch (1.13) 1.06 KB:
Text Utils (2.0) 1,040 KB:
Mawk (1.3.3) 168 KB:
Texinfo (4.0) 812 KB:
Patch (2.5.4) 149 KB:
MAKEDEV - 7 KB:
Glibc (2.2.1) 10,137 KB:
Glibc-linuxthreads (2.2.1) 149 KB:
Man-pages (1.35) 478 KB:
Man-pages Patch (1.35) 3.2 KB:
Ed (0.2) - 158 KB:
Find Utils (4.1) 226 KB:
Find Utils Patch (4.1) 1.01 KB:
Ncurses (5.2) 1,308 KB:
ftp://packages.linuxfromscratch.org/3.0-pre3/ncurses-5.2.tar.bz2
http://packages.linuxfromscratch.org/3.0-pre3/ncurses-5.2.tar.bz2
Vim-rt (5.7) 905 KB:
Vim-src (5.7) 963 KB:
Bison (1.28) - 321 KB:
Less (358) 178 KB:
Groff (1.17) 1,198.50 KB:
Man (1.5i) 158 KB:
Man Patch (1.5i) 3.24 KB:
Perl (5.6.1) 4,750.30 KB:
M4 (1.4) 249 KB:
Autoconf (2.13) - 333 KB:
Automake (1.4-p1) - 280.33 KB:
Flex (2.5.4a) 278 KB:
File (3.34) - 130 KB:
Libtool (1.4) 604.79 KB:
Bin86 (0.15.5) - 111.58 KB:
Gettext (0.10.37) 760.43 KB:
Kbd (1.05) 585 KB:
E2fsprogs (1.19) - 808 KB:
Lilo (21.7.5) 174.53 KB:
Modutils (2.4.6) 199.20 KB:
Procinfo (18) 22 KB:
Procps (2.0.7) 153 KB:
Psmisc (20.1) 51 KB:
Shadow Password Suite (20001016) 551 KB:
Shadow Password Suite Patch (20001016) 0.40 KB:
Sysklogd (1.4.1) 67 KB:
Sysvinit (2.78) 90 KB:
Sysvinit Patch (2.78) 0.39 KB:
Util Linux (2.11b) 919 KB:
Netkit-base (0.17) 49 KB:
Net-tools (1.60) 193.87 KB:
所有软件的总和大小为:74,500.57 KB (72.75 MB)
第四章 准备新的分区
简介
本章将讨论如何创建存放LFS系统的分区。我们将自行创建分区、文件系统及目录结构。当完成分区创建以后我们将从第五章开始进行实际的创建过程。
创建新的分区
首先声明在原始的Linux所在分区上创建新的LFS系统是可能的。但是并不推荐这样做,因为如果你是新手,可能会出现很多错误。从而导致安装失败,而且将原有的系统破坏。
在可以创建我们新的Linux系统以前,需要有一个空的Linux分区来创建LFS系统。推荐拥有至少750MB大小的分区。这个大小可以保证在
该分区上包含所有的源代码tar包和解包并编译新软件,而无需担心空间不够使用。但是如果你希望安装其他软件那么你可能需要更多的空间,若你已经拥有了一
个空的Linux主分区那么可以跳过这一节。
分区程序cfdisk(另一个fdisk程序)应该以适合的硬盘作为参数启动(例如/dev/hda)。使用cfdisk创建一个Linux主分区,写入分区表然后退出cfdisk程序。如何创建分区请参考man帮助页。
新分区的分区号应该被记住,例如hda11。新创建的分区将被用来安装LFS系统。
在新分区上创建文件系统
一旦分区被创建,下一步将在该分区上创建文件系统。当前linux的标准文件系统是ext2文件系统。但是日志式文件系统正在逐渐被接受。使用何种文件系统是由你自己来决定的,但是这里我们讨论最常见的使用ext2的情况。
为了创建ext2文件系统,使用mke2fs命令。LFS分区被用作参数:
mke2fs /dev/xxx
这里替代"xxx"为你新创建的分区的分区号(例如/dev/hda11)。
加载新分区
现在我们已经创建了可以使用的文件系统,下一步就需要实现能对该文件系统访问,这就需要加载该分区。假设分区被加载在/mnt/lfs目录下。创建/mnt/lfs分区:
mkdir -p /mnt/lfs
加载该LFS分区:
mount /dev/xxx /mnt/lfs
替代"xxx"为LFS分区号。
目录/mnt/lfs就将是$LFS变量的值。若希望使用$LFS变量则需要"export LFS=/mnt/lfs"。
创建目录结构
现在我们根据FHS标准在LFS分区中着手创建目录结构,FHS标准可以在下面地址得到:
使用下面的命令序列就可以创建默认的目录结构:
cd $LFS
mkdir p bin boot dev/pts etc/opt home lib mnt proc root sbin
tmp var opt
for dirname in $LFS/usr $LFS/usr/local
do
mkdir $dirname
cd $dirname
mkdir bin etc include lib sbin share src var
ln s share/man man
ln s share/doc doc
ln s share/info info
cd $dirname/share
mkdir dict doc info locale man nls misc terminfo zoneinfo
cd $dirname/share/man
mkdir man{1,2,3,4,5,6,7,8}
done
cd $LFS/var
mkdir p lock log mail run spool tmp opt cache lib/misc local
cd $LFS/opt
mkdir bin doc include info lib man
cd $LFS/usr
ln s ../var/tmp tmp
一般来讲创建的目录的访问权限为755,但有些目录的访问权限则不同。首先是$LFS/root目录的访问权限应该被设置为0750。这确保不是
所有的用户可以进入root目录(其他用户主目录有同样的访问权限)。第二个修改是对$LFS目录下的所有tmp目录的访问权限设置为1777,以使所有
用户可以写入数据到/tmp或/var/tmp目录,但是不能删除其他用户创建的文件(不能删除其他用户的目录是由sticky位,也就是1777的1来
设定的)。
cd $LFS &&
chmod 0750 root &&
chmod 1777 tmp var/tmp
现在合适的目录结构已经被创建,下面就需要拷贝第三章下载的源代码文件到$LFS/usr/src的相应子目录下。
FHS兼容性注意事项
FHS标准指定/usr/local目录应该包含bin、game、include、lib、man、sbin、和share等几个子目录。你可以修改你的/usr/local目录以保证FHS兼容性。
同样标准指定应该包含/usr/share/games子目录,但是在我们创建系统中我们不不需要该目录。如果需要可以自行创建该目录。
第五章 准备LFS系统
简介
在后面的章节中我们将安装这个基本系统所需要所有软件。完成软件安装以后,你将拥有具有完全功能的Linux系统。后面的章节将讨论如何创建启动脚本、使得LFS系统可自启动和设置基本的网络配置。
本章的软件都是以静态链结方式安装。这些软件将在第六章重新安装。首先以静态连接的方式安装软件的原因是当前系统和将要创建的LFS系统使用的是不同的C库版本。若开始安装的程序使用的是老版本的C库,这些程序可能在LFS系统上工作不正常。
了解Linux的工作原理的关键是知道使用了哪些数据报及为什么用户或系统需要该软件包。在每种软件的安装指示之后都讨论了关于该软件包的内容及其功能描述。
在安装各种软件时很可能会出现很多编译告警消息,这是正常的,可以不加理会。它们仅仅是对C或C++的语法不规范的告警,这可能是因为C语法标准更新导致的原因。
在开始工作以前,确信$LFS变量被正确设定:
echo $LFS
该命令输出应该包含正确的LFS分区目录路径。
以root身份安装软件
在安装软件时最好以root用户进行。这样就会导致所有文件都属于root用户和root组。若一个软件包需要设置特殊的访问权限,则作为root用户可以对这些软件进行特定的设置。
Glibc、gcc及其他的一些软件的安装文档推荐不以root身份编译,但是我们觉得忽略推荐而以root身份编译软件是安全的。很多使用LFS系统的用户这样安装也没有发现任何问题,而且我们在编译过程中也没有遇到任何bug导致出现问题。
安装Bash
Bash安装
使用下面的命令安装Bash:
./configure --enable-static-link --prefix=$LFS/usr --bindir=$LFS/bin --with-curses &&
make &&
make install &&
cd $LFS/bin &&
ln -s bash sh
如果Make install命令输出以下面的内容结束:
install-info: unknown option `--dir-file=/mnt/lfs/usr/info/dir'
usage: install-info [--version] [--help] [--debug] [--maxwidth=nnn]
[--section regexp title] [--infodir=xxx] [--align=nnn]
[--calign=nnn] [--quiet] [--menuentry=xxx]
[--info-dir=xxx]
[--keep-old] [--description=xxx] [--test]
[--remove] [--] filename
make[1]: *** [install] Error 1
make[1]: Leaving directory `/mnt/lfs/usr/src/bash-2.04/doc'
make: [install] Error 2 (ignored)
则说明你可能是在Debian系统上构建LFS系统,而且你的Debian发布中的texinfo软件是老版本的。make
install的错误并不是严重错误。在第六章重新编译动态连接方式的Bash时info已经被安装,因此这里可以忽略这些错误。但是却需要手工重新运行
最后两个命令(cd $LFS/bin &&和ln -s bash sh),因为make
install出现了错误而导致后面两个命令没有执行。
命令解释
--enable-static-link:该配置选项指示bash以静态链结方式编译。
--prefix=$LFS/usr:该配置选项将把Bash的所有文件安装在$LFS/usr目录下,在用户chroot以后,$LFS/usr就会变为/usr目录。
--bindir=$LFS/bin:该配置选项安装可执行程序在目录$LFS/bin中。这是因为bash程序应该安装在/bin,而不是
/usr/bin。这样做的一个原因是/usr可能是一个独立于系统主分区的分区,在分区被加载以前一个用户会需要bash环境(例如没有bash环境启
动脚本将无法执行)。
--with-curses:该参数指定bash链结curses库,而不是使用即将消失的termcap库。
ln -s bash sh:该命令创建名为sh的符号连接指向bash。大多数脚本都通过sh(在脚本第一行定义#!/bin/sh来调用sh)来运行的特定的脚本。
每条命令后的&&使得该命令后的命令只有在该命令正确执行结束的情况下才会继续执行。因为每条命令都只有在前一条命令正确执行的情况下才能执行。
内容
Bash软件包包包含bash shell程序
描述
Bash是一个"Bourne-Again SHell",在作为命令解释器得到了广泛的应用。Bash是一个从标准输入(一般是键盘)读取命令,用户在键盘上输入某些命令,Bash将读取输入加以解析然后执行该程序。
Binutils软件包
安装
使用下面的命令安装Binutils软件包:
./configure --prefix=$LFS/usr --disable-nls &&
make -e LDFLAGS=-all-static tooldir=$LFS/usr &&
make -e tooldir=$LFS/usr install
命令解释
make -e:参数-e指示make命令环境变量要优先于Makefile文件中定义的变量。这对于以静态链结方式编译Binutils是必须的。
LDFLAGS=-all-static:设置变量LDFLAGS的值为-all-static。、,使得binutils以静态方式链结。
tooldir=$LFS/usr:通常tooldir(binutils软件包的可执行程序存放目录)被设置为$(exec_prefix)/
$(target_alias),使用变量代换以后一般为/usr/i686-pc-linux-gnu。但是由于我们仅仅创建自己的系统,因此在$
LFS/usr中不需要这些特殊的目标目录。这只有在系统进行交叉编译(例如在Intel体系结构上编译程序,却在Apple的PowerPC机器执行)
时才会有用。
内容
Binutils软件包包含如下工具程序:
gasp, gprof, ld, as, ar, nm, objcopy, objdump, ranlib, readelf, size, strings, strip, c++filt及 addr2line。
描述
gasp:编译器的宏预处理器。
gprof:显示调用段描述数据。
ld:链结多个对象文件和存档文件,重新定位数据,链结符号引用。常常是编译程序的最后一步被调用。
as:主要用于汇编gcc编译器的输出以供ld使用。
ar:创建、修改和读取存档文件。一个存档文件是一个包含多个其他文件的单个文件,其结构保证了可以从中得到原始的被包含文件。
nm:列出目标文件中的符号。
objcopy:拷贝一个目标文件中的内容到另外一个。objcopy使用GNU的BFD库来读写目标文件。它可以以一种不同于源目标文件的格式来写入目的目标文件。
objdump:显示关于一个或多个目标文件的信息。其参数控制显示哪些信息。这些信息对处理编译工具相关工作的程序员来说是非常有用的,而对于那些仅仅编译程序的程序员来说则没有太大用处。
ranlib:对存档文件的内容生成索引,并将其存放在存档文件中。索引列出是类型为可重定向目标文件的存档成员定义的每个符号。
readelf:显示关于elf格式的二进制文件的相关信息。
size:列出作为参数指定的每个目标文件的块(section)大小和整个大小。默认情况下每个目标文件或每个存档文件中的一个模块输出一行。
strings:对参数中指定的每个文件,strings打印文件中包含的长度至少为连续四个字符的可打印字符串(或者参数中指定的数字)。默认情况下其仅仅输出目标文件的初使和缓加载部分的字符串,对于其他类型的文件,其打印文件所有的内容。
strings主要用于决定非文本文件的内容。
strip:丢弃目标文件中的所有或特定的符号。目标文件列表可能包括存档文件(archives)。至少一个对象文件必须给出。strip修改参数中指定的文件,而不是将修改过的版本写入其他名字的文件中。
c++filt:C++语言提供了函数重载的功能,也就是能编写多个具有同样名字的函数(但是每个函数的参数是不同的)。所有的C++函数名被编
码到较低级别的汇编标号当中。而c++filt程序则进行相反的匹配。它解码低级的标号到用户级的符号名,从而使得链接器能保持这些重载的函数,防止冲
突。
addr2line:将程序地址转译成文件名和行号。给定一个地址和一个可执行程序,它通过使用可执行程序中的调试信息来计算哪个文件名和行号和给定的地址关联。
Bzip2软件包
安装
使用下面命令来安装软件包Bzip2:
sed s/"\$(CC) \$(CFLAGS) -o"/"\$(CC) \$(CFLAGS) \$(LDFLAGS) -o"/ Makefile | make -f - LDFLAGS=-static &&
make PREFIX=$LFS/usr install &&
cd $LFS/usr/bin &&
mv bzcat bunzip2 bzip2 bzip2recover $LFS/bin
命令解释
sed:该命令搜索Makefile文件中的字符串"$(CC) $(CFLAGS) -o"使用$(CC) $(CFLAGS) $(LDFLAGS) -o"来替代。这样使得更容易的以静态方式链结bzip2。
...Makefile | make -f
-:Makefile十sed的最后一个参数,表示这个文件被搜索和替换。sed通常是发送修改过的文本到标准输出(常常为console)中。使用上面
的命令sed的输出将被管道定向到make程序。通常make程序启动时常常试图寻找类似Makefile的文件,但是这里要使用修改过的
Makefile文件内容,因此需要指示make使用修改过的文件内容。"-f
-"参数就是指示make从不是Makefile的其他文件中读取make命令,这里-表示标准输入。另外一个实现方式是将sed的输出定向到一个文件
中,然后指示make从该文件中读取。
LDFLAGS=-static:这是第二种静态链结软件包的方法。这也是最常见的方法。-all-static方式仅仅用于binutils和gettxt软件包,而不用于其他的软件包编译中。
内容
Bzip2软件包包含下列工具程序:
bzip2, bunzip2, bzcat和bzip2recover。
描述
Bzip2:使用Burrows-Wheeler块排列文本压缩算法和霍夫曼编码来压缩文件。压缩比要大于gzip工具使用的基于LZ77/LZ78的压缩算法,接近PPM统计压缩算法族的压缩比。
Bunzip2:解压使用bzip2压缩的文件。
bzcat:(等同于bzip2 -dc)解压缩所有指定的文件到标准输出。
bzip2recover:从被破坏的bzip2文件中回复数据。
Diffutils软件包
安装Diffutils
使用下面命令安装Diffutils
export CPPFLAGS=-Dre_max_failures=re_max_failures2 &&
./configure --prefix=$LFS/usr &&
unset CPPFLAGS &&
make LDFLAGS=-static &&
make install
命令解释
CPPFLAGS=-Dre_max_failures=re_max_failures2:
变量CPPFLAGS是被cpp(C预处理器)使用的。该变量指示预处理器替换re_max_failures的每个实例为
e_max_failures2。这个软件包在某些平台上进行拟稿静态链接方式的编译是可能出现错误(和使用的Glibc版本有关)。定义这个变量能修补
这个错误。
内容
Diffutils包含下列程序:
描述
cmp and diff:这两个命令都是比较两个文件,并打印输出其不同之处。
diff3:比较三个文件的不同。
sdiff:合并两个文件并以交互方式输出结果。
Fileutils软件包
安装
使用下面命令安装 Fileutils软件包:
./configure --disable-nls --prefix=$LFS/usr --libexecdir=$LFS/bin --bindir=$LFS/bin &&
make LDFLAGS=-static &&
make install &&
cd $LFS/usr/bin &&
ln -s ../../bin/install
命令解释
--libexecdir=$LFS/bin: 该配置选项将设定将程序的可执行目录为$LFS/bin,而通常是设定为/usr/libexec目录,但其实在该目录中并不存放任何内容。因为为了防止创建一个空目录,而修改程序可执行目录。
内容
该软件包包含下列程序:
chgrp,chmod,chown,cp,dd,df,dir,dircolors,du,install,ln,ls,mkdir,mkfifo,mknod,mv,rm,rmdir,sync,touch和vdir。
描述
chgrp:修改指定的文件的属组,属组可以使用组名和组ID来指定。
chmod:修改指定文件的访问权限,访问权限可以使用数字方式表示或使用修改某个特定权限的方式修改。
chown:修改指定文件的属主或属组。
cp:拷贝文件。
dd:使用用户可选择的块大小来拷贝文件(默认是从标准输入到标准输出),并在拷贝可以进行对文件进行一定的转换。
df:显示指定文件所在分区的空间情况,若没有指定文件则显示当前加载的所有文件系统的空间情况。
ls, dir和vdir:dir和vdir是带有不通默认输出格式的ls版本。这些程序按照字母顺序显列指定的文件或目录的名字。vidr默认为长格式输出(和ls -l功能相同)。
dircolors:输出设置LS_COLOR环境变量的命令。LS_COLOR变量被用来修改ls等工具软件使用的色彩方案。
du:显示参数指定的对象使用的磁盘空间(如为对象为目录则包括子目录)。
install:拷贝文件并设置它们的访问权限,在需要时还能设定其属主和属组。
ln:创建软链接或硬链接。
mkdir:创建参数指定的名字的目录。
mkfifo:创建参数指定的名字的FIFO。
mknod:创建参数指定的名字的FIFO、字符设备文件或块设备文件。
mv:将一个文件或目录从一个目录搬移到另外一个目录,或重命名文件。
rm:删除文件或目录。
rmdir:删除目录,但是目录必须为空。
shred:安全的删除一个文件,以确保其内容不可恢复。
sync:清空文件系统缓冲到磁盘中。
touch:修改制订文件的访问和修改时间,若指定文件不存在则创建空文件。
安装GCC
GCC的安装
使用下面的命令安装GCC:
mkdir $LFS/usr/src/gccbuild &&
cd $LFS/usr/src/gccbuild &&
../gcc2.95.2.1/configure prefix=/usr \
withgxxincludedir=/usr/include/g++ \
enablelanguages=c,c++ disablenls &&
make e LDFLAGS=static bootstrap &&
make prefix=$LFS/usr local_prefix=$LFS/usr/local \
gxx_include_dir=$LFS/usr/include/g++ install &&
cd $LFS/lib &&
ln s ../usr/bin/cpp &&
cd $LFS/usr/lib &&
ln s ../bin/cpp &&
cd $LFS/usr/bin &&
ln s gcc cc
命令解释
--enable-languages=c,c++: 这个编译参数仅仅安装GCC中的C和C++编译器,如果需要安装其它不常用的编译器,只需要省略"--enable-languages"编译参数即可。
ln -s ../usr/bin/cpp: 创建到$LFS/lib/cpp的符号链接,因为某些程序包指定在/lib下查找cpp。
ln -s ../bin/cpp: 创建到$LFS/usr/lib/cpp的符号链接,因为某些程序包指定在/usr/lib下寻找cpp。
内容
GCC包包含编译器、预处理程序和GNU C++库。
说明
编译器
编译器的功能是将文本格式的源代码编译成计算机能够理解的格式。源代码文件编译成目标文件后,目标代码连接器就会根据这个编译器产生的一个或多个目标文件产生一个可执行文件。
预处理程序
预处理程序或称编译预处理器实现对源代码进行编译前的预处理,例如将源代码中指定的头文件包含进来。通过头文件声明引入代码是一个节省编程时间的非常好的思想。您可以仅仅通过在代码头中插入类似#include
的代码,预处理器就可以将您指定的文件的全部内容插入到需要编译的源代码中。
C++ 库
C++库是C++程序所使用的,C++库包括C++程序中经常使用的函数,这样就可以保证程序员不必要在每次编写新的程序时都重新些某些特定的通用函数(如将文本输出到终端屏幕的函数)。
安装Linux内核
Linux内核的安装
我们不是要编译一个新内核,但会在完成本章的基本系统软件的安装后做这件事。由于某些软件需要内核的一些头文件,所以我们现在需要将内核归档文件解包安装以便编译那些需要内核头文件的程序包。
通过执行下面的命令可以实现内核配置文件的创建工作:
make mrproper &&
yes "" | make config &&
make dep &&
cd $LFS/usr/include &&
cp R ../src/linux/include/linux . &&
mkdir asm &&
cp a ../src/linux/include/asm/* asm
命令解释
make mrproper:这条命令确保内核树(kernel tree)是绝对干净的。
yes "" | make config: 这条命令执行make config并且用缺省值回答config脚本询问用户的每一个问题(它通过简单的等效于用户敲键
以接受问题缺省的Y或N答案来实现)。这里,我们并不是在配置真正的内核,我们仅仅是为了创建一些运行make
dep所必须的配置文件,然后在$LFS/usr/src/linux/include/linux目录下创建一些象version.h一类的文件,这些
文件会在编译Glibc和chroot等其它程序包时需要。
make dep: make dep检查依赖并且设置依赖文件。我们不必关心依赖检查,我们真正关心的是前面提到的make dep在$LFS/usr/src/linux/include/linux目录下创建的后面会用到的一些文件。
cp -R ../src/linux/include/linux . 与 mkdir asm && cp -a
../src/linux/include/asm/*
.:这些命令拷贝内核的头文件到$LFS/usr/include中,如果您想知道为什么我们不再创建这些目录的连接而是拷贝它们,请参阅内核源代码的
README文件。
内容
Linux内核包包含Linux内核。
说明
Linux和每一个Linux系统的心脏,它为系统提供生命的脉搏。当打开计算机电源并且引导Linux系统时,最先载入载入的Linux软件就
是内核。内核初始化系统的硬件组件,诸如:串口、并口、声卡、网卡IDE控制器、SCSI控制器等等。简而言之,内核让软件能够在硬件上得以运行。
安装Grep
Grep的安装
通过下面的命令安装Grep:
export CPPFLAGS=-Dre_max_failures=re_max_failures2 &&
./configure --prefix=$LFS/usr --disable-nls &&
unset CPPFLAGS &&
make LDFLAGS=-static &&
make install
内容
Grep包包含egrep、fgrep和grep程序。
说明
grep:打印文件中匹配扩展正则表达式样板的行。
注:egrep(expression grep)扫描文件搜索一个字符模式,并且打印包含此模式的所有行,egrep使用完全规则表达式(使用字母数字和专用字符完全集作为串值的表达式)来匹配此模式,它使用快速判断算法,但有时需要额外的空间。
fgrep:打印文件中匹配固定串列表(以新行分隔)的行,列表中的固定串必须全部匹配。fgrep与grep和egrep不同之处在于它适用于串,而不是对匹配表达式模式的搜索。
grep:打印文件中匹配基本的正则表达式模式的行。
安装Gzip
Gzip的安装
在安装Gzip以前,必须首先解压缩gzip补丁文件。
patch -Np1 -i ../gzip-1.2.4a.patch &&
./configure --prefix=$LFS/usr &&
make LDFLAGS=-static &&
make install &&
cp $LFS/usr/bin/gunzip $LFS/usr/bin/gzip $LFS/bin &&
rm $LFS/usr/bin/gunzip $LFS/usr/bin/gzip
内容
Gzip包包含compress、gunzip、gzexe、gzip、uncompress、zcat、zcmp、zdiff、zforece、zgrep、zmore和znew程序。
说明
gunzip:解压缩由gzip压缩过的文件。
gzexe:将文件压缩成可以自解压的可执行文件(当然要牺牲一定的压缩性能)。
gzip:通过Lempel-Ziv编码(LZ77)压缩指定文件的大小。
zcat:可以将命令行或其标准输入中指定的一列文件解压缩并将解压缩的数据写到标准输出上。
zcmp:在压缩文件上调用cmp程序。
zdiff:在压缩文件上调用diff程序。
Zforce:强制性地为每一个gzip文件加上.gz扩展名,这样gzip就不会对它们再次进行压缩。这个程序可能在一个文件经过传输后名字被截短的情况下能够派上用场。
zgrep:在压缩文件上调用grep程序。
zmore:是一个过滤器,它允许在一个软拷贝(soft-copy)终端上每次一屏地检查已经压缩过或普通的文本文件(和more程序很相似)。
znew:将.Z (compress)格式的文件转压缩成.gz (gzip)格式。
安装Make
Make的安装
通过下面的命令安装make:
./configure --prefix=$LFS/usr --disable-nls &&
make LDFLAGS=-static &&
make install
内容
Make包包含make程序。
说明
make程序能够自动地确定一个大型程序的哪些片段需要重新编译,并且发出命令去重新编译它们。
安装Sed
Sed的安装
通过下面的命令安装Sed:
export CPPFLAGS=-Dre_max_failures=re_max_failures2 &&
./configure --prefix=$LFS/usr --bindir=$LFS/bin &&
unset CPPFLAGS &&
make LDFLAGS=-static &&
make install
内容
Sed包包含sed程序
说明
sed是一个流编辑器。流编辑器用于在标准的输入流(文件或管道的输入)上完成基本的流转换。
安装Shellutils
Sh-utils的安装
在安装Sh-utils之前,必须首先将sh-utils打包文件解包:
patch -Np1 -i ../sh-utils-2.0.patch &&
./configure --prefix=$LFS/usr --disable-nls &&
make LDFLAGS=-static &&
make install &&
cd $LFS/usr/bin &&
mv date echo false pwd stty $LFS/bin &&
mv su true uname hostname $LFS/bin
内容
Shellutils包含basename、chroot、date、dirname、echo、env、expr、factor、false、
groups、hostid、hostname、id、logname、nice、nohup、pathchk、pinky、printenv、
printf、pwd、seq、sleep、stty、su、tee、test、true、tty、uname、uptime、users、who、
whoami和yes程序。
说明
basename:将文件名上的目录和后缀剥去。
chroot:允许通过指定的根目录运行命令或交互式shell。
date:通过指定格式显示当前时间或设置系统日期。
dirname:从文件名上将非目录后缀剥去。
echo:显示一行文本。
env:更改系统环境,保证程序在新环境中运行。
expr:可以求解表达式的值。
factor:打印所有指定整数的素因子。
false:退出程序时将状态码标识为失败。
groups:打印用户所在的用户组。
hostid:hostid打印当前主机的数字标识符(十六进制格式) 。
hostname:设置或打印当前主机系统的主机名。
id:打印一个用户或当前用户的真实有效的UIDs和GIDs。
logname:打印当前用户的登录名。
nice:通过修改后的调度优先级运行一个程序。
nohup:以避免挂起的方式运行输出不是TTY节点的命令。
pathchk:检查文件名是否有效或可移植。
pinky:是一个可以获得一个指定用户信息的小型finger实用程序。
printenv:打印全部或者部分系统环境配置。
printf:将数据进行格式化并且打印(功能与C语言中的printf函数相同)。
pwd:打印当前工作目录的名字。
seq:是一个序列号程序,它打印一个在特定范围内以指定的增量产生的数值。
sleep:延迟指定量的时间。
stty:改变并且打印TTY终端的行设置。
su:使用替代的用户和组ID运行shell。
tee:从标准输入读取信息并且写到标准输出和文件中。
test:检查文件类型并能够进行值比较。
true:退出时将状态码标识为成功。
tty:打印连接标准输入的终端的文件名。
uname:打印系统信息。
uptime:告诉您系统已经运行了多少时间。
users:打印登录到当前主机的当前用户的用户名。
who:显示谁曾经登录过。
whoami:打印用户的有效userid。
yes:重复地输出 一个字符串知道程序被杀死。
安装Tar
Tar的安装
<