Linux快速入门之Linux下的软件安装
时间:2006-08-11 来源:ming_nuaa
3.1 Linux内核编译
内核,是一个操作系统的核心。它负责管理系统的进程、内存、设备驱动程序、文件和网络系统,决定着系统的性能和稳定性。Linux作为一个自由软件,在广大爱好者的支持下,内核版本不断更新。通常,更新的内核会支持更多的硬件,具备更好的进程管理能力,运行速度更快、更稳定,并且一般会修复老版本中发现的许多漏洞等,经常性地选择升级更新的系统内核是Linux使用者的必要操作内容。
3.1.1 Linux内核编译的全过程
编译内核并不是一件难事.如果能按照正确的方法来操作,最多花上一个半小时就能搞定。哈哈:)
编译内核共分为四个部分:编译前准备->编译配置->编译过程->运行内核的常见问题
1)编译前准备
①:下载一份内核源代码,我下的是linux-2.6.7.tar.bz2,可在如下地址下载它或者是更新的版本.http://kernel.org/pub/linux/kernel/v2.6/
②:下载最新版本的module-init-tools
("module-init-tools-3.0.tar.gz" and "modutils-2.4.21-23.src.rpm") ③:安装module-init-tools. 替代depmod [/sbin/depmod]和其他工具.
tar -zxvf module-init-tools-3.0.tar.gz
cd module-init-tools-3.0
./configure --prefix=/sbin
make
make install
./generate-modprobe.conf /etc/modprobe.conf
④:安装modutils-2.4.21-23.src.rpm.
可能会看到"user rusty and group rusty not existing"的警告. 没关系,只需强制安装就是了.如果你不对Redhat 9和Redhat 8做这几步, 你将会在"make modules_install"这一步时出现问题.
rpm -i modutils-2.4.21-23.src.rpm
rpmbuild -bb /usr/src/redhat/SPECS/modutils.spec
rpm -Fi /usr/src/redhat/RPMS/i386/modutils-2.4.21-23.i386.rpm
⑤:解压缩内核源代码.把下载的源代码包放到目录/usr/src下,然后
cd /usr/src
tar xvfj linux-2.6.7.tar.bz2
cd linux-2.6.7
2)编译配置
在这一部分涉及几个重要模块的配置请,特别注意.一般用"make menuconfig"命令来配置内核.输入以上命令后出现一个菜单界面,用户可以对需要的模块.下面着重讲几个重要的配置:
①:文件系统
请务必要选中ext3文件系统,
File systems--->
[*] Ext3 journalling file system support
[*] Ext3 Security Labels
[*] JBD (ext3) debugging support
以上三项一定要选上,而且要内建(即标*). 这个非常重要,在配置完后一定要检查一下.config文件有没有"CONFIG_EXT3_FS=y"这一项. 如果不是"CONFIG_EXT3_FS=y"而是"CONFIG_EXT3_FS=m",你在运行内核时就会遇上以下错误: pivotroot: pivot_root(/sysroot,/sysroot/initrd) failed
②:网卡驱动
务必把自己网卡对应的驱动编译进内核,比较普遍的网卡是realtek 8139,以下就是这种网卡的配置,以供参考
Device Drivers--->
Networking support--->
Ethernet (10 or 100Mbit) --->
<*> RealTek RTL-8139 C+ PCI Fast Ethernet Adapter support
<*> RealTek RTL-8139 PCI Fast Ethernet Adapter support
③:声卡驱动
也要选择自己声卡对应的驱动编译进内核,比较普遍的声卡是i810_audio,以下就是这种声卡的配置,以供参考
Device Drivers --->
Sound --->
<*> Sound card support
Advanced Linux Sound Architecture --->
<*> Advanced Linux Sound Architecture
<*> Sequencer support
< > Sequencer dummy client
<*> OSS Mixer API
<*> OSS PCM (digital audio) API[*] OSS Sequencer API
<*> RTC Timer support
PCI devices --->
<*> Intel i8x0/MX440, SiS 7012; Ali 5455; NForce Audio; AMD768/8111
Open Sound System --->
< > Open Sound System (DEPRECATED)
以上三项配置关系到新内核能否正常运行,请备加注意.其他的配置如果不是很了解,大可以按默认的选择。
3)编译过程
按如下命令编译,大概需要一个多小时,大可以好好放松一下
make bzImage
make modules
make modules_install
make install
运行新内核之前,请检查一下/boot/grub/grub.conf的内容,下面的配置可作参考
# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to
this file
# NOTICE: You have a /boot partition. This means that
# all kernel and initrd paths are relative to /boot/, eg.
# root (hd0,0)
# kernel /vmlinuz-version ro root=/dev/hdc3
# initrd /initrd-version.img
#boot=/dev/hdc
default=1
timeout=10
splashimage=(hd0,0)/grub/splash.xpm.gz
title Red Hat Linux (2.6.7)
root (hd0,0)
kernel /vmlinuz-2.6.7 ro root=LABEL=/
initrd /initrd-2.6.7.img
title Red Hat Linux
root (hd0,0)
kernel /vmlinuz-2.4.20-8 ro root=LABEL=/
initrd /initrd-2.4.20-8.img
④:运行内核的常见问题
1)RPM问题
进入编译好的内核后,与RPM相关的命令有些不能使用,并出现下列错误:
rpmdb: unable to join the environment
error: db4 error(11) from dbenv->open: Resource temporarily unavailable
error: cannot open Packages index using db3 - Resource temporarily unavailable (11)
error: cannot open Packages database in /var/lib/rpm
no packages
解决方法是执行“export LD_ASSUME_KERNEL =2.2.25”命令,也可以将其写入/etc/bashrc。
2)Sound问题
声音部分的模块名也改变了。我的笔记本原来的声卡驱动是i810_audio,现在已改为snd-intel8x0。因此需要把下面的内容添加到/etc/modprobe.conf中:
alias char-major-14 soundcore
alias sound snd-intel8x0
alias sound-slot-0 snd-intel8x0
alias snd-card-0 snd-intel8x0
alias sound-service-0-0 snd-mixer-oss
alias sound-service-0-1 snd-seq-oss
alias sound-service-0-3 snd-pcm-oss
alias sound-service-0-8 snd-seq-oss
alias sound-service-0-12 snd-pcm-oss
install snd-intel8x0 /sbin/modprobe --ignore-install sound-slot-0 &&
{/bin/aumix-minimal -f /etc/.aumixrc -L >/dev/null 2>&1; /bin/true; }
remove snd-intel8x0
{/bin/aumix-minimal -f /etc/.aumixrc -S >/dev/null 2>&1; /bin/true;};
/sbin/modprobe -r --ignore-remove sound-slot-0
然后执行“modprobe sound”加载声音模块,并使用下列命令检验声卡驱动:
#cat /proc/asound/cards
显示结果如下:
0 [SI7012]: ICH - SiS SI7012
SiS SI7012 at 0xdc00, irq 11
3)VMware问题
解决方法是:
◆ 将/usr/bin/vmware-config.pl中所有的“/proc/ksyms”替换为“/proc/kallsyms”。使用“sed”命令可以达到这个目的。
◆ 重新运行该脚本,使用内核头文件编译新的内核模块。在编译过程中如发生错误,应该进入/usr/lib/vmware/modules/source,使用下面的命令将vmnet.tar解包:
#tar xvf vmnet.tar
◆进入vmnet-only目录修改bridge.c文件。将“atomic_add(skb->truesize, &sk->wmem_alloc);”修改为“atomic_add(skb->truesize, &sk->sk_wmem_alloc);”,并用类似的方式将“protinfo”改为“sk_protinfo”。
◆ 再次把vmnet-only目录用下面的命令重新打包为vmmon.tar:
#tar cvf vmmon.tar vmnet-only。
如果按照上面的操作依旧失败,另一解决方法是到http://ftp.cvut.cz/vmware/下载vmware-any-any-updateXX.tar.gz,将其解压到任何目录下,执行其中的runme.pl。
4)USB问题
新的2.6.0内核中使用的USB模块大多数已经改名,因此需要修改/etc/rc.sysinit中对USB子系统初始化的代码。将该文件中所有的“keybdev”改为“usbkbd”、“mousedev”改为“usbmouse”、“/proc/bus/usb”改为 “/sys/bus/usb”,并在/etc/init.d/halt中进行同样的修改。此外,还要在/etc/rc.sysinit中找到 “needusbstorage”,做如下修改:
needusbstorage=
if [ $usb = "1" ]; then
needusbstorage=`LC_ALL=C grep -e "^I.*Cls=08" /sys/bus/usb/devices 2>/dev/null`
action $"Initializing USB 1.1 host controller: " modprobe ohci-hcd 2> /dev/null
action $"Initializing USB HID interface: " modprobe hid 2> /dev/null
action $"Initializing USB keyboard: " modprobe usbkbd 2> /dev/null
action $"Initializing USB mouse: " modprobe usbmouse 2> /dev/null
fi
如果USB总线是2.0的,还需将“ohci-hcd”改为“ehci-hcd”。
5)Sysfs问题
解决方法是:
◆ 建立目录/sys:#mkdir /sys
◆ 在/etc/rc.d/rc.sysinit文件中找到“mount -f /proc”,在其下一行加入“mount -f /sys”。
◆ 同样在/etc/rc.d/rc.sysinit文件中找到action $"Mounting proc filesystem: " mount -n -t proc /proc /proc”,在其下一行加入action $"Mounting sysfs filesystem: " mount -n -t sysfs /sys /sys”。
◆ 在/etc/fstab文件中加入“none /sys sysfs defaults 0 0”。
◆ 在/etc/init.d/halt的halt_get_remaining函数中找到“awk ’$2 ~ /^\/$|^\/proc|^\/dev/{next}”,改为“awk ’$2 ~ /^\/$|^\/proc|^\/sys|^\/dev/{next}”。
6)Hotplug(热插拔)问题
内核对热插拔功能的支持与KMOD内核线程有关。
解决方法是将/etc/rc.sysinit中所有的/proc/ksyms替换为/proc/kallsyms。执行如下命令:
#mv /etc/rc.d/rc.sysinit /etc/rc.d/rc.sysinit.bak
#sed -e ’s/\/proc\/ksyms/\/proc\/kallsyms/g’ /etc/rc.d/rc.sysinit.bak > /etc/rc.d/rc.sysinit
7)Glibc问题
用户可以升级Glibc标准库的软件包来解决该问题。因为有些发行版,例如Red Hat 9.0上默认安装的Glibc可能是被Red Hat内核小组修改过的。软件包的下载地址是:
ftp://ftp.rpmfind.net/linux/redhat/updates/9/en/os/i386/glibc-2.3.2-27.9.i386.rpm。
可以连同以下几个软件包一起升级:
ftp://ftp.rpmfind.net/linux/redhat/updates/9/en/os/i386/glibc-common-2.3.2-27.9.i386.rpm
ftp://ftp.rpmfind.net/linux/redhat/updates/9/en/os/i386/glibc-devel-2.3.2-27.9.i386.rpm
ftp://ftp.rpmfind.net/linux/redhat/updates/9/en/os/i386/glibc-utils-2.3.2-27.9.i386.rpm
如果使用“rpm -Uvh glibc*”失败,请用命令“rpm -e”先删除旧的Glibc,然后用命令“rpm -Uvh --force glibc*”强制安装。
8)其它问题
大家也许还会遇到其它问题,但是无论遇上什么问题都可以依照下列步骤尝试解决:
1.内核组件尽可能编译为模块。执行如下命令可以快速重建内核:
#make all modules_install install
2.软件失败的大多数情况是由于模块名已被更改,而/etc/rc.d/rc.sysinit和/etc/rcX.d/*下的脚本却没有修改这些值而导致的。因此,依次修改相关条目可以改进,但是这也需要相当多的背景知识。如果觉得麻烦,可以把所有加载模块的命令集中在 /etc/rc.d/rc.local中。例如:
modprobe eth0
modprobe isofs
modprobe loop
modprobe vfat
同时修改/etc/modoribe.conf文件。具体可参见“man modoribe.conf”获得更多的帮助信息。
3.如果想知道某模块变更后的名字,可以首先在“make menuconfig”时找到该选项,选择Help找到它的配置名称(CONFIG_*),然后到源代码相关目录下的makefile中寻找 CONFIG_*。一般可以找到obj-$(CONFIG_*)一项,其值就是该模块的名字。
3.1.2 Linux内核重编译常见故障分析
在介绍Linux内核重编译常见故障前,假设我们已经按照参考工具书上的步骤对Linux内核进行了相应的配置。
Linux内核重编译通常包括了许多步骤。如果“幸运”的话,Linux内核重编译是可以一次性编译成功的。如果在编译完成后,启动计算机或者内核的时候系统有错误信息的提示,那么最有可能出现的是以下5个:1.内核不能启动;2.异常I/O错误;3.内核反映缓慢;4.内核不能正确编译;5.系统重复启动。下面给出故障分析及其解决方法
1)内核不能启动
当我们重新创建Linux内核时,主要是选择用户需要或不需要在系统中使用的设备及服务。从2.0版内核开始,Linux引入了一个全新的设计特征到内核中并提供了折中方案:组件可以动态的、随时的调入和调出内核。例如我们在修改/etc/lilo.conf之后都要重新启动系统,如果内核不能启动,并且在屏幕上看到了下面的信息:
Warning: unable to open an initial console Kernel panic: no init found. Try passing init= option to kernel |
这个错误最大的可能就是我们没有正确的给/etc/lilo.conf 中的“root=”提供参数。例如,在一个Linux系统中有root=dev/hdc5这样的配置方式,那么这是错误的,正确的应该是root=/dev/hdc5,不要小看只是多了一个 “/”,这是给root提供的重要参数。没有“/”则Linux内核无法确认root到底该从哪里启动。很多朋友往往忽略了这个小细节而造成内核引导失败。下面给出/etc/lilo.conf的一个正确的配置清单,仅供参考。
/etc/lilo.conf示例 |
2)异常I/O错误
如果您重新创建了一个Linux内核,并且能正确启动,但在使用新内核过程中,系统经常出现崩溃、死机等异常现象。那么很可能是I/O出现了问题。I/O异常除了使得系统频繁出现莫名其妙的故障之外,更重要的是会使Linux内核降级,导致整个系统系能严重下降。
究其异常I/O错误的原因,是用户在编译Linux内核结束的时候没有执行“make dep clean”这一步骤。一般来说,在保存Kernel configuration选项中的“menuconfig”或“xconfig”时并不包含“make dep clean”这个步骤。因此,这里建议用户在保存配置后的Kernel configuration选项时注意确认是否已经进行了“make dep clean”这一步。
3)内核反映缓慢
目前很多计算机都采用了高速的CPU和大容量内存。可有时候在创建新内核后系统显得比没有配置内核之前的反映速度慢得多。出现这个情况,很可能是用户在修改Kernel configuration options的时候,在“menuconfig”或者“xconfig”选择了过多的选项。这样不仅使得计算机在编译新内核的时候要花费更多的时间,也使得系统在工作的时候占用了太多的内存。由于很多内存都是被无用的选项所占用,这就导致了系统运行的缓慢。解决方法很简单,尽量选择我们需要的选项,那些无用的,太过于复杂的选项就无需去修改了,有时候使用默认的参数效果会显得更好。
4)内核不能编译
当用户输入“make bzImage modules”并按下输入键的时候,出现了内核不能编译或者其他的奇怪现象。此时最好的方法就是重新启动系统,然后使用“rpm -e”命令移除Kernel configuration tools这个内核配置工具。接着再重新安装这个工具(请使用“rpm -I”或“rpm -Uvh”命令来安装),如果能正确安装,那么问题就简单多了,此时再重新配置内核和再编译应该就能成功。如果还是不能编译内核,请检查硬件设备是不是有问题。
5)系统重复启动
出现这种情况,十有八九是因为在对内核做完修改之后忘记使用LILO来注册新的映象到启动加载程序。LILO需要内核的扇区位置,因此即使是拷贝映象也会将其迁移到新的扇区中,这将使得LILO存储的老指针挂在一个深渊上。
为了解决这个问题,请从软驱启动并运行LILO命令,或使用挽救磁盘启动并安装启动分区到“/mnt”,同时使用如下命令:lilo -r /mnt。
3.2 软件安装
3.2.1 RPM
The Red Hat Package Manager (RPM),是一个开放的软件包管理系统。对于最终用户来说,RPM所提供的众多功能使维护系统要比以往容易的多。RPM维护一个所有已安装的软件包和文件的数据库,可以进行功能强大的软件包查询和验证工作。
RPM 有五种基本的操作方式(不包括创建软件包): 安装, 卸载, 升级, 查询,和验证。本节简要的描述了这五种操作。使用命令 rpm –help可以获得更为全面的信息。
1)安装
RPM 软件包通常具有类似foo-1.0-1.i386.rpm 的文件名。其中包括软件包的名称(foo), 版本号(1.0), 发行号(1), 和硬件平台(i386). 安装一个软件包只需简单的键入以下命令:
$ rpm -ivh foo-1.0-1.i386.rpm
foo ####################################
RPM 将会打印出软件包的名字(并不一定与文件名相同), 而后打印一连串的#号以表示安装进度。软件包的安装被设计的尽量简单易行, 但是可能会发生几个错误:
① 软件包已被安装
如果软件包已被安装, 将会出现以下信息:
$ rpm -ivh foo-1.0-1.i386.rpm
foo package foo-1.0-1 is already installed
error: foo-1.0-1.i386.rpm cannot be installed
如果仍旧要安装该软件包, 可以在命令行上使用--replacepkgs 选项,这将忽略该错误信息。
② 文件冲突
如果要安装的软件包中有一个文件已在安装其它软件包时安装,会出现以下错误信息:
# rpm -ivh foo-1.0-1.i386.rpm
foo /usr/bin/foo conflicts with file from bar-1.0-1
error: foo-1.0-1.i386.rpm cannot be installed
要想让RPM 忽略该错误信息, 可以使用--replacefiles 命令行选项。 ③ 未解决依赖关系
RPM软件包可能依赖于其它软件包,也就是说要求在安装了特定的软件包之后才能安装该软件包。如果在安装某个软件包时存在这种未解决的依赖关系。会产生以下信息:
$ rpm -ivh bar-1.0-1.i386.rpm
failed dependencies:
foo is needed by bar-1.0-1
必须安装完所依赖的软件包,才能解决这个问题。如果想强制安装(这是个坏主意,因为安装后的软件包未必能正常运行), 可以使用--nodeps 命令行选项。
2) 卸载
卸载软件包就象安装软件包时一样简单:
$ rpm -e foo
注意这里使用软件包的名字“foo”,而不是软件包文件的名字foo-1.0-1.i386.rpm。
如果其它软件包依赖于要卸载的软件包,卸载时则会产生错误信息。如:
$ rpm -e foo
removing these packages would break dependencies:
foo is needed by bar-1.0-1
要想RPM忽略该错误信息继续卸载的话(这可不是一个好主意 ,因为依赖于该软件包的程序可能无法运行), 可以使用--nodeps 命令行选项.
3)升级
升级软件包和安装软件包十分类似:
$ rpm -Uvh foo-2.0-1.i386.rpm
foo ####################################
RPM将自动卸载已安装的老板本的foo 软件包。事实上可能总是使用 -U 来安装软件包, 因为即便以往未安装过该软件包,也能正常运行。
因为RPM 执行智能化的软件包升级,自动处理配置文件,将会看到如下信息:
saving /etc/foo.conf as /etc/foo.conf.rpmsave 这表示对配置文件的修改不一定能向上兼容于该软件包中的配置文件。因此,RPM 会备份老文件,安装新文件。应当尽快解决这两个配置文件的不同之处,以使系统能持续正常运行。
因为升级其实就是软件包的卸载与安装的综合,可能会遇见那些操作中所可能发生的错误。有一处不同,那就是当使用旧版本的软件包来升级新版本的软件时,会产生以下错误信息:
$ rpm -Uvh foo-1.0-1.i386.rpm
foo package foo-2.0-1 (which is newer) is already installed
error: foo-1.0-1.i386.rpm cannot be installed
要使RPM 坚持这样“升级”,就使用 --oldpackage 命令行参数。
4)查询
使用命令rpm -q来查询已安装软件包的数据库。简单的使用命令 rpm -q foo 会打印出foo软件包 的包名 ,版本号,和发行号:
$ rpm -q foo
foo-2.0-1
除了指定软件包名以外,还可以连同-q使用以下选项来指明要查询哪些软件包的信息。
· -a 查询所有已安装的软件包.
· -f <file> 将查询包含有文件<file>. 的软件包
· -p <packagefile> 查询软件包文件名为<packagefile>. 的软件包
· -i 显示软件包信息,如描述, 发行号, 尺寸, 构建日期, 安装日期,
平台, 以及其它一些各类信息。
· -l 显示软件包中的文件列表。
· -s 显示软件包中所有文件的状态。.
· -d 显示被标注为文档的文件列表(man 手册, info 手册, etc).
· -c 显示被标注为配置文件的文件列表。
对于那些要显示文件列表的文件, 还可以增加-v 命令行选项以获得如同 ls -l 格式的输出。
5)验证
验证软件包是通过比较compares从软件包中安装的文件和软件包中的原始文件信息来进行的。除了其它一些东西,验证主要是比较文件的尺寸, MD5 校验码, 文件权限, 类型, 属主和用户组等。
rpm-V命令用来验证一个软件包。
命令rpm -V foo 将用来验证foo软件包。又如:
· 验证包含特定文件的软件包:
· rpm -Vf /bin/vi
· 验证所有已安装的软件包:
· rpm -Va
· 根据一个RPM来验证某个软件包:
· rpm -Vp foo-1.0-1.i386.rpm
如果担心RPM数据库已被破坏,就可以使用这种方式。如果一切均校验正常将不会产生任何输出。如果有不一致的地方,就会显示出来。如果有信息输出,应当认真加以考虑,是删除,重新安装,还是修正出现的问题。
要想了解有关RPM的更多信息,可以参阅rpm的man 手册, rpm的屏幕帮助信息(rpm --help), 和以下站点上的RPM 文档资料:http://www.rpm.org/ 。
3.2.2 SRC
1)几种常用文件格式初步处理
*.gz:
常见的压缩格式。“gunzip xxxxxxxxx.gz”或者“tar zxvf xxxxxxxxx.gz”。桌面环境往往带有图形化解压工具,用鼠标点点,不成再用命令。
*.tgz:
常见tar归档加gzip压缩格式。只解成tar归档文件用“gunzip xxxxxxxxx.tgz”,完全解开用“tar zxvf xxxxxxxxx.tgz”。桌面环境往往带有图形化解压工具,用鼠标点点,不成再用命令。
*.bz:
常见tar归档加gzip压缩格式。完全解开用“tar jxvf xxxxxxxxx.bz”。桌面环境往往带有图形化解压工具,用鼠标点点,不成再用命令。
*.tar:
tar归档文件,解压命令为“tar xvf xxxxxxxxx.tar”。桌面环境往往带有图形化解压工具,用鼠标点点,不成再用命令。
*.bin:
没什么好说的了,直接执行吧。
2)安装源代码包
本机编译出来的软件在本机具有最好的执行效率,也能尽量减少软件冲突,源代码包的体积也比二进制包小许多,所以更多的软件都以源代码形式发布。下面讲解详细的安装过程:
1.首先,将安装文件拷贝至你的目录中。例如,如果你是以root身份登录上的,就将软件拷贝至/root中。
#cp xxx.tar.gz /root |
2.由于该文件是被压缩并打包的,应对其解压缩。命令为:
#tar xvzf filename.tar.gz |
3.执行该命令后,安装文件按路径,解压缩在当前目录下。用ls命令可以看到解压缩后的文件。通常在解压缩后产生的文件中,有“Install”的文件。该文件为纯文本文件,详细讲述了该软件包的安装方法。
4.执行解压缩后产生的一个名为configure的可执行脚本程序。它是用于检查系统是否有编译时所需的库,以及库的版本是否满足编译的需要等安装所需要的系统信息。为随后的编译工作做准备。命令为:#./configure。
5.检查通过后,将生成用于编译的MakeFile文件。此时,可以开始进行编译了。编译的过程视软件的规模和计算机性能的不同,所耗费的时间也不同。命令为:#make。
6.成功编译后,键入如下的命令开始安装:
#make install |
7.安装完毕,应清除编译过程中产生的临时文件和配置过程中产生的文件。键入如下命令:
#make clean |
至此,软件的安装结束可以写一个小的脚本,内容如下:
./configure prefix=xxxxxxxxx>../conf_log.txt 2>conf_err.txt
make>../make_log.txt 2>../make_err.txt
make install>../install_log.txt 2>../install_err.txt
init 0
第一行,配置,把配置过程中该显示的东西打到上级目录中的文件“conf_log.txt” ,错误提示进“conf_err.txt”。
第二行,编译,同样把屏幕正常显示和错误提示写入记录文件。
第三行,安装,还把屏幕正常显示和错误提示写入记录文件。
第四行,搞定关机。软件大一点,或者机子旧一点,编译时间都比较长,脚本一运行就可以做其他的事了。当然,也可以不要关机这行,总之不必干等。