19.构建LFS系统──配置系统启动脚本(一)
时间:2006-11-17 来源:anima
十九、构建LFS系统──配置系统启动脚本(一 )
1.简介
本章详细描述了如何安装并恰当配置启动脚本(LFS-Bootscripts),大多数脚本无需修改就可运行,但少数需要附加配置文件,因为它们与硬件相关。
因为 System-V 风格的初始化脚本被广泛使用,因此本书使用这种风格的脚本,作为补充选项,在 http://www.linuxfromscratch.org/hints/downloads/files/bsd-init.txt 可以找到一个详细设计 BSD 风格启动初始化的提示。在 LFS 邮件列表里搜索"depinit"还可以找到更多选择。
如果您使用其它风格的初始化脚本,请跳过本章继续进行下一章“使LFS系统能够启动”。
2.LFS-Bootscripts-6.2
LFS-Bootscripts 软件包包含一套在 LFS 系统启动和关闭时的启动和停止脚本。
预计编译时间: 0.1 SBU
所需磁盘空间: 0.3 MB
安装依赖于: Bash, Coreutils
安装LFS-Bootscripts
root:/# tar -jxvf sources/lfs-bootscripts-6.2.tar.bz2 -C sources/
root:/# cd sources/lfs-bootscripts-6.2
安装软件包:
root:/sources/lfs-bootscripts-6.2# make install
install -d -m 755 /etc/rc.d/rc0.d
install -d -m 755 /etc/rc.d/rc1.d
install -d -m 755 /etc/rc.d/rc2.d
install -d -m 755 /etc/rc.d/rc3.d
install -d -m 755 /etc/rc.d/rc4.d
install -d -m 755 /etc/rc.d/rc5.d
install -d -m 755 /etc/rc.d/rc6.d
install -d -m 755 /etc/rc.d/rcsysinit.d
install -d -m 755 /etc/rc.d/init.d
install -d -m 755 /etc/sysconfig
install -d -m 755 /etc/sysconfig/network-devices/services
install -m 754 lfs/init.d/checkfs /etc/rc.d/init.d/
install -m 754 lfs/init.d/cleanfs /etc/rc.d/init.d/
install -m 644 lfs/init.d/functions /etc/rc.d/init.d/
install -m 754 lfs/init.d/halt /etc/rc.d/init.d/
install -m 754 lfs/init.d/console /etc/rc.d/init.d/
install -m 754 lfs/init.d/localnet /etc/rc.d/init.d/
install -m 754 lfs/init.d/modules /etc/rc.d/init.d/
install -m 754 lfs/init.d/mountfs /etc/rc.d/init.d/
install -m 754 lfs/init.d/mountkernfs /etc/rc.d/init.d/
install -m 754 lfs/init.d/network /etc/rc.d/init.d/
install -m 754 lfs/init.d/rc /etc/rc.d/init.d/
install -m 754 lfs/init.d/reboot /etc/rc.d/init.d/
install -m 754 lfs/init.d/sendsignals /etc/rc.d/init.d/
install -m 754 lfs/init.d/setclock /etc/rc.d/init.d/
install -m 754 lfs/init.d/sysklogd /etc/rc.d/init.d/
install -m 754 lfs/init.d/swap /etc/rc.d/init.d/
install -m 754 lfs/init.d/sysctl /etc/rc.d/init.d/
install -m 754 lfs/init.d/template /etc/rc.d/init.d/
install -m 754 lfs/init.d/udev /etc/rc.d/init.d/
install -m 754 lfs/init.d/udev_retry /etc/rc.d/init.d/
ln -sf ../init.d/network /etc/rc.d/rc0.d/K80network
ln -sf ../init.d/sysklogd /etc/rc.d/rc0.d/K90sysklogd
ln -sf ../init.d/sendsignals /etc/rc.d/rc0.d/S60sendsignals
ln -sf ../init.d/mountfs /etc/rc.d/rc0.d/S70mountfs
ln -sf ../init.d/swap /etc/rc.d/rc0.d/S80swap
ln -sf ../init.d/localnet /etc/rc.d/rc0.d/S90localnet
ln -sf ../init.d/halt /etc/rc.d/rc0.d/S99halt
ln -sf ../init.d/network /etc/rc.d/rc1.d/K80network
ln -sf ../init.d/sysklogd /etc/rc.d/rc1.d/K90sysklogd
ln -sf ../init.d/network /etc/rc.d/rc2.d/K80network
ln -sf ../init.d/sysklogd /etc/rc.d/rc2.d/K90sysklogd
ln -sf ../init.d/sysklogd /etc/rc.d/rc3.d/S10sysklogd
ln -sf ../init.d/network /etc/rc.d/rc3.d/S20network
ln -sf ../init.d/sysklogd /etc/rc.d/rc4.d/S10sysklogd
ln -sf ../init.d/network /etc/rc.d/rc4.d/S20network
ln -sf ../init.d/sysklogd /etc/rc.d/rc5.d/S10sysklogd
ln -sf ../init.d/network /etc/rc.d/rc5.d/S20network
ln -sf ../init.d/network /etc/rc.d/rc6.d/K80network
ln -sf ../init.d/sysklogd /etc/rc.d/rc6.d/K90sysklogd
ln -sf ../init.d/sendsignals /etc/rc.d/rc6.d/S60sendsignals
ln -sf ../init.d/mountfs /etc/rc.d/rc6.d/S70mountfs
ln -sf ../init.d/swap /etc/rc.d/rc6.d/S80swap
ln -sf ../init.d/localnet /etc/rc.d/rc6.d/S90localnet
ln -sf ../init.d/reboot /etc/rc.d/rc6.d/S99reboot
ln -sf ../init.d/mountkernfs /etc/rc.d/rcsysinit.d/S00mountkernfs
ln -sf ../init.d/modules /etc/rc.d/rcsysinit.d/S05modules
ln -sf ../init.d/udev /etc/rc.d/rcsysinit.d/S10udev
ln -sf ../init.d/swap /etc/rc.d/rcsysinit.d/S20swap
ln -sf ../init.d/checkfs /etc/rc.d/rcsysinit.d/S30checkfs
ln -sf ../init.d/mountfs /etc/rc.d/rcsysinit.d/S40mountfs
ln -sf ../init.d/udev_retry /etc/rc.d/rcsysinit.d/S45udev_retry
ln -sf ../init.d/cleanfs /etc/rc.d/rcsysinit.d/S50cleanfs
ln -sf ../init.d/setclock /etc/rc.d/rcsysinit.d/S60setclock
ln -sf ../init.d/console /etc/rc.d/rcsysinit.d/S70console
ln -sf ../init.d/localnet /etc/rc.d/rcsysinit.d/S80localnet
ln -sf ../init.d/sysctl /etc/rc.d/rcsysinit.d/S90sysctl
if [ ! -f /etc/sysconfig/createfiles ]; then install -m 644 lfs/sysconfig/createfiles /etc/sysconfig/; fi
if [ ! -f /etc/sysconfig/modules ]; then install -m 644 lfs/sysconfig/modules /etc/sysconfig/; fi
if [ ! -f /etc/sysconfig/rc ]; then install -m 644 lfs/sysconfig/rc /etc/sysconfig/; fi
install -m 754 lfs/sysconfig/network-devices/ifup /etc/sysconfig/network-devices/
install -m 754 lfs/sysconfig/network-devices/ifdown /etc/sysconfig/network-devices/
install -m 754 lfs/sysconfig/network-devices/services/ipv4-static /etc/sysconfig/network-devices/services/
install -m 754 lfs/sysconfig/network-devices/services/ipv4-static-route /etc/sysconfig/network-devices/services/
root:/sources/lfs-bootscripts-6.2#
Contents of LFS-Bootscripts
Installed scripts: checkfs, cleanfs, console, functions, halt, hotplug, ifdown, ifup, localnet, mountfs, mountkernfs, network, rc, reboot, sendsignals, setclock, static, swap, sysklogd, template, udev
简要描述
checkfs |
在挂载之前检查文件系统完整性(日志文件系统和基于网络的文件系统除外) |
cleanfs |
删除系统重启后就不需要保存了的文件,例如在 /var/run/ 和 /var/lock/ 目录下的文件;重新创建 /var/run/utmp 文件并删除可能存在的 /etc/nologin, /fastboot, /forcefsck 文件。 |
console |
为指定的键盘布局读入正确的键盘映射表,并设置屏幕字体。 |
functions |
包含在不同脚本中共用的一些函数,例如错误和状态检查函数。 |
halt |
关闭系统 |
hotplug |
为系统设备加载模块 |
ifdown |
协助 network 脚本停止网络设备 |
ifup |
协助 network 脚本启动网络设备 |
localnet |
设置系统主机名和本地回环(loopback)设备 |
mountfs |
挂载所有文件系统,有 noauto 标记或者基于网络的文件系统除外。 |
mountkernfs |
用来挂载内核提供的文件系统,例如 proc |
network |
设置网络连接,例如网卡等;并设置默认网关(如果可用) 。 |
rc |
主要的运行级控制脚本,负责让所有其它脚本按符号链接名确定的顺序一个接一个的运行。 |
reboot |
重新启动系统 |
sendsignals |
在系统重启或关闭系统之前,确保每一个进程都已经终止了。 |
setclock |
如果硬件时钟没有设置为 UTC 时间,将内核时钟重置为本地时间。 |
static |
提供为网络接口指派静态 IP 地址的功能 |
swap |
启用或禁用交换文件和交换分区 |
sysklogd |
启动或停止系统和内核日志守护进程 |
template |
为其它守护进程创建自定义启动脚本的模板 |
udev |
启动 udev 并在 /dev 目录创建设备节点 |
3.启动脚本是如何工作的?
Linux 使用的是基于 运行级(run-levels) 概念的称为 SysVinit 的专用启动工具。它在不同的系统上可能是完全不一样的,所以不能认为一个脚本在某个 Linux 发行版上工作正常,于是在 LFS 中也会正常工作。LFS 有自己的一套规则,当然,LFS 也遵守一些公认的标准。
SysVinit(从现在开始我们称之为"init")以运行级的模式来工作,一般有 7 个运行级(从 0 到 6,实际上可以有更多的运行级,但都是用于特殊情况而且一般使用不到。 参见 init(8) 以获得更多信息),每个运行级对应于一套设定好的任务,当启动一个运行级的时候,计算机就需要执行相应的任务。默认的运行级是 3,下面是对不同运行级的描述:
0: 停止计算机
1: 单用户模式
2: 无网络多用户模式
3: 有网络多用户模式
4: 保留作自定义,否则同运行级 3
5: 同运行级 4,一般用于图形界面(GUI)登录(如 X 的 xdm 或者 KDE 的 kdm)
6: 重新启动计算机
用来改变运行级的命令是 init [runlevel] ,这里的 [runlevel] 是目标运行级。例如,要重启计算机,用户可以运行 init 6 命令,reboot 其实只是这个命令的别名,同样,halt 命令也只是 init 0 的别名。
在 /etc/rc.d 目录下有一些类似于 rc?.d 的目录(这里 ? 是运行级的数字)以及 rcsysinit.d ,里面都包含许多符号链接,其中一些以 K 字母开头,另外一些以 S 字母开头,这些链接名在首字母后面都跟着两个数字。K 字母的含义是停止(杀死)一个服务,S 字母的含义是启动一个服务。而数字则确定这些脚本的启动顺序,从 00 到 99(数字越小执行的越早)。当 init 转换到其它运行级时,一些相应的服务会停止,而另一些服务则会启动。
真正的脚本则在 /etc/rc.d/init.d 目录下,它们完成实际工作,符号链接都是指向它们的。停止脚本的链接和启动脚本的链接都指向 /etc/rc.d/init.d 目录下同一个脚本,这是因为调用这些脚本时可以使用不同的参数,例如 start, stop, restart, reload, status 当调用 K 链接时,相应的脚本用 stop 参数运行;当调用 S 链接时,相应的脚本用 start 参数运行。
上面的说明有一个例外,在 rc0.d 和 rc6.d 目录下以 S 开头的链接不会启动任何东西,而是用 stop 参数调用,来停止某些服务。这背后的逻辑是,当用户要重启或关闭系统的时候,不会要启动什么服务,只会要系统停止。
以下是脚本参数的描述:
start 启动服务 stop 停止服务 restart 停止服务,然后再启动 reload 该服务的配置已更新。如果修改了某个服务的配置文件,又不必重启这个服务的时候,可以使用这个参数。 status 显示服务的状态,如果服务正在运行,会显示该服务进程的 PID 。您可以自由修改启动进程工作的方式(毕竟这是您自己的 LFS 系统),我们这里给出的文件只是它们怎样工作的一个示例而已。
4.LFS系统设备和模块处理
在安装系统基础软件里,我们安装了 Udev 软件包,在开始深入讨论它如何工作之前,我们先简要回顾一下以前处理设备的方法。
传统上一般 Linux 系统使用创建静态设备的方法,因此在 /dev 目录下创建了大量的设备节点(有时会有数千个节点),而不管对应的硬件设备实际上是否存在。这通常是由 MAKEDEV 脚本完成的,这个脚本包含许多调用 mknod 程序的命令,为这个世界上可能存在的每个设备创建相应的主设备号和次设备号。而使用 udev 方式的时候,只有被内核检测到的设备才为其创建设备节点。因为每次系统启动的时候都要重新创建这些设备节点,所以它们被存储在 tmpfs 文件系统(一种完全存在于内存里,不占用任何磁盘空间的文件系统)上,设备节点不需要很多磁盘空间,所占用的内存可以忽略不计。
4.1.历史
2000 年 2 月的时候,2.3.46 版本的内核引入了一种称为 devfs 的文件系统,在 2.4 系列稳定版本的内核中都是可用的。尽管它存在于内核源代码中,但这种动态创建设备的方法却从未得到核心内核开发者们的全力支持。
devfs 存在的主要的问题是它处理设备检测、创建和命名的方式,其中设备节点的命名可能是最严重的问题。一般可接受的方式是,如果设备名是可配置的,那么设备命名 策略应该由系统管理员决定,而不是由某些开发者强制规定。devfs 文件系统还存在竞争条件(race conditions)的问题,这是它天生的设计缺陷,不对内核做彻底的修改就无法修正这个问题。因为近来缺乏维护,它已经被标记为 deprecated(反对的)。
随着非稳定的 2.5 内核树的开发,即后来发布的 2.6 系列稳定版本内核,一种被称为 sysfs 的新虚拟文件系统诞生了。sysfs 的工作是把系统的硬件配置视图导出给用户空间的进程。由于有了这个用户空间可见的表示,代替 devfs 方案的时机就成熟了。
4.2.Udev实现
4.2.1.Sysfs文件系统
上面简单的提到了 sysfs 文件系统,您可能想知道 sysfs 是怎么认出系统中存在的设备以及应该使用什么设备号。对于已经编入内核的驱动程序,当被内核检测到的时候,会直接在 sysfs 中注册其对象;对于编译成模块的驱动程序,当模块载入的时候才会这样做。一旦挂载了 sysfs 文件系统(挂载到 /sys), 内建的驱动程序在 sysfs 注册的数据就可以被用户空间的进程使用,并提供给 udev 以创建设备节点。
4.2.2.Udev启动脚本
S10udev 初始化脚本负责在 Linux 启动的时候创建设备节点,该脚本首先将 /sbin/udevsend 注册为热插拔事件处理程序。热插拔事件(随后将讨论)本不应该在这个阶段发生,注册 udev 只是为了以防万一。然后 udevstart 遍历 /sys 文件系统,并在 /dev 目录下创建符合描述的设备。例如,/sys/class/tty/vcs/dev 里含有"7:0"字符串,udevstart 就根据这个字符串创建主设备号为 7 、次设备号为 0 的 /dev/vcs 设备。udevstart 创建的每个设备的名字和权限由 /etc/udev/rules.d/ 目录下的文件指定的规则来设置,这些文件以类似于 LFS 启动脚本风格的编号。如果 udev 找不到所创建设备的权限文件,就将其权限设置为缺省的 660 ,所有者为 root:root 。
上面的步骤完成后,那些已经存在并且已经内建驱动的设备就可以使用了,那么以模块驱动的设备呢?
前面我们提到了"热插拔事件处理程序"的概念,当内核检测到一个新设备连接时,内核会产生 一个热插拔事件,并在 /proc/sys/kernel/hotplug 文件里查找处理设备连接的用户空间程序。udev 初始化脚本将 udevsend 注册为该处理程序。当产生热插拔事件的时候,内核让 udev 在 /sys 文件系统里检测与新设备的有关信息,并为新设备在 /dev 里创建项目。
这样带来了 udev 存在的一个问题,之前 devfs 也存在同样的问题。这通常是个"先有鸡 还是先有蛋"问题。大多数 Linux 发行版通过 /etc/modules.conf 配置文件来处理模块加载,对某个设备节点的访问导致相应的内核模块被加载。对 udev 这个方法就行不通了,因为在模块加载前,设备节点根本不存在。为了解决这个问题,在 LFS-Bootscripts 软件包里加入了 S05modules 启动脚本,以及 /etc/sysconfig/modules 文件。通过在 modules 文件里添加模块名,就可以在系统启动的时候加载这些模块,这样 udev 就可以检测到设备,并创建相应的设备节点了。
注意,在慢速的机器上,或者对于需要创建大量设备节点的驱动程序,创建设备的过程可能需要好几秒钟,这意味着某些设备节点不能立即访问到。
4.2.3.设备节点创建
为了得到正确的主次设备号,Udev 依赖于 /sys 目录下的 sysfs 提供的信息。例 如, /sys/class/tty/vcs/dev 包含字符串 "7:0",被 udevd 用来创建主设备号是7、次设备号是0的设备节点。在 /dev 目录下创建的设备节点的名字和权限由/etc/udev/rules.d/ 目录下相应的规则决定。这 些以类似的形式包含在 LFS-Bootscripts 包中。 如果 udevd 不能为它现在创建的设备发现一个规则,它会默认把权限设置为 660 ,属主设置为 root: root。Udev 规则语法的文档可以查看 /usr/share/doc/udev -096/index.html。
4.2.4.模块加载
被编译成模块的设备驱动可能有编译进去的别名。别名可以通过 modinfo 程序的输出来查看,通常与设备总线特 有的标识有关(模块要支持)。例如,snd-fm801 驱动支持 PCI 设备,通过生产厂商 ID 0x1319 和设备 ID 0x0801,有一个别名"pci:v00001319d00000801sv*sd*bc04sc01i*"。 对于大多数的设备,总线驱动通过 sysfs 导出可能会处理的设备驱动的别名。例如,/sys/bus/pci/devices/0000:00:0d.0/modalias 文件可能包含字符串"pci:v00001319d00000801sv00001319sd00001319bc04sc01i00"。 LFS 安装的规则会导致 udevd 调用 /sbin/modprobe 处理热插拔事件环境变量 MODALIAS 的内容(应该与 sysfs 中的 modalias 文件的内容一样)。 因此在通配符扩展之后,加载所有的别名匹配这个字符串的模块。
这个例子中,除了 snd-fm801,荒废的(不想要的) forte 驱动会被加载(如果它是有效的)。 查看下面的方法来避免加载不想要的模块。
内核能在后台加载有关网络协议、文件系统和 NLS(国际语言支持) 支持的模块。
4.2.5.处理可热插拔/动态设备
当您插入一个设备,例如一个 USB 接口的 MP3 播放器,内核会检测到设备连接,并产生一个热插拔事件,如果驱动程序已经加载(要么是因为驱动已经编入内核,要么是已经通过 S05modules 启动脚本加载了),udev 将被调用,并根据 /sys 目录下的 sysfs 数据来创建相应的设备节点。如果该设备的驱动是一个未加载的模块,将设备连接到系统上只会让内核的总线驱动产生一个热插拔事件,通知用户空间有新设备连 接,但并不加载驱动。事实上,什么都没有做,设备仍然不能使用。
如果刚才插入的设备有一个驱动程序模块但是尚未加载,Hotplug 软件包就有用了,它就会响应上述的内核总线驱动热插拔事件并加载相应的模块,为其创建设备节点,这样设备就可以使用了。
4.3.创建设备的问题
自动创建设备节点的时候,存在一些已知的问题:
4.3.1.内核模块没有自动加载
如果有一个总线特有的别名,并且总线驱动器导出必需的别名到 sysfs,那么 Udev 将只会加载一个模块。在其他情况下,需要安排其他的模块加载方式。在 Linux-2.6.16.27 中,Udev 为INPUT, IDE, PCI, USB, SCSI, SERIO 和 FireWire 设备加载适当的驱动。
为了确定你请求的设备驱动 Udev是否支持,可以以模块的名字为参数运行 modinfo。 现在把设置设备目录到 /sys/bus ,检测那里是否有一个 modalias 文件。
如果 modalias 文件存在于 sysfs 中,驱动程序支持设备可以直接通信,但是没有别名,这是驱动中的一个 bug。不利用 Udev 的帮助加载驱动,希望在以后这个问题会被修正。
如果在 /sys/bus下的相应目录内没有 modalias 文件,这就意味着内核开发者没有添加对这种总线类型的模块别名支持。在 Linux-2.6.16.27中,ISA 总线就是这种情况。希望在下个内核版本中会修正这个问题。
Udev 根本不会加载 "封装" 驱动像 snd-pcm-oss,和 非硬件驱动器像 loop。
4.3.2.内核模块没有自动加载,并且Udev也不加载
如果 “封装” 模块增强其他模块提供的功能(例如,snd-pcm-oss 增强 snd-pcm 的功能,使声卡对于 OSS 程序可用),配置 modprobe 使其在加载了相应模块后加载其封装模块。在 /etc/modprobe.conf 中添加一个 "install" 行来实现,例如:
install snd-pcm /sbin/modprobe -i snd-pcm ; \
/sbin/modprobe snd-pcm-oss ; true
如果模块不是一个封装,而是对自己本身有用,配置 S05modules 启动脚本使其在系统启动的时候加载。 要实现这个,在 /etc/sysconfig/modules 文件的相应行上添加模块的名字。这对于封装模块也有用,但不是最优的。
4.3.3.Udev加载了不需要的模块
在下面例子中,对于 forte 模块,可以不编译它或者是在 /etc/modprobe.conf 文件中列入黑名单:
blacklist forte
列入黑名单的模块仍然能够通过 modprobe 命令手工加载。
4.3.4.Udev错误的创建了设备或创建了错误的符号链接
如果规则匹配不是预想的设备,那么这种情况就会经常发生。例如,一个写的很糟糕的规则通过计算机提供商匹配到一个 SCSI 硬盘(期望的)和一个一般的 SCSI 设备(错误的)。找出这些不合格的规则,更正他们。
4.3.5.Udev规则工作不可靠
这或许是前面问题的一个表现。如果不是,你的规则使用 sysfs 属性,这可能是一个内核计时问题,在下个版本的内核中会被修正 。 现在,你可以通过创建一个等待使用 sysfs 属性的规则,把它添加到 /etc/udev/rules.d/10-wait_for_sysfs.rules 文件中。如果你做了,请通知 LFS 开发邮件列表 ,对他们有所帮助。
4.3.6.Udev没有创建设备
后面的文本假设驱动已经被静态的编译进了内核或者是作为模块已经被加载,你已经检查了 Udev 没有创建错误的设备。
某个内核驱动可能没有将其数据导出到 sysfs。这个问题在内核源代码树之外的第三 方驱动程序上尤其常见,结果是这些驱动无法创建其设备节点。用 /etc/sysconfig/createfiles 配置文件手动创建这些设备,参考内核文档里的 devices.txt 文件或者该驱动的文档以获得正确的主/次设备号。 静态的设备将会被 S10udev 启动脚本拷贝到 /dev。
4.3.7.重启后设备名字顺序变化
这是由于 Udev 设计的问题,它以并行方式处理热插拔事件和加载模块。因此名字的顺序就会不可预测。 这将不会被修正。你不应当依赖内核设备名字会稳定。相应的,根据设备稳定的属性(比如,序列号或者 Udev 安装的各种 *_id 工具的输出)写自己 的规则来创建符号链接。可以参见后面的“为设备创建惯用符号链接”和“配置网络脚本”。
4.4.有用的读物
一些有用的补充文档可以在下列网站得到:
-
devfs 的用户空间实现 http://www.kroah.com/linux/talks/ols_2003_udev_paper/Reprint-Kroah-Hartman-OLS2003.pdf
-
udev FAQ http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev-FAQ
-
sysfs 文件系统 http://www.kernel.org/pub/linux/kernel/people/mochel/doc/papers/ols-2005/mochel.pdf
5.配置setclock脚本
The setclock脚本从硬件时钟,也就是 BIOS 或 CMOS 时钟读取时间。如果硬件时钟设置为 UTC ,这个脚本会使用 /etc/localtime 文件(这个文件把用户所在的时区告诉 hwclock 程序)将硬件时钟的时间转换为本地时间。没有办法自动检测硬件时钟是否设置为 UTC 时间,因此需要手动设置。
如果您忘了硬件时钟是不是设置为 UTC 时间了,可以运行 hwclock --localtime --show 命令,这将显示硬件时钟当前的时间。如果显示的时间符合您的手表的时间,那么硬件时钟设置的是本地时间;如果 hwclock 显示的不是本地时间,就有可能设置的是 UTC 时间,可以通过在所显示的 hwclock 时间加上或减去您所在时区的小时数来验证。例如,如果您所在的时区是 MST(美国山区时区),已知是 GMT -0700,在本地时间上加 7 小时。
如果你的硬件使用的不是 UTC 时间,就必须将下面的 UTC 变量值设为 0 (零),而"UTC=1"表示使用的是UTC时间。
运行下面的命令新建一个 /etc/sysconfig/clock 文件:
cat > /etc/sysconfig/clock << "EOF"
# Begin /etc/sysconfig/clock
UTC=1
# End /etc/sysconfig/clock
EOF
root:/sources/lfs-bootscripts-6.2# cat > /etc/sysconfig/clock << "EOF"
> # Begin /etc/sysconfig/clock
>
> UTC=1
>
> # End /etc/sysconfig/clock
> EOF
root:/sources/lfs-bootscripts-6.2#
在 http://www.linuxfromscratch.org/hints/downloads/files/time.txt 有一个很好的关于如何处理 LFS 时间的提示,说明了例如时区、UTC、TZ 环境变量等等问题。
6.配置Linux控制台
本节讨论如何配置 console 初始化脚本来设置键盘映射表和控制台字体。如果您不使用非 ASCII 字符(英镑和欧元符号就是非 ASCII 字符的例子),并且是美式键盘,可以跳过这一节,没有配置文件的话,console 初始化脚本不会做任何事情。
console 使用 /etc/sysconfig/console 作为配置文件以决定使用什么键盘映射表和屏幕字体,各种特定语言的 HOWTO(参见 http://www.tldp.org/HOWTO/HOWTO-INDEX/other-lang.html) 能帮助您完成配置。LFS-Bootscripts 软件包安装了一个已为一些国家配置好了的预制的 /etc/sysconfig/console 文件,如果您所在的国家已经被支持了,您可以去掉相应部分的注释。如果您还有疑问,请在 /usr/share/kbd 目录下查找正确的键盘映射表和屏幕字体。 阅读 loadkeys(1) 和 setfont(8) 的手册,来确定这些程序的正确参数。
/etc/sysconfig/console 文件中可能包含这样格式的行:VARIABLE ="value"。变量如下:
KEYMAP 这个变量指定 loadkeys 程序的参数。典型的像键盘映射的名字 "es"。 如果不设定参数,bootscript 就不会运行 loadkeys 程序, 而是使用默认的内核键盘映射。 KEYMAP_CORRECTIONS 这个参数很少用到,它可被用来指定再次调用loadkeys 程序的参数。对于提供的键盘映射不是很领人满意时,做些调整。 例如,我们要把一些正常情况下不会出现的欧洲字符包含到在键盘映射中, 那我们就需要把这个参数设为 “euro2”。 FONT 这个变量是为 setfont 程序设定的. 通常情况下它要包括font的名字, “-m”, 以及需要载入的application character map名. 比方., 要调用 “lat1-16” font 以及 “8859-1” application character map , 就把这个参数设为 “lat1-16 -m 8859-1”. 如果这个变量没有被设定,bootscript会加载默认的 setfont 程序, 以及默认的一大堆 UNICODE 此参数设成“1”, “yes” 或 “true” 会把控制台改为UTF-8模式。在 UTF-8 的 locale 下比较有用,其他情况都是有害的。 LEGACY_CHARSET 对于许多的键盘布局,在 Kbd 包中没有提供 Unicode 键盘映射。如果这个变量被设置为一个有效的非 UTF-8 编码的键盘映射,console bootscript 会把它转换成 UTF-8 编码。注意,无效键(例如,键位本身不能产生字符,而是对下一个键产生的字符限制 ;在标准美国键盘中没有无效键)和组合键(例如,为了产生字符按下 Ctrl+. A E)没有相应的内核 patch 在 UTF-8 模式下是不能工作的。这个变量只用在 UTF-8 模式下。 BROKEN_COMPOSE 如果你应用第八章中的内核 patch ,把它设为 "0"。你不得不在 "-m" 开关之后,添加需要的字符集到 FONT 变量中。这个变量只用在 UTF-8 模式下。对于把键盘映射直接编译进内核的支持,在内核中已经去掉了。因为这样会导致有一些错误的结果。
一些例子:
-
对于一个非 Unicode 的安装,只有 KEYMAP 和 FONT 变量是必需的。例如,在波兰语安装中,应当使用:
cat > /etc/sysconfig/console << "EOF"
# Begin /etc/sysconfig/console
KEYMAP="pl2"
FONT="lat2a-16 -m 8859-2"
# End /etc/sysconfig/console
EOF -
正如上面的方法,有时需要对对提供的键盘映射进行稍微的调整。下面的例子在德国键盘映射中添加欧洲符号:
cat > /etc/sysconfig/console << "EOF"
# Begin /etc/sysconfig/console
KEYMAP="de-latin1"
KEYMAP_CORRECTIONS="euro2"
FONT="lat0-16 -m 8859-15"
# End /etc/sysconfig/console
EOF -
下面是一个保加利亚的 Unicode 例子,存在一个 UTF-8 键盘映射,并且没有定义无效键和组合键规则:
cat > /etc/sysconfig/console << "EOF"
# Begin /etc/sysconfig/console
UNICODE="1"
KEYMAP="bg_bds-utf8"
FONT="LatArCyrHeb-16"
# End /etc/sysconfig/console
EOF -
由于在前面的例子中使用了 512-字符 的 LatArCyrHeb-16 字体,在控制台上不能再显示明亮的颜色,除非使用 framebuffer。如果你想不利用 framebuffer 来显示明亮的颜色,并使用本语种字符,像下面的说明,通过使用相应语言的 256-字符 字体,这仍然是可能实现的。
cat > /etc/sysconfig/console << "EOF"
# Begin /etc/sysconfig/console
UNICODE="1"
KEYMAP="bg_bds-utf8"
FONT="cyr-sun16"
# End /etc/sysconfig/console
EOF -
下面的例子解释了键盘映射从 ISO-8859-15 到 UTF-8 的自动转变和在 Unicode 模式下打开无效键:
cat > /etc/sysconfig/console << "EOF"
# Begin /etc/sysconfig/console
UNICODE="1"
KEYMAP="de-latin1"
KEYMAP_CORRECTIONS="euro2"
LEGACY_CHARSET="iso-8859-15"
BROKEN_COMPOSE="0"
FONT="LatArCyrHeb-16 -m 8859-15"
# End /etc/sysconfig/console
EOF -
对于中文、日文、韩文等一些语言,Linux 的控制台不能显示需要的字符。这些语种的用户应当安装 X Window 系统,包含所需字符集的字体,以及合适的输入法(例如,SCIM 支持很多语言)。
注意
/etc/sysconfig/console 文件只能控制 Linux 文本控制台。在 X Windows、SSH 会话以及串口控制台中,设置键盘布局和终端字体是没有用的。
7.配置sysklogd脚本
sysklogd 脚本用 -m 0 选项调用 syslogd 程序,该选项关闭了周期时间戳标记,这个标记默认让 syslogd 每 20 分钟写入一次 log 文件。要打开周期时间戳标记,请编辑 sysklogd 脚本做相应修改。请运行 man syslogd 以获得更多信息。
8.创建/etc/inputrc文件
inputrc 文件为特定的情况处理键盘映射,这个文件被 Readline 用作启动文件,Readline 是 Bash 和其它大多数 shell 使用的与输入相关的库。
大多数人并不需要自定义键盘映射,所以下面的命令将创建一个适用于所有登陆用户的全局 /etc/inputrc 文件。如果你需要为某个用户覆盖默认的设置,你可以在该用户的主目录中创建一个包含自定义键盘映射的 .inputrc 文件。
要想了解更多关于如何编辑 inputrc 文件的信息,运行 info bash 以参考 bash 的 info 页的 Readline Init File 这一节,运行 info readline 以参考readline 自己的 info 页也不错。
下面是一个基本的全局 inputrc 文件,那些选项的注释也一起包括在文件里。请注意,注释不能和命令放在同一行里。
cat > /etc/inputrc << "EOF"
# Begin /etc/inputrc
# Modified by Chris Lynn <[email protected]>
# Allow the command prompt to wrap to the next line
set horizontal-scroll-mode Off
# Enable 8bit input
set meta-flag On
set input-meta On
# Turns off 8th bit stripping
set convert-meta Off
# Keep the 8th bit for display
set output-meta On
# none, visible or audible
set bell-style none
# All of the following map the escape sequence of the
# value contained inside the 1st argument to the
# readline specific functions
"\eOd": backward-word
"\eOc": forward-word
# for linux console
"\e[1~": beginning-of-line
"\e[4~": end-of-line
"\e[5~": beginning-of-history
"\e[6~": end-of-history
"\e[3~": delete-char
"\e[2~": quoted-insert
# for xterm
"\eOH": beginning-of-line
"\eOF": end-of-line
# for Konsole
"\e[H": beginning-of-line
"\e[F": end-of-line
# End /etc/inputrc
EOF
root:/sources/lfs-bootscripts-6.2# cat > /etc/inputrc << "EOF"
> # Begin /etc/inputrc
> # Modified by Chris Lynn <[email protected]>
>
> # Allow the command prompt to wrap to the next line
> set horizontal-scroll-mode Off
>
> # Enable 8bit input
> set meta-flag On
> set input-meta On
>
> # Turns off 8th bit stripping
> set convert-meta Off
>
> # Keep the 8th bit for display
> set output-meta On
>
> # none, visible or audible
> set bell-style none
>
> # All of the following map the escape sequence of the
> # value contained inside the 1st argument to the
> # readline specific functions
>
> "\eOd": backward-word
> "\eOc": forward-word
>
> # for linux console
> "\e[1~": beginning-of-line
> "\e[4~": end-of-line
> "\e[5~": beginning-of-history
> "\e[6~": end-of-history
> "\e[3~": delete-char
> "\e[2~": quoted-insert
>
> # for xterm
> "\eOH": beginning-of-line
> "\eOF": end-of-line
>
> # for Konsole
> "\e[H": beginning-of-line
> "\e[F": end-of-line
>
> # End /etc/inputrc
> EOF
root:/sources/lfs-bootscripts-6.2#