星期三, 一月 31, 2007

Apache 1.3 to 2.0 VirtualHost

原来的 Apache 1.3,其虚拟主机的设定如下:
NameVirtualHost *:80
"<"VirtualHost *">"
...
但把虚拟主机的那些配置拷贝到 Apache 2.0 中的配置文件之后,启动 Apache 得到报错"No VirtualHost found for NameVirtualHost *:80"。

排错,将所有的 VirtualHost * 替换为 VirtualHost *:80 即可。

星期二, 一月 30, 2007

"tar -T/-X" for my backup design

在我设计的备份方案中,应该根据 backup ID 有若干文件列表,备份程序在执行时应该是从这个列表中查找所有的目录和文件来打包。因为涉及到差分和增量备份的问题,所有不能直接利用这个列表来 tar,而是需要比较时间戳,因此还需要根据这个列表来查找更新的所有文件(可利用 find),并记录到一个新的列表中,随后的 tar 利用这个实际的列表来操作(当然这个过程都是自动完成的,也不一定要调用 find/tar,而可以编写 python 时使用 tarfile 等模块,但直接 wrap 可能比较方便)。

tar 可以使用 -T/-I 参数来读取列表,-X 读取排除列表,但列表生成以后,其中某些文件可能会被删除,例如 web 产生的一些 cache。这时候运行 tar -T 就会报错并退出,而后续的打包就不再进行。

可能需要忽略这一点,用 --ignore-failed-read 可以,问题就是他不会报告哪些被忽略了。我想可以在使用的使用 wrap 这个参数,由用户来进行选择,再传递给 tar 处理。

如果同时使用 -T i-files -X x-files 会怎样呢?
sh$ find `pwd`/lamp01 >i-files
sh$ echo "/tmp/temp/lamp01/profiles" >x-files
sh$ tar -c -z -f lamp01.tgz -T i-files -X x-files /tmp/temp/lamp01
sh$ tar tfz lamp01.tgz | grep profiles | sort
tmp/temp/lamp01/.svn/prop-base/profiles.svn-base
tmp/temp/lamp01/.svn/prop-base/profiles.svn-base
tmp/temp/lamp01/.svn/prop-base/profiles.svn-base
tmp/temp/lamp01/.svn/prop-base/profiles.svn-base
tmp/temp/lamp01/.svn/prop-base/profiles.svn-base
tmp/temp/lamp01/.svn/props/profiles.svn-work
tmp/temp/lamp01/.svn/props/profiles.svn-work
tmp/temp/lamp01/.svn/props/profiles.svn-work
tmp/temp/lamp01/.svn/props/profiles.svn-work
tmp/temp/lamp01/.svn/props/profiles.svn-work
tmp/temp/lamp01/.svn/text-base/profiles.svn-base
tmp/temp/lamp01/.svn/text-base/profiles.svn-base
tmp/temp/lamp01/.svn/text-base/profiles.svn-base
tmp/temp/lamp01/.svn/text-base/profiles.svn-base
tmp/temp/lamp01/.svn/text-base/profiles.svn-base
会发现很多重复的项,而且 tar 归档的大小是普通情况下的 3 倍,这意味着同时使用 -T/-X 选项会有问题。因此如果要排除某个目录,只能将希望放在 find 上了——如果使用 shell script 或在 python 中使用 os.popen() 直接调用这些命令来实现的时候。

例如可以使用如下命令:
find `pwd`/lamp01 -path `pwd`/lamp01/profiles -prune -o -print | grep profiles
这里最好使用绝对路径,在备份的这个脚本设计中也最好使用绝对路径,能够避免很多混乱的情况!可以使用 tar -P 参数。

如果要排除两个目录:
find `pwd`/lamp01 \( -path `pwd`/lamp01/profiles -o -path /tmp/temp/lamp01/confiles \) -prune -o -print | grep profiles
对一个目录也同样可以使用 \(\):
find `pwd`/lamp01 \( -path `pwd`/lamp01/profiles \) -prune -o -print
即便是有不相干的目录加入进来也没有关系
find `pwd`/lamp01 \( -path `pwd`/lamp01/profiles -o -path /etc \) -prune -o -print
不过可以认真考虑一下 backup list 应该以怎样的形式为好?

星期四, 一月 25, 2007

quota 磁盘配额

首先需要修改 /etc/fstab 对指定的文件系统实施磁盘配额:
/dev/VolGroup00/LogVol00 /                      ext3    defaults,usrquota,grpquota       1 1
然后重新挂载分区:
# mount -a -o remount
接着运行:
# quotacheck -cug /
-c,create, -u,user, -g,group
这不一定会成功,你可能会得到下面的错误提示:
quotacheck: Mountpoint (or device) / not found.
quotacheck: Can't find filesystem to check or filesystem not mounted with quota option.
这是因为指定的分区没有在 mount 时施加 usrquota,grpquota 选项,用 mount 或 cat /etc/mtab 应该可以看到:
/dev/mapper/VolGroup00-LogVol00 on / type ext3 (rw,usrquota,grpquota)
否则就只能重启或在 remount 是手工添加这两个参数。

然后打开 quota 功能:
# quotaon /

查看单个用户的 quota:
[root@localhost ~]# quota sysadm
Disk quotas for user sysadm (uid 501): none
[root@localhost ~]# quota magic
Disk quotas for user magic (uid 500):
Filesystem blocks quota limit grace files quota limit grace
/dev/mapper/VolGroup00-LogVol00
301600* 8192 8192 17489 0 0

查看全部的:
[root@localhost ~]# repquota /
*** Report for user quotas on device /dev/mapper/VolGroup00-LogVol00
Block grace time: 7days; Inode grace time: 7days
Block limits File limits
User used soft hard grace used soft hard grace
----------------------------------------------------------------------
root -- 8092660 0 0 181769 0 0
daemon -- 20 0 0 3 0 0
lp -- 8 0 0 1 0 0
rpm -- 36688 0 0 111 0 0
netdump -- 16 0 0 2 0 0
rpcuser -- 8 0 0 1 0 0
smmsp -- 12 0 0 2 0 0
apache -- 52 0 0 10 0 0
squid -- 16 0 0 2 0 0
webalizer -- 32 0 0 4 0 0
xfs -- 0 0 0 1 0 0
ntp -- 16 0 0 2 0 0
magic +- 301600 8192 8192 6days 17489 0 0
sysadm -- 40 0 0 11 0 0
admin -- 40 0 0 11 0 0
test -- 40 0 0 11 0 0

可以使用 edquota 命令来编辑指定用户的磁盘配额,如 edquota magic [/]。Blocks 反映的是空间的大小,一般 1 block = 1K,而 indoe 反映的是对文件数量的限制,可以认为 1 inode = 1 file。

在上面的例子中,magic 用户已经超过了 hard limit,那么当他使用磁盘时,会报错如下:
$ echo "fjiajefi" >test
dm-0: write failed, user block limit reached.


很多时候,我们会需要批量处理大量用户的磁盘配额设置,不可能一个个去做,那么应该使用 edquota 的 -p 选项,例如:
# edquota -p magic admin test
即可将 admin 和 test 用户的配额设置为 magic 用户的模式。

更多的例子:
# edquota -p bob `awk -F: '$3 > 499 {print $1}' /etc/passwd`
# edquota -p ftpd `awk -F: '$1~/^user_.*$/ {print $1}' /etc/passwd`
在这里,user_* 是由程序自动生成的(根据网站页面注册提供的一种服务,并会自动添加系统帐户,来自于一个商业软件),数量是比较大的。

另外可以使用基于命令行的 setquota 命令。具体参见 man 手册吧:)

星期三, 一月 24, 2007

Apache mod_rewrite & .htaccess for mass VirtualHost

我遇到这样的应用,在 httpd.conf 中 Include virtual.conf,而在 virtual.conf 中全部都是以 "<"VirtualHost">" 方式建立的虚拟主机,每一个虚拟主机的配置大体上一致,是由程序根据注册的情况自动添加的。

现在的要求是,针对每一个站点,可能需要定义一些 Rewrite 规则。因为 "<"VirtualHost">" 是由程序自动生成的,所以不可能在每一个 VirtualHost 中手工更改,而这又是一个商业软件,更改代码也不是那么方便。一种安全一点的考虑是在全局来实现,即编写一个全局的 Rewrite 规则,在所有的虚拟主机中都可以使用。

但这种方法实际上是行不通的。回忆一下 VirtualHost 的基础知识,如果定义了一个 VirtualHost,那么定义的很多全局变量都将失效的,而且原来的主机也需要定义成 VirtualHost 才能继续使用。对 Rewrite 也是如此。实验如下:
httpd.conf
NameVirtualHost 192.168.0.98:80
"<"VirtualHost 192.168.0.98:80">"
ServerName www1.test.com
DocumentRoot /var/www/html/dir
RewriteEngine on (1)
RewriteRule "^/index\.html" "/test.html" (2)
"<"/VirtualHost">"

"<"VirtualHost 192.168.0.98:80">"
ServerName www2.test.com
DocumentRoot /var/www/html/dir2
# RewriteEngine on
# RewriteRule "^/index.html" "/test.html"
"<"/VirtualHost">"

"<"VirtualHost 192.168.0.98:80">"
ServerName www.test.com
DocumentRoot /var/www/html/test
"<"/VirtualHost">"

$ cat /var/www/html/dir/index.html
Index of TEST 1
$ cat /var/www/html/dir/test.html
TEST 1
$ cat /var/www/html/dir2/test2.html
TEST 2
$ cat /var/www/html/test/index.html
INDEX at TEST
$ cat /var/www/html/test/test.html

$ cat /etc/hosts
...
192.168.0.98 www1.test.com
192.168.0.98 www2.test.com
192.168.0.98 www.test.com
192.168.0.98 www.example.com
将(1),(2)分别放置于全局和 VirtualHost 内,就可以看到差异。即使在 VirtualHost 之前增加如下的规则也无效:
RewriteEngine on
RewriteCond %{HTTP_HOST} "!^www.test.com$" [NC,OR]
RewriteCond %{SERVER_NAME} "!^www.test.com$" [NC]
RewriteRule "(.*)" "http://www.test.com$1
这是希望把所有不是到 www.test.com 的请求重定向到 www.test.com(记得修改 /etc/hosts 文件如上),则理论上到 www.example.com 的请求应该会转向 www.test.com,如果这样可以做到,那么我只需要增加一个虚拟主机,然后在这里定义所有的 RewriteRule,再 Rewrite 回去也许是可以的。

但实际上这样也仍然是无效的,最后连接到的仍然是和默认的一样:www1.test.com──这是符合 VirtualHost 的基本原理的。所以 VirtualHost “优先级”更高,会覆盖掉全局的 Rewrite 设置。

那么另一个解决办法就是利用 .htaccess 来实现了。所有虚拟主机的 DocumentRoot 均是 /www/users/$virtualhostname,则方法是:
$ cat httpd.conf
"<"Directory "/www/users"">"
AllowOverride FileInfo
Order Allow, Deny
Allow From All
"<"/Directory">"

$ cat /www/users/www.test04.com/.htaccess
RewriteEngine on
RewriteRule "^index\.html" "/index.php"
注意这里的正则表达式是"^index\.html"而不是象全局和 VirtualHost 段中使用的 "^/index\.html",这是因为 .htaccess 是在指定的 Directory 中,所以其使用的是一个类似于相对路径的概念,当然这里是 URL 的一个相对路径。所以"^/index\.html"将得不到任何匹配。而 RewriteRule 部分的正则匹配串则是 URL 部分去除主机名后的那部分路径,并一定以"/"开头──也就是 DocumentRoot

这样就基本上可以实现了,但开放 .htaccess 以后可能会有负载问题,目前来看,可以考虑使用 PAM 来实现对于资源的控制看是否可行?

星期二, 一月 23, 2007

ncftp 几点

ncftp 客户端主体是基于交互式的 ftp browser,同时它也提供的专门的非交互模式的命令 ncftpget, ncftpput 等。

有几个命令比较重要的,了解一下:
get -R 传递一个目录
show 显示变量
set 设置变量,例如 set passive off 设置使用 PASV 模式(对 passive 可以用 passive 命令开关)

另外,设置环境变量 EDITOR:
export EDITOR=/usr/local/bin/vim
则可以在交互命令行上直接调用 vim 编辑远端的文件!

ftp 传输模式和防火墙设置

ftp 总是要用到两个端口,一个指定的默认端口(21)用来接受 ftp 指令和一个数据传输的端口。而 ftp 传输又可分为两种模式,即 PORT 和 PASV(passive 被动模式)。PORT 模式是由服务器端来指定数据传输所使用的端口,一般是20端口,而 PASV 则是由客户端来指定,一般是一个随机的高端端口。

所以为了 ftp 的正常使用,需要正确配置 iptables 防火墙,如果采用 PORT 模式,那么只需要加载了 ip_conntrack 模块,并且有:
iptables -A INPUT/FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
这样的配置即可,因为20端口可以看做一个 RELATED 的状态。

而如果使用 PASV 模式,则需要加载 ip_conntrack_ftp 和 ip_nat_ftp 这两个模块,否则客户端无法使用 passive 模式。

从实际使用的情况来看,如果不添加 ip_conntrack_ftp 和 ip_nat_ftp 模块,即不使用 PASV 模式时,速度比较慢,而且有时候会挂起、断掉。这可能也和 Windows 的客户端的有关,比如 cuteftp,运行时有如下的记录:
COMMAND:> [2007-1-31 10:55:18] PORT 192,168,0,64,11,208
[2007-1-31 10:55:18] 200 PORT command successful. Consider using PASV.

Red Hat kickstart

使用 Red Hat 作为生产系统,则应该利用 kickstart 提供的自动化安装和定制功能来提高装机的效率,并且可以减小企业环境中软件环境的不一致所造成的重复。一个 ks 配置文件如下:
# Kickstart file automatically generated by anaconda.

install
url --url ftp://192.168.0.98/pub/
lang en_US.UTF-8
langsupport --default=en_US.UTF-8 en_US.UTF-8 zh_CN.UTF-8 zh_TW.UTF-8
keyboard us
xconfig --card "ATI Rage XL" --videoram 8128 --hsync 30-61 --vsync 50-120 --resolution 800x600 --depth 16 --startxonboot --defaultdesktop kde
# network --device eth0 --bootproto dhcp
network --device eth0 static --ip 192.168.0.99 --netmask 255.255.255.0 --gateway 192.168.0.1 --nameserver 192.168.0.230 --hostname shopex
network --device eth1 --bootproto dhcp
rootpw --iscrypted $1$ntYDkgk/$AY.RmHTCjLUFJWzHlPYfF1
firewall --enabled --port=22:tcp --port=80:tcp
selinux --disabled
authconfig --enableshadow --enablemd5
timezone Asia/Shanghai
bootloader --location=mbr
# The following is the partition information you requested
# Note that any partitions you deleted are not expressed
# here so unless you clear all partitions first, this is
# not guaranteed to work
clearpart --all --drives=sda
part /boot --fstype ext3 --size=100 --ondisk=sda
part pv.5 --size=0 --grow --ondisk=sda
volgroup VolGroup00 --pesize=32768 pv.5
logvol swap --fstype swap --name=LogVol01 --vgname=VolGroup00 --size=1000 --grow --maxsize=2000
logvol / --fstype ext3 --name=LogVol00 --vgname=VolGroup00 --size=1024 --grow

%packages
@ editors
@ emacs
@ text-internet
@ dialup
@ compat-arch-support
@ chinese-support
@ development-tools
grub
kernel-smp
kernel-smp-devel
kernel-devel
e2fsprogs
lvm2
subversion
ntp
samba-common
samba-client
vsftpd

%post --interpreter /bin/bash
PKGSTORE=192.168.0.98
cd /opt
wget ftp://$PKGSTORE/pub/linux-2.6.14.2.tar.bz2 \
&& tar xfj linux-2.6.14.2.tar.bz2 \
&& cd linux-2.6.14.2 \
&& wget ftp://$PKGSTORE/pub/config-2.6.14.2.SMP -O ./.config \
&& make oldconfig \
&& make \
&& make modules \
&& make modules_install \
&& cp -vbf arch/i386/boot/bzImage /boot/vmlinuz-2.6.14.2.SMP \
&& cp -vf System.map /boot/System.map-2.6.14.2.SMP \
&& cp -vbf .config /boot/config-2.6.14.2.SMP \
&& mkinitrd -v -f /boot/initrd-2.6.14.2.SMP.img 2.6.14.2 \
&& /sbin/depmod -ae -F System.map 2.6.14.2 \
&& echo -e "title Red Hat Linux AS4 (2.6.14.2.SMP)
\troot (hd0,0)
\tkernel /vmlinuz-2.6.14.2.SMP ro root=/dev/VolGroup00/LogVol00
\tinitrd /initrd-2.6.14.2.SMP.img" >>/boot/grub/grub.conf \
&& sed -i "s/default=0/default=2/" /boot/grub/grub.conf
cd ..
sed -i 's/id:5:initdefault:/id:3:initdefault:/' /etc/inittab
wget ftp://$PKGSTORE/pub/trun-off.list
for SERVICE in `cat turn-off.list`
do
/sbin/chkconfig $SERVICE off
done
这样,通过在 %package 部分定制需要的包,在 %post 部分运行需要的命令(这里是给内核升级并关闭一些服务,因为原来的 2.6.9-SMP 内核有问题,不能正常重启),可以勉强达到对软件环境的定制和复用需求。

在这个例子里,kickstart 的配置文件和所有的安装包以及其他辅助文件都放置在 ftp 服务器上:
ftp://192.168.0.98/pub/ks/base-baode_36G.ks
ftp://192.168.0.98/pub/ks/turn-off.list
ftp://192.168.0.98/pub/config-2.6.14.2.SMP
ftp://192.168.0.98/pub/linux-2.6.14.2.tar.bz2
ftp://192.168.0.98/pub/RedHat
注意安装树 ftp://192.168.0.98/pub/RedHat/RPMS 应该包含了所有需要的 rpm 包,可以将4张光盘的所有的 RPMS 下的 rpm 文件都拷贝到这里面,而在 ks 文件中只需指定 url --url ftp://192.168.0.98/pub/。

然后在需要安装的主机上运行安装光盘,在 boot: 下键入:
boot: linux ks=ftp://192.168.0.98/pub/ks/base-baode_36G.ks text
安装程序会询问你使用哪个网络接口,保证网线正确连通了之后,选择正确的接口,以后的东西都会自动完成了。

针对不同的系统制作不同的 ks 文件,可以的得到不同的定制环境。然后正确的作法应该是,利用 DHCP 和 tftp 来实现 PXE 的自动安装,通过 PXE 启动 grub,在菜单中选择需要的安装项目,可以得到更好的自动化实现。

服务器安装完毕之后,有一些内容需要检查一下,最主要的是:
1. 服务器是否能够正确的启动、关闭和重启
2. 服务器的 22 号端口是否能够正常访问,并能够 su - 到 root 帐号

星期日, 一月 21, 2007

一个关于网络基本原理的问题

另外一个问题是,接到同一个物理设备如交换机的两台主机使用不同的 IP 网段,能否 ping 通?

想一想 IP 的基本原理,想想主机是怎么计算路由的。

当系统需要连接到另一台主机时,会首先将目标路由与自己的网络地址进行比较(关于网络地址的计算,参考这里),如果发现不是自己网段的,就会到自己的路由表里寻找路由,一般会是默认网关,

docbook xml (1)

XML 的应用已经非常广泛,现在必须放到我们的学习计划中来。但目前好像没有什么很好的材料,而 XML 本身也是比较复杂的,所以如果单纯的去啃那些理论性的东西,一定会非常的枯燥和令人厌烦,特别是那种文档性质的东西就更是如此(系统化介绍的书籍会好些)。那么正确的方法应该是从一种实际的应用开始,这相对来说应该会简单一些。DocBook 就是这样的一种应用。

不过 DocBook 本身也够理论化的,一大堆概念摆在面前也不是那么好消化的。在看了《DocBook: The Definitive Guide》后,对 XML 和 DocBook 基本上有了点认识(当然对 XML 以前也不是没有一点概念:_),但仍然是有点头大的。所以我想,干脆不管多的,先实际操作起来,边做边学吧──从实践中去领会应该是最好的办法。

首先是安装 DocBook,因为是使用 XML 的 DocBook 而不是 SGML,所以安装 docbook-xml-4.4。所谓安装 docbook-xml,其实基本上就是把一些 DocBook XML 的 DTD 文件拷贝到系统中。DTD(Document Type Definition)实际上就是一些文本文件,用来定义 XML 的有效性的,即 XML 可以包含那些元素,这些元素应该是怎样的顺序和嵌套关系、它们可以有那些子元素等。比如在 DocBook 这个具体的例子中,一个 Book 可以包含 Abstract, Chapter, Section, Paragraph, Bibliography... 这些元素,而象 Foo 这样的东西出现在你书籍的结构中就毫无意义;同时,你不可能把 Chapter 放在 Section 里;也不能把 Bibliography 放在书籍开头而把 Abstract 放在结束的地方,所有这些都由 DTD 定义,当处理程序进行处理时会自动进行检查。通常 DocBook 的 DTD 是 docbook.dtd,XML 为 docbookx.dtd。

我直接使用了 BLFS 上的安装方法:
pkgname = "docbook-xml";
version = "4.4";
user = "docbook-xml";
groups = "";
group = "docbook-xml";
archive = "docbook-xml-4.4.zip";
command = "mkdir docbook-xml";
command = "cd docbook-xml";
command = "unzip ../docbook-xml-4.4.zip";
command = "install -v -d -m755 /usr/share/xml/docbook/xml-dtd-4.4";
command = "install -v -d -m755 /etc/xml";
command = "cp -v -af docbook.cat *.dtd ent/ *.mod /usr/share/xml/docbook/xml-dtd-4.4";
command = "if [ ! -e /etc/xml/docbook ]; then xmlcatalog --noout --create /etc/xml/docbook; fi";
command = "xmlcatalog --noout --add "public" "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" /etc/xml/docbook";
command = "xmlcatalog --noout --add "public" "-//OASIS//DTD DocBook XML CALS Table Model V4.4//EN" "file:///usr/share/xml/docbook/xml-dtd-4.4/calstblx.dtd" /etc/xml/docbook";
command = "xmlcatalog --noout --add "public" "-//OASIS//DTD XML Exchange Table Model 19990315//EN" "file:///usr/share/xml/docbook/xml-dtd-4.4/soextblx.dtd" /etc/xml/docbook";
command = "xmlcatalog --noout --add "public" "-//OASIS//ELEMENTS DocBook XML Information Pool V4.4//EN" "file:///usr/share/xml/docbook/xml-dtd-4.4/dbpoolx.mod" /etc/xml/docbook";
command = "xmlcatalog --noout --add "public" "-//OASIS//ELEMENTS DocBook XML Document Hierarchy V4.4//EN" "file:///usr/share/xml/docbook/xml-dtd-4.4/dbhierx.mod" /etc/xml/docbook";
command = "xmlcatalog --noout --add "public" "-//OASIS//ELEMENTS DocBook XML HTML Tables V4.4//EN" "file:///usr/share/xml/docbook/xml-dtd-4.4/htmltblx.mod" /etc/xml/docbook";
command = "xmlcatalog --noout --add "public" "-//OASIS//ENTITIES DocBook XML Notations V4.4//EN" "file:///usr/share/xml/docbook/xml-dtd-4.4/dbnotnx.mod" /etc/xml/docbook";
command = "xmlcatalog --noout --add "public" "-//OASIS//ENTITIES DocBook XML Character Entities V4.4//EN" "file:///usr/share/xml/docbook/xml-dtd-4.4/dbcentx.mod" /etc/xml/docbook";
command = "xmlcatalog --noout --add "public" "-//OASIS//ENTITIES DocBook XML Additional General Entities V4.4//EN" "file:///usr/share/xml/docbook/xml-dtd-4.4/dbgenent.mod" /etc/xml/docbook";
command = "xmlcatalog --noout --add "rewriteSystem" "http://www.oasis-open.org/docbook/xml/4.4" "file:///usr/share/xml/docbook/xml-dtd-4.4" /etc/xml/docbook";
command = "xmlcatalog --noout --add "rewriteURI" "http://www.oasis-open.org/docbook/xml/4.4" "file:///usr/share/xml/docbook/xml-dtd-4.4" /etc/xml/docbook";
command = "if [ ! -e /etc/xml/catalog ]; then xmlcatalog --noout --create /etc/xml/catalog; fi";
command = "xmlcatalog --noout --add "delegatePublic" "-//OASIS//ENTITIES DocBook XML" "file:///etc/xml/docbook" /etc/xml/catalog";
command = "xmlcatalog --noout --add "delegatePublic" "-//OASIS//DTD DocBook XML" "file:///etc/xml/docbook" /etc/xml/catalog";
command = "xmlcatalog --noout --add "delegateSystem" "http://www.oasis-open.org/docbook/" "file:///etc/xml/docbook" /etc/xml/catalog";
command = "xmlcatalog --noout --add "delegateURI" "http://www.oasis-open.org/docbook/" "file:///etc/xml/docbook" /etc/xml/catalog";
command = "cd ..";
command = "rm -rf docbook-xml";
time = "20070121 22:12:35 Sun";
这中间有许多 xmlcatalog(属于 libxml2 包),只是为了创建 /etc/xml/catalog 和 /etc/xml/docbook 这两个文件。这两个文件本身也是 XML 文件,只是比较特殊,是专门的 catalog 文件:!DOCTYPE catalog PUBLIC "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN"。所谓 catalog,实际上是一些映射文件,将 Public Identifier 映射为 System Identifier。

而 Identifier 是 DocBook XML 文档中对于外部文件的引用的说明,即引用了那些外部文档,通常都是 DTD,如 DocBook 本身的 DTD docbookx.dtd(注意区分一下 DocBook 文档和 DocBook 本身!)。Identifier 通常分为 PUBLIC 和 SYSTEM 两种,例如在一个 XML 文档中:
"<"!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"">"
这里是一个文档类型申明,即 DTD,PUBLIC 后面是一个 PUBLIC Identifier,然后是一个 SYSTEM Identifier,这里实际上是一个映射,将 PUBLIC Identifier 映射为 SYSTEM Identifier,所以 System Identifier 并不是指只有系统内部的 DTD!如上,只要是一个 URI 就行,当然必须是实际有效的。另外,XML 只能使用 System Identifier,所以必然会有这样一个映射,或者直接使用 SYSTEM:
"<"!DOCTYPE chapter SYSTEM "/usr/share/sgml/docbook/xml-dtd-4.2-1.0-25/docbookx.dtd"">"
所以编写一个 XML 文档,通常包括如下步骤:
1. 按照 DTD 定义编辑 XML 文档
2. 使用解析器进行解析,需要 Validate 检查
3. 依照样式表 XSL 将 XML 转换成其他格式,如 HTML/TEX 等
4. 针对不同格式使用不同工具检查效果

mplayer -zoom

我在 LFS 下安装的 mplayer,播放视频时电击最大化或拉大窗口,屏幕大小却不变。可以通过使用 -zoom 参数来解决这个问题。

在 Fedora 下没有这个问题,不知道是否是编译的参数的问题?

星期六, 一月 20, 2007

*** 关于 upm 的用户的问题 ***

主要是操作包的用户还是应该和操作数据的用户分开!比如安装 mysql,如果使用了如下的方式:
pkgname = "mysql";
version = "4.1.22";
user = "mysql";
groups = "";
group = "mysql";
archive = "mysql-4.1.22.tar.gz";
command = "tar xfz mysql-4.1.22.tar.gz";
command = "cd mysql-4.1.22";
command = "./configure --without-debug --with-extra-charsets=gb2312 --enable-assembler --without-isam --without-innodb --with-pthread --enable-thread-safe-client --with-client-ldflags=-all-static --with-mysqld-ldflags=-all-static --localstatedir=/data/mysql";
command = "make";
command = "make install";
command = "scripts/mysql_install_db --user=mysql";
command = "cp support-files/mysql.server /etc/rc.d/init.d/mysqld";
command = "chmod 0700 /etc/rc.d/init.d/mysqld";
command = "cd ..";
command = "rm -rf mysql-4.1.22";
command = "cd /usr/local/libexec";
command = "cp mysqld mysqld.backup";
command = "strip mysqld";
time = "20070107 21:22:55 Sun";
那么 /data/mysql 的属主和这个包本身的属主就都是 mysql 这个用户了。这在安装的时候固然是方便了,但在删除的时候就会有问题,因为你基本上只会希望删除包的的程序,而不是它产生的其他数据。

所以类似于 /var 这样的目录不应该出现在初试化目录中;我在 userpack 中也设定了给用户名增加前缀的功能,比如增加"_"前缀(不过没有经过完善的测试,对于测试,我也需要花很多时间好好学习学习──想做的事情很多,能做的事情很少,唉),当然如果分类的问题解决了,那么每个用户名可以自然的增加一个分类名,如 db.mysql,就不会有这个问题了;而对于运行象 mysql_install_db 这样的命令,还是在完善了 sudo 命令的基础上,由 root 身份来执行并指定不同的用户比较好。