7.9. Bash Shell 启动文件
shell 程序 /bin/bash (在此之后以“shell”称呼)使用了一个启动文件集全,来帮助创造一个运行的环境。每一个文件都有特定的用处,有的文件还能使登入与交互环境有所不同。放在 /etc 目录下的一些文件提供了全局设置。如果相类似的设置文件出现在某个用户起始文件夹下(~/),那么在登入该用户时,它将替代该全局设置。
使用 /bin/login 读取 /etc/passwd 文件成功登录后,启动了一个交互登录 shell 。用命令行可以启动一个交互非登录 shell(例如 [prompt]$/bin/bash)。非交互 shell 通常出现在 shell 脚本运行的时候,之所以称为非交互的,因为它正在运行一个脚本,而且命令与命令之间并不等待用户的输入。
要获得更多信息,请运行 info bash 以参考 Bash Startup Files and Interactive Shells 小节。
当以交互登录方式运行 shell 的时候,会读取 /etc/profile 和 ~/.bash_profile 文件。
下面是一个基本的 /etc/profile 文件,设置了本地语言支持所必需的环境变量,适当设置这些变量会导致:
· 程序将产生翻译成本地语言的输出
· 正确的将字符分类为字母、数字和其它类,这样做是必要的,可以让 bash 在非英语 locale 下正确接收命令行输入的非 ASCII 字符。
· 为指定的国家设置正确的字母排序
· 适当的默认页面大小
· 为货币、时间和日期值设置正确的格式
这个脚本还设置了 INPUTRC 环境变量,让 Bash 和 Readline 使用我们先前创建的 /etc/inputrc 文件。
把下面的 [ll] 换成您想要设置的两个字母的语言代码(例如"en"),把 [CC] 换成适当的两个字母的国家代码(例如"GB"),把 [charmap] 换成规范的字符映射表。
Glibc 支持的所有 locales 列表可以使用下列命令获得:
locale -a
很多 locale 有许多别名,比如"ISO-8859-1"也被称为"iso8859-1"和"iso88591"。一些应用程序不能正确的处理这些别名,所以安全的做法是使用 locale 的规范名称。要确定正确的规范名称,运行下面的命令,并把其中的 [locale name] 替换成 locale -a 命令的输出中你感兴趣的 locale (在这个例子中是"en_GB.iso88591")。
LC_ALL=[locale name] locale charmap
对于"en_GB.iso88591" locale ,上面的命令将会打印:
ISO-8859-1
这样你就得到了正确的 locale 设置是"en_GB.ISO-8859-1"。将使用上述试探方法得到的 locale 在添加进 Bash 启动文件前做充分的测试是很重要的。
LC_ALL=[locale name] locale country
LC_ALL=[locale name] locale language
LC_ALL=[locale name] locale charmap
LC_ALL=[locale name] locale int_curr_symbol
LC_ALL=[locale name] locale int_prefix
上述命令将会打印与 [locale name] 对应的国家和语言名称、使用的字符编码、货币符号、国际长途电话号码前缀。如果上述命令中的任意一个出现了类似下面的错误信息,则表明你该 locale 要么在 Chapter 6 中没有安装,要么不被 Glibc 的默认安装支持。
locale: Cannot set LC_* to default locale: No such file or directory
在这种情况下,你应当要么使用 localedef 命令安装相应的 locale ,要么选择一个其他的 locale 。接下来的指令都将假定 Glibc 没有出现上述错误信息。
一些 LFS 基本系统之外的软件包可能并不支持你选择的 locale 。一个例子就是 X 库(X Window System 的一部分),它会输出如下信息:
Warning: locale not supported by Xlib, locale set to C
有时可以通过移除该 locale 的字符映射(charmap)定义部分来解决这个问题——只要这样做不会改变 Glibc 中与该 locale 关联的字符映射关系(这个可以通过对两个 locale 运行 locale charmap 命令来检查)。例如将"de_DE.ISO-8859-15@euro"修改为"de_DE@euro"即可让这个 locale 被 Xlib 正确识别。
其他一些软件包在你选择的 locale 出乎其意料的情况下可能即使运行异常也不会显示错误信息。在这种情况下,研究一下其他 Linux 发行版是如何支持你选择的 locale 可能会得到更加有用的信息。
一旦确定了正确的 locale 设置,创建 /etc/profile 文件:
cat > /etc/profile << "EOF"
# Begin /etc/profile
export LANG=<ll>_<CC>.<charmap><@modifiers>
export INPUTRC=/etc/inputrc
# End /etc/profile
EOF
"C"(默认)和"en_US"(美国英语用户的推荐值)这两个 locale 是不同的。
设置键盘布局、屏幕字体和 locale 相关的环境变量,是使用一般的单字节编码和从左至右书写方式地区所需的国际化步骤。更复杂的情况(包括基于 UTF-8 的 locale)需要更多的步骤和补丁,因为这种情况下许多程序可能工作不正常。这些步骤和补丁没有包含在本书里,因此 LFS 无法支持这些 locale 。
7.10. 配置 localnet 脚本
localnet脚本的一部分工作是设置系统的主机名,这需要在 /etc/sysconfig/network 文件里配置。
运行下面的命令创建 /etc/sysconfig/network 文件并设置主机名:
echo "HOSTNAME=<lfs>" > /etc/sysconfig/network
<lfs> 请用您的计算机名替换 [lfs] ,不要在这里输入全限定域名(Fully Qualified Domain Name),FQDN 的信息稍后将放在 /etc/hosts 文件里。
7.11. 定制 /etc/hosts 文件
要在 /etc/hosts 文件里配置网卡的 IP 地址、FQDN 和可能会用的别名,语法如下:
<IP address> myhost.example.org aliases
除非您的计算机在 Internet 上是可访问的(例如,有一个注册的域名并分配到了一个合法的 IP 地址(块)(大多数用户没有)),请确保 IP 地址在私有网络 IP 地址范围内,正确的范围是:
类别 网络
A 10.0.0.0
B 172.16.0.0 到 172.31.0.255
C 192.168.0.0 到 192.168.255.255
一个合法的 IP 地址可能是 192.168.1.1 ,这个 IP 的合法 FQDN 可能是 www.linuxfromscratch.org(不推荐,因为这是个已合法注册的域名,这样做可能会造成域名服务器的问题)。
即使您没有网卡,仍然需要一个 FQDN,某些程序需要这个才能正常工作。
运行下面的命令创建 /etc/hosts 文件:
cat > /etc/hosts << "EOF"
# Begin /etc/hosts (network card version)
127.0.0.1 localhost
<192.168.1.1> <HOSTNAME.example.org> [alias1] [alias2 ...]
# End /etc/hosts (network card version)
EOF
把 [192.168.1.1] 和 [<HOSTNAME>.example.org] 更改为特定用户或特别要求所需要的值(如果这台机器要连入一个已存在的网络,并且网络/系统管理员已经给您分配了一个 IP 地址)。
如果您不打算配置网卡,运行下面的命令创建 /etc/hosts 文件:
cat > /etc/hosts << "EOF"
# Begin /etc/hosts (no network card version)
127.0.0.1 <HOSTNAME.example.org> <HOSTNAME> localhost
# End /etc/hosts (no network card version)
EOF
7.12. 为设备创建惯用符号连接
7.12.1. CD-ROM symlinks
我们可能装一些软件用到 cdrom dvd 等,因此我们会需要把 /dev/cdrom /dev/dvd 的符号链接加在/etc/fstab中。对于每一个CD-ROM 设备,在 /sys 下找到相应的目录(例如, /sys/block/hdd) ,然后运行如下命令:
udevtest /block/hdd
观察一下包含很多 *_id 输出的程序的行。
有两种方法可以创建symlinks,可以用model名及序号,或是用设备在总线上的位置。 以第一种方法,可以创建如下文件:
cat >/etc/udev/rules.d/82-cdrom.rules << EOF
# Custom CD-ROM symlinks
SUBSYSTEM=="block", ENV{ID_MODEL}=="SAMSUNG_CD-ROM_SC-148F", \
ENV{ID_REVISION}=="PS05", SYMLINK+="cdrom"
SUBSYSTEM=="block", ENV{ID_MODEL}=="PHILIPS_CDD5301", \
ENV{ID_SERIAL}=="5VO1306DM00190", SYMLINK+="cdrom1 dvd"
EOF
注意
这个例子能正常工作,但 udev 不能识别 \ 的继续上一行功能,所以若要用编辑器来编辑 udev 的规则时,一定要保证每行只有一个命令。
做完这些symlinks就会保持正常工作状态,即使把cdrom移到 IDE 总线的其他位置上也能正常工作。但是如果使用新的驱动器来替换原来的 SAMSUNG CD-ROM,/dev/cdrom 符号链接将不会被创建。
SUBSYSTEM=="block" 关键字是为了避免匹配一般的 SCSI 设备。 在没有这个关键字的情况下,若同时存在两个 SCSI CD-ROM, 这个符号链接有时会指向 /dev/srX 设备 ,但有时会错误的指向 /dev/sgX。
第二种方法的步骤:
cat >/etc/udev/rules.d/82-cdrom.rules << EOF
# Custom CD-ROM symlinks
SUBSYSTEM=="block", ENV{ID_TYPE}=="cd", \
ENV{ID_PATH}=="pci-0000:00:07.1-ide-0:1", SYMLINK+="cdrom"
SUBSYSTEM=="block", ENV{ID_TYPE}=="cd", \
ENV{ID_PATH}=="pci-0000:00:07.1-ide-1:1", SYMLINK+="cdrom1 dvd"
EOF
这样,即使你使用不同的 model 来替换原来的设备,符号链接仍然是正确的,它指向在 IDE 总线上旧的位置。 ENV{ID_TYPE}=="cd" 关键字是为了确保符号链接在总线上的那个位置放的不是 CD-ROM 时,能够消失。
当然把两种方法混合使用也是可以的。
7.12.2. Dealing with duplicate devices
在 节 7.4, "LFS 系统的设备和模块处理"提到过, /dev 下相同功能设备的顺序是随机的。例如,你有一个 USB 的网络摄像头和一个 TV 的调谐器,有时 /dev/video0 指向网络摄像头,/dev/video1 指向调谐器,但是在重启之后可能就会改变。除了网卡和声卡之外的其他设备,都可以通过创建 udev 的规则来定制固定的符号链接。网卡的解决方法请见 节 7.13, "配置网络脚本", 声卡解决方法请见 BLFS。
每一个设备都可能有这个问题(即使这个问题在你现在的发行版中不存在),在 /sys/class 或 /sys/block 下找到相应的目录。 对于视频设备,可能是 /sys/class/video4linux/videoX。找出标记设备唯一性的属性(通常是 设备提供商、产品 ID 以及序列号):
udevinfo -a -p /sys/class/video4linux/video0
接下来,写一个创建符号链接的规则,例如:
cat >/etc/udev/rules.d/83-duplicate_devs.rules << EOF
# Persistent symlinks for webcam and tuner
KERNEL=="video*", SYSFS{idProduct}=="1910", SYSFS{idVendor}=="0d81", \
SYMLINK+="webcam"
KERNEL=="video*", SYSFS{device}=="0x036f", SYSFS{vendor}=="0x109e", \
SYMLINK+="tvtuner"
EOF
结果 /dev/video0 和 /dev/video1 设备仍然随机指向调谐器和网络摄像头(因此不应当直接使用),但是符号链接 /dev/tvtuner 和 /dev/webcam 总是指向正确的设备。
关于书写 Udev 规则的更多信息,可以查看 /usr/share/doc/udev-096/index.html。
7.13. 配置网络脚本
本节仅适用于需要配置网卡的情况。
如果不使用网卡,就不需要创建关联网卡的配置文件,这样的话,在所有运行级目录(/etc/rc.d/rc*.d) 下删除 network 符号链接。
7.13.1. 创建网络接口的稳定名称
这一段的说明对于单网卡是可选的。
由于 Udev 和网络驱动的模块化,网络设备的接口的加载顺序在每次reboot后可能会不同,因为驱动是并行加载的,所以顺序会变成随机。例如,在一台计算机上有两块网卡Intel 和 Realtek。Intel 制造的网卡可能是 eth0,Realtelk 的网卡是 eth1;但是重启后网卡的顺序可能反过来。为避免这种情况,我们应该根据网卡的MAC地址或总线位置来为他们命名。
如果想要根据MAC地址来识别网卡,可以使用如下命令:
grep -H . /sys/class/net/*/address
为每个网卡(除loopback),设计一个描述性的名字,比方 “realtek”, 然后参照如下建立Udev规则:
cat > /etc/udev/rules.d/26-network.rules << EOF
ACTION=="add", SUBSYSTEM=="net", SYSFS{address}=="00:e0:4c:12:34:56", \
NAME="realtek"
ACTION=="add", SUBSYSTEM=="net", SYSFS{address}=="00:a0:c9:78:9a:bc", \
NAME="intel"
EOF
注意
虽然这个例子可以正常工作,但要注意 udev 不能识别 \ 的继续上一行的功能。所以如果用文本编辑器来编辑就一定要保证每个规则占一行。
如果要以总线位置作为标准,可以创建如下的Udev规则:
cat > /etc/udev/rules.d/26-network.rules << EOF
ACTION=="add", SUBSYSTEM=="net", BUS=="pci", ID=="0000:00:0c.0", \
NAME="realtek"
ACTION=="add", SUBSYSTEM=="net", BUS=="pci", ID=="0000:00:0d.0", \
NAME="intel"
EOF
这个规则会把网卡名字每次都定为 “realtek” 和 “intel”, 以替代eth0和eth1 (即:原来的eth0和eth1接口不存在了除非把他们加到 NAME 下)。在下面的文件中我们使用描述性的名字来替代eth0 等。
需注明以上规则并不永远适用。例如, 当VLAN 和 网桥 使用时,以MAC为基准的命名就会出问题。由于 VLAN 和 网桥在网卡上有相同的MAC地址。如果只想重新命名网卡接口,而不是brige和VLAN接口,但是规则都会匹配它们。如果使用虚拟接口,我们会有两种解决办法。其一是把 DRIVER=="?*" 关键字加在 SUBSYSTEM=="net" 后。但这种方法对于一些老型号的网卡不起作用,因为这些网卡的 uevent 中没有 DRIVER 变量,因此按规则就不可能匹配到这些卡。 另外一种就是以总线位置命名。
另外一种已知的不能工作的情况存在于无线网络中,当应用MadWifi 或 HostAP 驱动时, 他们会以相同的MAC地址和总线位置创建至少两个接口。例如,Madwifi 驱动会创建一个 athX 和 wifiX 接口(X是一个数字)。为区别这些接口,可以把 KERNEL 参数,比如 KERNEL=="ath*" 加到 SUBSYSTEM=="net"后。
可能还有很多情况会导致不能正常工作,现在这方面的 bug 仍然不断的报告给 Linux 的各个发布版,没有一个解决方法可以解决所有的情况。
7.13.2. 创建网络接口配置文件
network 脚本启用或关闭哪个接口由 /etc/sysconfig/network-devices 目录下的文件决定,这个目录下的文件应该是类似于 ifconfig.xyz 的形式,这里"xyz"是网络接口名(例如 eth0 或者 eth0:1)。这个目录中的文件将定义接口的属性,比如IP地址、子网掩码等等。
在这个目录下新建文件,下面是一个为 eth0 设备创建 ipv4 文件的示例:
cd /etc/sysconfig/network-devices &&
mkdir -v ifconfig.eth0 &&
cat > ifconfig.eth0/ipv4 << "EOF"
ONBOOT=yes
SERVICE=ipv4-static
IP=192.168.1.1
GATEWAY=192.168.1.2
PREFIX=24
BROADCAST=192.168.1.255
EOF
每个文件中的这些变量的值都要改成您的设置,如果 ONBOOT 变量设置为"yes",network 脚本会在系统启动的时候启动 NIC(Network Interface Card 网络接口卡,简称网卡),如果设置为"yes"以外的值,网卡会被 network 脚本忽略而没有启动。
SERVICE 变量定义获取 IP 地址的方式,LFS-Bootscripts 有一套模块化的 IP 地址分配格式,并在 /etc/sysconfig/network-devices/services 目录下为其它的 IP 分配方式创建了附加的文件,这通常用作 DHCP(Dynamic Host Configuration Protocol 动态主机配置协议)方式,在 BLFS 里有详细介绍。
GATEWAY 变量应该设置为默认网关的 IP 地址,如果没有默认网关,就把这个变量完全注释掉。
PREFIX 变量设置为子网使用的位数,IP 地址的每个字节是 8 bit ,如果子网掩码是 255.255.255.0 ,那么它使用前三个字节(24 bit)指定网络号;如果网络掩码是 255.255.255.240 ,它用前 28 bit 来指定网络号。长于 24 bit 的前缀一般由 DSL 和 cable 的 ISP(Internet Service Providers 因特网服务提供商)使用,我们的例子里(PREFIX=24),子网掩码是 255.255.255.0 ,请根据您的网络情况调整 PREFIX 变量。
7.13.3. 创建 /etc/resolv.conf 文件
如果系统要连接到 Internet 上,就需要 DNS(Domain Name Service 域名服务)名称解析的手段,来把 Internet 域名解析为 IP 地址,反之亦然。在 /etc/resolv.conf 文件里设置 ISP 或网络管理员提供的域名服务器的 IP 地址就可以达到这个目的了,运行下面的命令创建这个文件:
cat > /etc/resolv.conf << "EOF"
# Begin /etc/resolv.conf
domain {<域名>}
nameserver <主域名服务器IP地址>
nameserver <副域名服务器IP地址>
# End /etc/resolv.conf
EOF
把 [域名服务器IP地址] 替换为您的域名服务器的 IP 地址。域名服务器常常不止一项(作为备份用途),如果您只需要一个域名服务器,把文件里的第二行 nameserver 删除就可以了。在局域网里这个 IP 地址还可能是路由器。