📄 linux caijian.txt
字号:
义一个,因此一项服务可以有多行配置。
Control规定了如何处理模块认证失败或成功,可以是requisite、required、
sufficient或optional。
Module-path是PAM库文件的文件名。缺省路径是/lib/security/。
Module-arguments是可以传给模块的参数。
5.5.4 other
特别需要指出的是,有一个特殊的服务名字——other。如果没有明确指明应用
于某项服务的规则,就用other的定义来处理。因此,我们可以想到,系统中PAM的
最简配置为,只有/etc/pam.d/other这一个配置文件,即可处理所有的认证请求。
下面是我们用过的一个other配置文件的例子:
[xmdong@lips pam.d]$ cat other
#%PAM-1.0
auth required /lib/security/pam_unix.so
account required /lib/security/pam_unix.so
password required /lib/security/pam_unix.so
session required /lib/security/pam_unix.so
当然,这样处理对系统的安全性来说是不利的,最好还是给每项服务定义单独
的配置文件。这不过是一种简化问题的临时方案。
5.6 再论initrd
在前面的5.3节中,对initrd机制已经有了比较详细的讨论。准确的说,该部分
内容来自linux-2.4/Documentation/initrd.txt 文件。但是在实践中,我们发现其
中描述的有些方法并不适用。是新版本内核的变化造成的(内核实现与文档不同步
),还是2.4版内核的bug,不得而知。在我查证的过程中,看到网上有不少相关的
问题和讨论。遗憾的是至今我还不能确认到底是什么原因。
后来我又专门读了2.2版内核中所附带的 initrd.txt 文件。我感觉实际的情况
似乎更接近于这个老文档的描述。我还看到一个有关的patch文件,从该文件中可以
明确看到新的initrd.txt文档的改变。下面是该文件的开始部分(行首的-表示老文
档有而新文档中已经删除,+表示新文档中增加的内容)。
Using the initial RAM disk (initrd)
===================================
-Written 1996 by Werner Almesberger <almesber@lrc.epfl.ch> and
- Hans Lermen <lermen@elserv.ffm.fgan.de>
+Written 1996,2000 by Werner Almesberger <werner.almesberger@epfl.ch
> and
+ Hans Lermen <lermen@fgan.de>
-initrd adds the capability to load a RAM disk by the boot loader. T
his
-RAM disk can then be mounted as the root file system and programs c
an be
-run from it. Afterwards, a new root file system can be mounted from
a
-different device. The previous root (from initrd) is then either mo
ved
-to the directory /initrd or it is unmounted.
+initrd provides the capability to load a RAM disk by the boot loade
r.
+This RAM disk can then be mounted as the root file system and progr
ams
+can be run from it. Afterwards, a new root file system can be mount
ed
+from a different device. The previous root (from initrd) is then mo
ved
+to a directory and can be subsequently unmounted.
下面我试图将我遇到的问题和能够确认的东西记录一下。(后面我们分别称新
、老文档为initrd.txt-2000和initrd.txt-1996)
5.6.1 根到底在哪里
在配置使用initrd之前,首先你要清楚,系统正常运行时,根文件系统挂载在
什么设备上(也就是说,root device是什么——root在哪里?)。
我们知道,使用initrd机制的话,系统启动时先以RAM Disk(/dev/ram0)作为
根,然后通过某种方法将根转换到“真实的根(real-root-dev)”(之所以说rea
l,是与前面的RAM里临时的根比较而言)。一种常见的情形是启动时用initrd,然
后切换到一个硬盘分区,比如/dev/hda1。
事实上,这个根转换不是必须的。我们完全可以就把/dev/ram0作为我们真实的
根设备。这时,系统启动之后所有的操作都在RAM Disk中进行。当然这样做也有一
个明显的缺点,即无法保存数据。比如对系统配置进行的修改(象IP地址),重新
启动之后就丢掉了。如果要保存数据,就要想别的办法。
LiPS目前的做法就是这一种(没有根转换,initrd就是真实的根)。为了在重
新启动之后保持配置文件的修改,我们将目录/etc链接到了其他非易失存储器(例
如,一个硬盘分区,或者USB盘的分区)。
指定根设备是通过内核参数“root=”来完成的。以GRUB引导器的配置为例:
kernel /boot/bzImage ro ramdisk_size=65536 root=/dev/ram0
initrd /boot/initrd.img
其中 ramdisk_size=65536 说明初始RAM盘的大小为64MB,root=/dev/ram0 说
明根的位置。下面第二个例子来自一台在hda1安装了Redhat 9的机子:
kernel /boot/vmlinuz-2.4.20-8 ro root=/dev/hda1
initrd /boot/initrd-2.4.20-8.img
很明显,这里 root=/dev/hda1 指定了真实的根,其启动过程包含根的转换。
但是这里没有指定 ramdisk_size,因为initrd的缺省大小是4MB,而initrd-2.4.2
0-8.img比较小,所以用缺省值即可。
(我们多次提到root, root filesystem, root device, 自己体会吧。)
5.6.2 linuxrc
在initrd机制的设计中,初始RAM盘只是作为一个过渡性质的根设备,由/linu
xrc来完成操作环境准备(比如加载一些不常用的、没有编译进内核的驱动程序模块
)和根转换工作。
Linuxrc的执行是自动的,即内核挂载initrd盘作为根,如果根下面有这个文件
(也就是/linuxrc),就执行它。(如果没有呢?当然什么也不做。所以linuxrc也
并不是必不可少的。)
接下来说说linuxrc的内容。下面的例子是从initrd-2.4.20-8.img中释放出来
的:
[root@lips initrd]# cat linuxrc
#!/bin/nash
echo "Loading jbd.o module"
insmod /lib/jbd.o
echo "Loading ext3.o module"
insmod /lib/ext3.o
echo Mounting /proc filesystem
mount -t proc /proc /proc
echo Creating block devices
mkdevices /dev
echo Creating root device
mkrootdev /dev/root
echo 0x0100 > /proc/sys/kernel/real-root-dev
echo Mounting root filesystem
mount -o defaults --ro -t ext3 /dev/root /sysroot
pivot_root /sysroot /sysroot/initrd
umount /initrd/proc
该脚本中首先加载了支持ext3文件系统所需的模块,然后挂载真实的根文件系
统,并进行转换。特别需要注意的是,linuxrc脚本一般是用nash解释执行的,而不
是通常的bash。有关nash的详情请看手册页nash(8)。简单说,nash内置实现了多数
在执行linuxrc这个阶段可能用到的命令,比如mount, pivot_root, umount;而如
果使用bash,象mount等都是“外部命令”,就需要复制/bin/mount到initrd映像文
件中。实际上,在initrd-2.4.20-8.img的/bin中只有insmod和nash两个程序(mod
probe符号链接到insmod):
[root@lips initrd]# ls bin/
insmod modprobe nash
当我按照5.3.4节描述的方法测试linuxrc的时候发现,我的脚本头两句执行就
报错。
mount –o ro /dev/hda11 /sysroot
cd /sysroot
这里我的真实的根设备是/dev/hda11,/sysroot是initrd映像中存在的一个目
录。这两句完全是按照该文档的要求写的。后来经过多次试验才发现问题之所在。
第一,nash实现的mount命令语法与我们常用的/bin/mount并不完全兼容;第二,n
ash根本没有实现cd命令。
因此,可以推断initrd.txt-2000中讲linuxrc时所举例子不是用的nash。实际
上在该文档中根本没有指明用什么shell。再回头仔细看才发现,所有例句都是在r
oot的shell命令提示符“#”后面的,那么它用的是bash之类了。但是令人迷惑的是
,同样在该小节中稍后出现如下例句: # exec chroot . what-follows <dev
/console >dev/console 2>&1
为什么用exec执行chroot呢?chroot可以在命令行直接用啊。文档中讲到,wh
at-follows可以是/sbin/init。我用nash试了下面这个句子(nash中用exec执行外
部命令):
exec chroot . /sbin/init <dev/console >dev/console 2>&1
还是不行。错误信息:
Usage: init 0123456SsQqAaBbCcUu
开始我还以为后面那一串是个“magic number”,后来想以Usage开头应该是讲
使用这个命令的语法。看init(8)手册页,果然要求给一个参数,0~6当然是运行级
别啦,试了一个init 3也还是不行。尤其搞不明白后面那些个console什么意思。
5.6.3 根转换机制:新的?旧的?
前面我们多次提到了根的转换。在initrd.txt的两个版本中,分别描述了两种
根转换机制,其中2000版中称1996版的内容已经“过时”,不推荐使用。然而事实
上要麻烦的多,事情并不总是按照预期(如文档所述)运行。
为了弄清楚这个问题,我进行了一系列测试。环境是这样的:
O 使用initrd机制,已经准备好了根文件系统映像文件initrd.img,准备好了内核
bzImage;
O initrd.img的所有内容释放到一个硬盘分区/dev/hda11,ext2文件系统;
O 在/dev/hda11上面增加一个/boot目录,存放bzImage和initrd.img文件;
O 以/dev/ram0作为根启动,然后以某种机制转换到“真实的根”/dev/hda11。
系统的引导器是GRUB,安装在硬盘MBR,grub.conf位于/dev/hda1(也就是做测
试的实际的根文件系统)。按照上述环境配置,在grub.conf中增加如下内容:
title lips (testing ......)
root (hd0,10)
kernel /boot/bzImage ro root=/dev/hda11 ramdisk_size=65536
initrd /boot/initrd.img
下面我们分别使用不同的/linuxrc进行了测试,以确认到底哪种机制是可行的
。
第一,如果没有/linuxrc会怎么样呢?
结果是系统能够成功启动到以/dev/hda11作为根,并且把initrd(也就是旧根
文件系统)的内容移到了/initrd目录。这是符合initrd.txt-1996文档中第一段的
描述的。所以只要你使用了initrd,指定了新的根,并且准备好了/initrd目录(已
经在/dev/hda11创建了/initrd),内核可以自动完成根的转换工作。终端上面有如
下输出信息:
Trying to move old root to /initrd ... okay
这里有个小问题,即最后/initrd没有卸载,这意味着initrd所分配内存也没有
释放。因此umount /initrd不是内核自动完成的,而应该在/linuxrc中的某个位置
进行。如果linuxrc仅包含卸载/initrd的命令,如下:
#!/sbin/nash
umount /initrd
则执行情况是这样的:umount命令报错(返回错误码22),然后出现前面所示
Trying…的信息。结果跟前面是一样的。因为linuxrc执行在先,当时旧根还没有被
转移到/initrd中来。
如果没有/initrd目录会怎样?我们把/dev/hda11上面的/initrd目录删除,重
新启动(没有/linuxrc),结果是可以启动到以/dev/hda11为根,且看不到原来的
initrd。该过程中出现如下信息:
Trying to move old root to /initrd ... failed
Unmouting old root
Trying to free ramdisk memory ... okey
第二,pivot_root可以用,但是chroot不能用。
pivot_root是在initrd.txt-2000文档中引入的新机制。在测试pivot_root的过
程中,除了在nash中不能用cd命令造成的困惑(这个问题前面已经说明)之外,使
用pivot_root基本上是成功的。/linuxrc脚本的主要内容如下:
#!/sbin/nash
mount -o defaults --ro -t ext2 /dev/hda11 /sysroot
pivot_root /sysroot /sysroot/initrd
但是,用这个脚本不能启动,造成系统挂起:
VFS: Cannot open root device “hda11” or 03:0b
Please append a correct “root=” boot option
Kernel panic: VFS: Unable to mount root fs on 03:0b
如果按照initrd.txt-2000的指导,pivot_root之后应该执行chroot,但是我始
终没有办法使chroot成功执行(有关情况前面已经说明)。不过可以肯定的是,pi
vot_root执行成功之后,当前目录就是新的根目录。
第三,/proc/sys/kernel/real-root-dev
initrd.txt的新版本中最后一节专门指出,向/proc/sys/kernel/real-root-d
ev文件中echo数字的方法(称为change_root机制)是过时的。然而令人迷惑的是,
Redhat 9的缺省安装产生的initrd-2.4.20-8.img中(前面已经列出了其/linuxrc文
件内容),同时使用了pivot_root和change_root机制。
测试下列/linuxrc脚本,系统可以启动到/dev/hda11,但是/initrd没有卸载。
如果在脚本末尾umount /initrd,会返回错误码16。
#!/sbin/nash
mount -t proc /proc /proc
mkrootdev /dev/root
echo 0x0100 > /proc/sys/kernel/real-root-dev
#echo 0x030b > /proc/sys/kernel/real-root-dev
mount -o defaults --ro -t ext2 /dev/hda11 /sysroot
pivot_root /sysroot /sysroot/initrd
umount /initrd/proc
虽然这样可以启动,但是有关real-root-dev还有几个没有弄清楚的问题:
real-root-dev的值到底是什么?
目前我还没有看到解释real-root-dev的值是什么东西的正式文档,根据情况判
断的话,我认为应该是该设备的“major-minor”(主、次设备号)。
为什么用0100而不是030b?
如果上述判断准确的话,那么写入0100就表示/dev/ram0。这就奇怪了,“真实
的根设备”应该是/dev/hda11呀,那么是不是应该写030b呢?但是测试发现用030b
同样会导致不能启动。
Kernel panic: VFS: Unable to mount root fs on 03:0b
5.7 提示
5.7.1 文件系统目录层次结构
根文件系统的目录结构最好符合“Filesystem Hierarchy Standard(文件系统
层次标准)”[7],而不能自己随意创建。
顺便说一下,象这种情况:/bin, /sbin, /usr/bin, /usr/sbin 这4个目录都
可以放应用程序,具体放在哪个目录,则要根据该应用程序在系统中的作用来确定
。一般地,系统的关键应用程序放在/bin,只能给超级用户root访问的关键应用程
序放在/sbin,相比之下比较次要的应用程序和root应用程序分别放在/usr/bin和/
usr/sbin。
5.7.2 mklips.sh(制作LiPS的脚本)
复制文件的工作全部可以手工进行,但是做一个shell脚本来完成所有工作显然
是一个更好的办法。
在我们的项目中,制作LiPS(也就是完成裁减Linux)的工作,除了编译内核之
外,都可以通过mklips.sh脚本完成。
5.7.3 lips.conf(LiPS配置文件)
lips.conf是LiPS的配置文件,由mklips.sh脚本使用,主要用来控制所制作的
LiPS系统包括哪些可选的模块,例如:
INCLUDE_APACHE=no
INCLUDE_IPTABLES=no
INCLUDE_PROFTPD=yes
INCLUDE_NFSD=no
INCLUDE_SAMBA=yes
通过一系列的INCLUDE_?=yes或者no,可以实现LIPS的模块化。在mklips.sh脚
本中,判断每个INCLUDE的值,来确定是否复制某个模块相关的文件。
配置文件中还可以包括其他可配置的信息。
5.7.4 cp –dpR
复制文件请使用“cp –dpR”命令,可以保留文件的属性(特别是对于设备节
点和符号连接等特殊文件),还可以复制整个目录。
5.7.5 如何判断一个程序依赖哪些文件
除了库文件外,关键是找出相关的配置文件。man手册页是判断应用程序配置文
件的重要依据。我们以安装Apache Server为例来说明判断复制哪些文件的过程。
首先确定其可执行文件是/usr/sbin/httpd。然后看httpd的手册页,即
[root@lips lips]# man httpd
httpd(8)
httpd(8)
NAME
httpd - Apache hypertext transfer protocol server
…………(略)
FILES
/etc/httpd/conf/httpd.conf
/etc/mime.types
/etc/httpd/conf/magic
/var/log/httpd/error_log
/var/log/httpd/access_log
/var/run/httpd.pid
February 1997
httpd(8)
(END)
这时关键看最后一段FILES,列出了有关的配置文件、日志文件和进程文件,那
么我们就知道了httpd要在目标系统中运行,这几个配置文件是必不可少的。
把httpd和用ldd找出的库文件以及上述配置文件复制到目标系统,运行httpd试
一下,看看是否正常。一般情况下应该没有问题。但是httpd比较特殊,除了ldd找
出的库文件外,它还需要很多可加载的模块(库)。怎么发现呢?重要的一点是看
出错信息(有时候还要查看日志中的信息,/var/log/messages或者应用程序日志)
,看httpd报告缺少什么;还可以看看相关的配置文件httpd.conf,也能找到有用的
信息。然后我们发现需要/usr/lib/httpd这个目录下的库,把它也复制过去即可。
5.7.6 带库文件复制——lcp()
在复制可执行文件(软件)的过程中,如果没
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -