﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-nighTuner &amp; Yuyu's Space-文章分类-Linux</title><link>http://www2.blogjava.net/nighTuner/category/1022.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 19:33:34 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 19:33:34 GMT</pubDate><ttl>60</ttl><item><title>cvs client howto</title><link>http://www.blogjava.net/nighTuner/articles/3878.html</link><dc:creator>nighTuner</dc:creator><author>nighTuner</author><pubDate>Thu, 28 Apr 2005 02:15:00 GMT</pubDate><guid>http://www.blogjava.net/nighTuner/articles/3878.html</guid><wfw:comment>http://www.blogjava.net/nighTuner/comments/3878.html</wfw:comment><comments>http://www.blogjava.net/nighTuner/articles/3878.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/nighTuner/comments/commentRss/3878.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/nighTuner/services/trackbacks/3878.html</trackback:ping><description><![CDATA[什么是 CVS？<BR><BR>　　CVS 是一种客户机／服务器系统，可以让开发人员将他们的项目存储在称为资源库的中央位置。使用 cvs 客户机工具，开发人员可以对资源库的内容进行更改。CVS 资源库会依次记录对每个文件所做的每个更改，并创建一个完整的项目开发进展历史。开发人员可以请求特定源文件的旧版本、查看更改日志，并根据需要执行其它一些有用的任务。<BR><BR>　　许多开放软件项目都有他们自己的 CVS 服务器，项目开发人员把这些服务器作为他们工作的源码仓库。源码仓库的源码目录中保存的都是实现版本控制的历史文件(history file)，历史文件名为filename,v。历史文件包含用来恢复所有版本文件的足够信息、所有提交的信息以及提交者信息。历史文件常常被称作RCS文件，因为最早是RCS程序用这种格式来保存文件的所有修改信息，可以从man rcsfile得到历史文件的。<BR><BR>　　开发人员每天都会改进 CVS 资源库内的源码，且他们往往分布在世界各地，而 CVS 提供了一种必要的机制，将他们的项目联合成一个集中的、协作的整体。CVS 创建了"组织粘和剂"，可以让这些开发人员改进代码而不会干扰别人、丢失重要数据或遗漏彼此对特定源文件的重要更新。<BR><BR>　　当开发人员准备好以后，他们把 CVS 上部分当前工作打包成 .tar.gz 文件，作为软件包的新官方版本来发布它。然而，由于种种原因，最新的官方发行版有时并不是最新的。在本教程的第一部分将首先介绍如何使用CVS为个人使用获取最新和最高开发人员版本的源码。<BR><BR>　　CVSROOT<BR><BR>　　在开始前，您需要了解一些 CVS 的基础知识。首先，为了连接到 CVS 资源库，您需要知道称为 "CVSROOT" 的路径。CVSROOT 是一个字符串，就象 URL，它告诉 cvs 命令远程资源库在哪里，以及如何连接它。不仅如此，根据 CVS 资源库是本地的还是远程的，以及连接到它的不同方式，CVS 还有许多不同的 CVSROOT 格式。这里有一些带有解释的 CVSROOT 示例。<BR><BR>　　本地 CVSROOT<BR><BR><BR>CVSROOT=/home/cvsroot<BR><BR>　　这是一个本地 CVSROOT 路径的示例；如果您想连接到 /home/cvsroot 中存在的本地资源库，或者有一个经 NFS 安装在 /home/cvsroot 的资源库，需要象这样使用 CSROOOT。<BR><BR>　　远程密码服务器 CVSROOT<BR><BR><BR>CVSROOT=:pserver:cvs@foo.bar.com:/home/cvsroot<BR><BR>　　这里是一个远程资源库的 CVSROOT 示例，该资源库位于 foo.bar.com 主机上，并在这台机器的 /home/cvsroot 目录中活动。前导 ":pserver:" 告诉我们的客户机使用 CVS 密码服务器协议连接到这台远程机器，该协议内置在 CVS 中。一般情况下，公共 CVS 资源库使用密码服务器协议以允许匿名用户访问。<BR><BR>　　远程 rsh/ssh CVSROOT<BR><BR><BR>CVSROOT=drobbins@foo.bar.com:/data/cvs<BR><BR>　　这是一个使用 RSH 或 SSH 协议的 CVSROOT 的示例；在该例中，CVS 服务器尝试使用 drobbing 帐户来访问在 foo.bar.com 上的资源库。如果 CVS_RSH 的环境变量设置成 "ssh"，那么我们的客户机就尝试用 ssh 去连接；否则就使用 rsh。那些关注安全性的用户往往使用 ssh 访问法；但是，无论是 RSH 还是 SSH 方法都不能对匿名用户提供一种获取源码的方式。为了使用这种方法，您在 foo.bar.com 上必须有个登录帐户。<BR><BR>　　除了 CVSROOT 之外，您还需要知道要检出的模块（源码集合）的名称，以及登录到 CVS 密码服务器的匿名密码。与匿名 ftp 不同，匿名密码没有什么"标准"格式，所以您需要从开发人员网站或开发人员那里获得具体的密码。一旦知道了所有这些信息，就可以开始了。<BR><BR>　　与 CVS 交互<BR><BR>　　获取源码需要两个步骤。首先，以远程密码服务器的方式登录到CVS服务器。然后，使用"checkout"命令获取源码。这里有一组命令的示例，用于检出最新的 Samba 源码（一个流行的 UNIX/Windows 集成项目）：<BR><BR><BR># export CVSROOT=:pserver:cvs@pserver.samba.org:/cvsroot<BR><BR>　　第一个命令设置 CVSROOT 环境变量。如果没有设置这个变量，下面两个命令将需要跟在 "cvs" 命令后再加上 "-d :pserver:cvs@pserver.samba.org:/cvsroot"。设定 CVSROOT 环境变量省去了一些输入。<BR><BR><BR># cvs login<BR>(Logging in to <A href="mailto:cvs@pserver.samba.org)">cvs@pserver.samba.org)</A> <BR>CVS password：（在此输入密码）<BR># cvs -z5 checkout samba<BR>U samba/COPYING <BR>U samba/Manifest <BR>U samba/README<BR>U samba/Read-Manifest-Now <BR>U samba/Roadmap <BR>U samba/WHATSNEW.txt<BR>（这只是完整的 cvs check 输出的一小段摘录）<BR><BR>　　上面第一个 cvs 命令是让我们登录到 pserver，第二个命令告诉 CVS 客户机使用 gzip 压缩级 5 ("-z5") 在慢速连接上加快传输速度，来检出 ("checkout") samba 模块。对于每个在本地创建的新文件，cvs 都会打印 "U [path]" 表明这个特定的文件已经在磁盘上更新过了。<BR><BR>　　一旦检出命令完成，将在包含最新源码的当前工作目录中看到 "samba" 目录。还会注意到每个子目录下都有一个"CVS"目录 -- CVS 在这些目录中存储帐户信息，可以放心地忽略它们。一旦检出结束，用户就无需担心是否设置了 CVSROOT 环境变量，也无需再在命令行上指定它，因为现在所有额外的 "CVS" 目录里都有它的缓存。<BR><BR>　　记住 -- 只需要为初始登录和检出设置 CVSROOT。<BR><BR>　　更新源码<BR><BR>　　现在已经有了源码，就可以继续编译和安装它们、检查它们，或者对它们执行任何操作。<BR><BR>　　偶尔，也需要将已检(checkout)出的源目录与 CVS 上的当前版本保持同步。为了做到这一点，您无需再次登录到 pserver；cvs 会将您的认证信息缓存到那些 "CVS"帐户目录中。首先，进入主检出目录（在这里是 "samba"），然后输入：<BR><BR><BR># cvs update -dP <BR><BR>　　如果有任何新文件，cvs就会在更新每一行的时候输出 "U [path]" 行。另外，如果本地编译了源码，您有可能会看到许多 "? [path]" 行；cvs 指出这些目标文件不来自于远程资源库。<BR><BR>　　另外，请注意我们用于 "cvs update" 的两个命令行选项。"-d" 告诉 cvs 创建可能已添加到资源库的新目录（缺省情况下，这不会发生），"-P" 告诉 cvs 从本地已检出的源码副本中除去所有空目录。"-P" 是个不错的选择，因为 cvs 倾向于收集许多随时间产生的空（曾经使用过，但现在已经放弃）目录树。<BR><BR>　　如果只是要获得最新的源码，这些就是您所需要了解的。现在，来看一下作为一个开发人员如何与 CVS 交互。<BR><BR>　　修改文件<BR><BR>　　作为一名开发人员，您需要修改 CVS 上的文件。要修改文件，只需要对资源库的本地副本进行适当的更改。在您明确地告诉 cvs "提交"更改之前，您对源码做的更改不会应用到远程资源库。测试过所有修改以确保它们可以正常运作之后，就可以准备将这些更改运用到资源库中，遵循下面的两个步骤。首先，在主源码目录中输入以下命令来更新源码：<BR><BR><BR># cvs update -dP <BR><BR>　　CVS 合并其他人的更改<BR><BR>　　我们在前面已经看到，"cvs update"将用资源库中的当前版本使您的源码保持最新状态 -- 但对您已经做过的更改会发生什么情况呢？不要担心，它们不会被丢弃。如果另一个开发人员对您没动过的文件做了一些更改，您的本地文件将进行更新以使它与资源库中的版本保持同步。<BR><BR>　　如果您修改了本地文件中的第 1-10 行，而另一个开发人员删除了第 40-50 行，在文件末尾添加了 12 行新行，同时修改了 30-40 行，然后在您之前他向资源库提交了他的更改，cvs 会智能地将这些更改合并到您本地已修改的副本中，这样你们的更改就都不会丢失。这可以让两个或更多开发人员针对同一文件的不同部分同时操作。<BR><BR>　　然而，如果两个或多个开发人员更改同一文件的同一部分，那么事情就有些复杂了。如果发生这种情况，cvs 会告诉您有冲突发生。所做的工作不会丢失，但需要手工干预，因为 cvs 需要您提供意见来决定如何合并这些有冲突的更改。<BR><BR>　　提交<BR><BR>　　我们过一会儿来看看冲突究竟是如何解决的，但现在，先让我们假设在输入 "cvs update -dP" 后没有冲突 -- 通常都没有冲突。由于没有冲突，本地源码是最新的。可以在主源码目录中输入以下命令来提交对资源库的更改：<BR><BR><BR># cvs commit <BR><BR>　　提交所起的作用<BR><BR>　　"cvs commit" 不只将您的更改应用到资源库。在真正将您的更改提交给远程资源库之前，cvs 会调用缺省编辑器，可以让您输入修改的描述。输入了注解后，保存该文件，退出编辑器，您的更改（和注解）就会应用到远程资源库，小组中的其他开发人员可以看到这些更改。<BR><BR>　　查看日志<BR><BR>　　要查看某个特定文件完整的历史以及提交时开发人员（包括您）所加的注解是很容易的。要查看这些信息，输入：<BR><BR><BR># cvs log myfile.c<BR><BR>　　"cvs log" 命令是递归的，所以如果您想查看整个目录树的完整日志，只需要进入该目录，输入：<BR><BR><BR># cvs log | less<BR><BR>　　提交选项<BR><BR>　　您可能想要使用另一个输入 "cvs commit" 时 cvs 在缺省情况下启动的编辑器。如果是这样，只需要把您希望使用的编辑器的名称放进 EDITOR 环境变量中。另外，也可以将更新日志消息作为命令行选项指定，这样， cvs 就不需要一上来就装入编辑器：<BR><BR><BR># cvs commit -m 'I fixed a few silly bugs in portage.py'<BR><BR>　　.cvsrc 文件<BR><BR>　　在继续了解其它 cvs 命令前，建议设置 ~/.cvsrc 文件。通过在您主目录中创建 .cvsrc 文件，可以告诉 cvs 在缺省情况下使用您所需的命令行选项，这样就不必每次都输入它们。这里有一个推荐的缺省 .cvsrc 文件：<BR><BR><BR>cvs -q <BR>diff -u -b -B<BR>checkout -P<BR>update -d -P<BR><BR>　　除了为一组 cvs 命令设置有用的选项以外，.cvsrc 的第一行将 cvs 置于安静模式下，它的主要好处是使 "cvs update" 输出更简洁，更具可读性。另外，一旦完成 .cvsrc 后，就可以输入 "cvs update" 而不是 "cvs update -dP"。<BR><BR>　　将文件添加到资源库<BR><BR>　　要将源文件添加到 CVS 很容易。首先，用您喜爱的文本编辑器创建该文件。然后，输入以下命令：<BR><BR><BR># cvs add myfile.c <BR>cvs server: use 'cvs commit' to add this file permanently<BR><BR>　　这将告诉 cvs 在您下次执行 "cvs commit" 时，将该文件添加到资源库。在那之前，其它开发人员看不它。<BR><BR>　　将目录添加到资源库<BR><BR>　　将目录添加到 CVS 的过程类似于：<BR><BR><BR># mkdir foo <BR># cvs add foo <BR>Directory /home/cvsroot/mycode/foo added to the repository <BR><BR>　　与添加文件不同，当您添加目录时，它会立即出现在资源库中；不需要 cvs commit。将本地目录添加到 cvs 后，您会注意到在远程cvs服务器的对应目录中创建了一个 "CVS" 目录，它作为包含 cvs 帐户数据的容器。因而，您只要看一下其中是否有 "CVS" 目录，就可以很容易地知道某个目录是否已添加到远程cvs服务器的 cvs中了<BR><BR>　　在将文件或目录添加到资源库之前，您必须确保它的父目录已经添加到 CVS。否则，您会看到类似于下面的错误：<BR><BR><BR># cvs add myfile.c cvs add: cannot open CVS/Entries for<BR>reading: No such file or directory cvs [add aborted]: no repository <BR><BR>　　熟悉 "cvs update"<BR><BR>　　在了解如何解决冲突之前，先让我们熟悉一下 "cvs update" 命令的输出。如果创建了一个包含 "cvs -q" 行的 ~/.cvsrc 文件，您会发现 "cvs update" 的输出相当容易理解。"cvs update" 通过打印单个字符、空格和文件名告诉您它都做些什么，看到些什么；如下例所示：<BR><BR><BR># cvs update -dP<BR>? distfiles<BR>? packages<BR>? profiles <BR><BR>　　"cvs update" 用 "?" 字符指示在地副本中找到的这些特殊文件。它们不是资源库的正式部分，也不是计划要添加的部分。这里有一个CVS使用的所有其它单字符信息性消息的列表：<BR><BR>　　U [path]<BR><BR>　　在本地资源库中创建新文件，或者更新了您没有动过的文件时使用。<BR><BR>　　A [path]<BR><BR>　　该文件是计划要添加的，使用 "cvs commit" 时，它被正式添加到资源库。<BR><BR>　　R [path]<BR><BR>　　象 "A" 一样，"R" 让您知道该文件计划要除去。输入 "cvs commit" 后，该文件就会从资源库中除去。<BR><BR>　　M [path]<BR><BR>　　这意味着您已经修改过该文件了；而且，有可能资源库中新的更改已成功地合并到该文件。<BR><BR>　　C [path]<BR><BR>　　"C" 字符表明该文件存在冲突，需要在使用 "cvs commit" 提交更改前手工修改它。<BR><BR>　　如何解决冲突<BR><BR>　　现在，让我们看一下如何解决冲突。我参与了大部分的 Gentoo Linux 项目，我们在 cvs.gentoo.org 上设置了自己的 cvs 服务器。我们这些开发人员花了绝大部分时间来修改 "gentoo-x86" 模块内部的源码。在 gentoo-x86 模块中，有一个叫 "ChangeLog" 的文件，它包含了（您猜一下它）我们对资源库中该文件做的主要更改的描述。<BR><BR>　　冲突的示例<BR><BR>　　因为几乎每次开发人员对 CVS 进行主要更改时都会对该文件做一些修改，这就成为冲突的主要根源 -- 这里有冲突的一个示例。假设我在 ChangeLog 的顶部添加了以下行：<BR><BR><BR>date 25 Feb 2001<BR>This is the thing I added myself<BR><BR>　　然而，在我提交这二新行之前，另一个开发人员也在 ChangeLog 的顶部添加了这些行并提交了他的更改：<BR><BR><BR>date 25 Feb 2001<BR>This is the part added by another developer<BR><BR>　　现在，当我运行 "cvs update -dP" （每次提交前您都应该这么做），cvs 不能把他的更改合并到我的 ChangeLog 本地副本，因为我们俩都向文件的同一部分添加了行 -- cvs 怎么知道用哪个版本？所以，CVS 会出现以下错误：<BR><BR><BR>RCS file: /home/cvsroot/gentoo-x86/ChangeLog,v<BR>retrieving revision 1.362<BR>retrieving revision 1.363<BR>Merging differences between 1.362 and 1.363 into ChangeLog<BR>rcsmerge: warning: conflicts during merge<BR>cvs server: conflicts found in ChangeLog<BR>C ChangeLog<BR><BR>　　啊 -- 有冲突！幸好消除这些冲突很容易。如果我启动我喜爱的文本编辑器，将会在 ChangeLog 文件的顶部看到以下文本：<BR><BR><BR>&lt;&lt;&lt;&lt;&lt;&lt;&lt; ChangeLog<BR>date 25 Feb 2001<BR>This is the thing I added myself<BR>=======<BR>date 25 Feb 2001<BR>This is the part added by another developer<BR>&gt;&gt;&gt;&gt;&gt;&gt;&gt; 1.363<BR><BR>　　cvs 不是选其中一个而舍弃另一个，而是把两个版本都加进 ChangeLog 文件，并用特殊的分隔符将它们圈起，以明确地标记出有问题的冲突。现在，我要用一个应该出现在 ChangeLog 里的文本来替换这部分；在这种情况下，替换的文本既不是我的版本也不是他的版本，而是两者的组合：<BR><BR><BR>date 25 Feb 2001<BR>This is the thing I added myself<BR>This is the part added by another developer<BR><BR>　　我用适当的文本替换掉了有冲突的部分（并除去了 "=======" 等标记），可以顺利地将我的更改提交给 cvs。<BR><BR>　　无论什么时候需要编辑文件来解决冲突时，都要确保已经浏览过整个文件，以便您知道所有内容；如果您忘记解决某个冲突，那么在这个冲突解决之前，cvs 是不允许您提交的！很显然，除去 cvs 添加到冲突文件中的特殊标记是很重要的。<BR><BR>　　如果您在解决某个冲突时犯了错误，然后意外地保存了您所作的更改，那么您可以在 ".#filename.version" 文件中找到您的原始副本。<BR><BR>　　删除文件<BR><BR>　　现在应该学习关于 CVS 的最后一个技巧 -- 从资源库中除去文件。除去文件是一个两阶段过程。首先，从源码的本地副本删除该文件，然后执行相应的 "cvs remove" 命令：<BR><BR><BR># rm myoldfile.c<BR># cvs remove myoldfile.c <BR><BR>　　在您下次提交时，该文件计划将从资源库中除去。一旦提交，该文件会从资源库当前的版本中正式删除。然而， cvs 不会将该文件抛弃，而是仍然完整地保留该文件的内容及其历史，以备您以后需要它。这只是 cvs 保护您有价值的源代码的众多方法之一。<BR><BR>　　"cvs remove" 是递归的，这意味着您可以删除一批文件，然后从父目录运行不带其它自变量的 "cvs remove" 命令。这样做会在下次提交时标记所有已删除的文件。<BR><BR>　　如果您想除去整个目录，我推荐使用下列过程。首先，从物理上删除，"cvs remove" 删除目录中的所有文件：<BR><BR><BR># rm *.c <BR># cvs remove <BR><BR>　　然后执行提交：<BR><BR><BR># cvs commit<BR><BR>　　这里有一个诀窍。执行以下步骤删除目录：<BR><BR><BR># cd ..<BR># cvs remove mydir<BR># rm -rf mydir<BR><BR>　　请注意，除去目录不需要另一次提交 -- 把目录添加到资源库和从资源库除去目录是实时的。<BR><BR>　　修订号<BR><BR>　　源码仓库中的一个文件可以有多个版本，同样一个软件可能有多个版本。一般在CVS中前一种意义上的版本（源码仓库中文件的版本）一般称为修订号(revisions)，而对软件的版本一般称为发布(release)。<BR><BR>　　一个文件的修订号一般是依次递增的，一般以偶数个通过"."连接的十进制数串来表示，如：`1.1', `1.2', `1.3.2.2'甚至`1.3.2.2.4.5<BR><BR>　　标签的定义和使用<BR><BR>　　源码仓库中各个文件的修订号是独立增加的，相互之间没有任何关联关系，和软件的发布号也没有任何关系，例如一个项目中的各个文件的修订号可能是这样的：<BR><BR><BR>ci.c 5.21<BR>co.c 5.9<BR>ident.c 5.3<BR>rcs.c 5.12<BR>rcsbase.h 5.11<BR>rcsdiff.c 5.10<BR>rcsedit.c 5.11<BR>rcsfcmp.c 5.9<BR>rcsgen.c 5.10<BR>rcslex.c 5.11<BR>rcsmap.c 5.2<BR>rcsutil.c 5.10<BR><BR>　　为了便于标记，可以使用标签来为某个特定版本的特定文件设定一个标记以方便访问，可以使用cvs tag和cvs rtag来定义标签，其中cvs tag用来为仓库中当前工作文件(或文件集合)指定一个符号标记；cvs rtag用来显式地为源码仓库的特定修订号的文件定义一个标记。例如下面的例子就是给文件backend.c的当前修订号定义一个标签，然后察看该文件的状态：<BR><BR><BR>$ cvs tag rel-0-4 backend.c<BR>T backend.c<BR>$ cvs status -v backend.c<BR><FONT face=宋体>===========================================================<BR></FONT>File: backend.c Status: Up-to-date<BR>Version: 1.4 Tue Dec 1 14:39:01 1992<BR>RCS Version: 1.4 /u/cvsroot/yoyodyne/tc/backend.c,v<BR>Sticky Tag: (none)<BR>Sticky Date: (none)<BR>Sticky Options: (none)<BR>Existing Tags:<BR>rel-0-4 (revision: 1.4)<BR><BR>　　但是在实际应用中很少会为特定文件定义一个标签，而往往是在开发过程中的特定阶段为特定项目的所有文件定义一个标签，以方便发布或者定义分支，例如：<BR><BR><BR>$ cvs tag rel-1-0 .<BR>cvs tag: Tagging .<BR>T Makefile<BR>T backend.c<BR>T driver.c<BR>T frontend.c<BR>T parser.c<BR><BR>　　定义标签以后，可以在随后的任何时候访问对应该标签的项目文件，例如下面这个命令就用来实现检出对应于标签rel-1-0的所有文件(可能是软件的1.0发布)：<BR><BR><BR>$ cvs checkout -r rel-1-0 tc<BR><BR>　　可以想像标签为联系特定修订号文件的曲线索引，例如：<BR><BR>　　这里表示在软件开发过程中的定义了标签*，也可这样看待标签：<BR><BR>　　当然也可以删除标签，例如：<BR><BR>　　cvs rtag(/tag) -d rel-0-4 tc 删除模块tc的rel-0-4标记<BR><BR>　　备份源码仓库<BR><BR>　　备份： 首先断开所有的cvs连接，然后使用cp命令备份即可<BR><BR>　　分支<BR><BR>　　通过CVS可以实现将对源码的修改提交给一个独立的开发线，被称为分支(branch)。当对分支的文件进行修改时，这些修改不会对主分支和其他分支产生影响。<BR><BR>　　随后可以将将一个分支的修改合并(merging)到其他分支。合并是通过cvs update -j来合并修改到当前工作目录(本地)，然后就可以提交修改来影响其他分支了。<BR><BR>　　分支的重要性<BR><BR>　　让我们假设这种情况，项目tc的1.0版本已经搞定，你将继续开发tc项目，计划在几个月内发布1.1版本，但是客户抱怨软件中有致命的错误。因此你检出1.0版本(这里就是需要使用标记的原因)并发现了这个bug的原因。然而当前的源码处于1.0和1.1版本之间因此代码处于混乱状态，而且在一个月内不大可能出现稳定版本，因此不大可能根据当前的版本得到一个修复错误的版本来发布。<BR><BR>　　对于这种情况这就需要创建一个包含错误修改的1.0分支发布，而不需要影响当前的开发，在合适的时候可以将修正合并的主发布中去。<BR><BR>　　创建分支<BR><BR>　　创建分支首先为拟修改的某些文件创建一个标签(tag)，标签是赋于一个文件或一组文件的符号.在源代码的生命周期里，组成一组模块的文件被赋于相同的标签。<BR><BR>　　创建标签：在工作目录里执行cvs tag 。<BR><BR>　　例: 为src创建标签：<BR><BR>　　cvs checkout src(/update亦可，用来更新本地的源代码)<BR><BR>　　cvs tag release-1-0(为当前最新源码加一个标签)<BR><BR>　　标签创建后, 就可以为其创建一个分支：<BR><BR>　　cvs rtag -b -r release-1-0 release-1-0-path print<BR><BR>　　-b :创建分支<BR><BR>　　-r release-1-0：-r参数用来标记那些包含指定的标签的文件<BR><BR>　　releas-1-0-patch:分支<BR><BR>　　print: 模块名<BR><BR>　　可以使用tag -b来创建分支，例如在工作目录中：<BR><BR><BR>$ cvs tag -b rel-1-0-patches<BR><BR>　　将会基于当前工作的分支分离一个分支，并将该分支命名为`rel-1-0-patches'。应该理解分支是在cvs的源码仓库中创建的，而不是当前工作目录，基于当前修正创建分支不会将当前工作拷贝自动转换为新的分支，需要手工来实现的。也可以通过使用rtag命令实现不涉及工作目录的分支：<BR><BR><BR>$ cvs rtag -b -r rel-1-0 rel-1-0-patches tc<BR><BR>　　`-r rel-1-0'指示创建的新分支应该以标记`rel-1-0'指定的修订为基础，而不是基于当前的工作主分支。这主要是用来从旧版本中创建一个分支(例如上面的例子)。<BR><BR>　　rtag -b指示创建分支(而不是仅仅创建标记)。应该注意的是`rel-1-0'包含的各个文件的修订号可能是不一样的。<BR><BR>　　所以该命令的效果是为工程tc创建一个新分支-名字为`rel-1-0-patches'，以标记`rel-1-0'为基础。<BR><BR>　　访问分支<BR><BR>　　可以以两种方式访问分支：从源码仓库中检出分支代码，或者将当前的工作拷贝切换为分支。<BR><BR>　　从源码仓库中创检出新分支可以使用命令'checkout -r release-tag'命令：<BR><BR><BR>$ cvs checkout -r rel-1-0-patches tc<BR><BR>　　将当前分支切换到分支命令：<BR><BR><BR>$ cvs update -r rel-1-0-patches tc<BR><BR>　　或者<BR><BR><BR>$ cd tc<BR>$ cvs update -r rel-1-0-patches<BR><BR>　　随后的提交等影响源码仓库的操作都仅仅对分支起作用，而不会影响主分支和其他分支。可以使用status命令来察看当前工作拷贝属于哪个分支。输出中察看'sticky tag'信息，这就是cvs显示当前工作拷贝是在哪个分支上：<BR><BR><BR>$ cvs status -v driver.c backend.c<BR><FONT face=宋体>=============================================================<BR></FONT>File: driver.c Status: Up-to-date<BR>Version: 1.7 Sat Dec 5 18:25:54 1992<BR>RCS Version: 1.7 /u/cvsroot/yoyodyne/tc/driver.c,v<BR>Sticky Tag: rel-1-0-patches (branch: 1.7.2)<BR>Sticky Date: (none)<BR>Sticky Options: (none)<BR>Existing Tags:<BR>rel-1-0-patches (branch: 1.7.2)<BR>rel-1-0 (revision: 1.7)<BR><FONT face=宋体>=============================================================<BR></FONT>File: backend.c Status: Up-to-date<BR>Version: 1.4 Tue Dec 1 14:39:01 1992<BR>RCS Version: 1.4 /u/cvsroot/yoyodyne/tc/backend.c,v<BR>Sticky Tag: rel-1-0-patches (branch: 1.4.2)<BR>Sticky Date: (none)<BR>Sticky Options: (none)<BR>Existing Tags:<BR>rel-1-0-patches (branch: 1.4.2)<BR>rel-1-0 (revision: 1.4)<BR>rel-0-4 (revision: 1.4)<BR><BR>　　不要被每个文件的分支号码不同(`1.7.2'和`1.4.2')所迷惑，分支是由分支标记来决定的这里都是' rel-1-0-patches'。这里的分支号仅仅表示当生成该分支时每个文件的修订号。<BR><BR>　　分支和修订号<BR><BR>　　通常情况下源码库中文件的修订号是以线性增大的:<BR><BR>　　+-----+ +-----+ +-----+ +-----+ +-----+<BR><BR>　　! 1.1 !----! 1.2 !----! 1.3 !----! 1.4 !----! 1.5 !<BR><BR>　　+-----+ +-----+ +-----+ +-----+ +-----+<BR><BR>　　但是CVS并不局限于线性开发，源码树可能出现分支，每个分支是一个对立的开发线。对分支的修改会很容易地被加入到主分支中来。<BR><BR>　　每个分支都拥有一个分支号，由使用"."分隔的奇数个数组成的数串来表示。分支号是通过在产生分支处的修订号后添加一个整数来实现得到的。通过定义分支号使得从同一个分支点分出多个开发分支成为可能。<BR><BR>　　分支的修订号是通过在分支号后顺序添加数字后缀得到的，如下图所示：<BR><BR>　　分支号产生的详细细节其实是不必详细了解的，但是了解其工作原理是必要的：当CVS创建一个分支时，其选择一个最小的偶数作为分支号后缀。因此当希望从修订号6.4分出一个分支时，新分支的分支号为6.4.2。所有以0作为分支号后缀的分支号都被CVS自己保留使用(例如6.4.0)。<BR><BR>　　合并分支<BR><BR>　　分支开发一段时间以后往往需要将修订合并到主分支中来，可以通过`-j branchname'参数实现合并分支。使用该参数将分支和其父分支合并。<BR><BR>　　考虑下面的源码修订树：<BR><BR>　　分支1.2.2被定义为标记R1fix。下面的例子假设模块mod仅仅包含一个文件m.c:<BR><BR>　　$ cvs checkout mod #获取最新的1.4版本<BR><BR>　　$ cvs update -j R1fix m.c # 合并分支的所有更新到主分支<BR><BR>　　# 也就是1.2到1.2.2.2的修改合并到当前工作拷贝<BR><BR>　　$ cvs commit -m "Included R1fix" # 创建修订版本1.5.<BR><BR>　　合并时可能出现冲突情况，如果发生冲突，应该在提交以前手工处理冲突。<BR><BR>　　检出命令(checkout)命令同样支持参数 `-j branchname'，上面的操作可以通过下面的命令实现；<BR><BR><BR>$ cvs checkout -j R1fix mod<BR>$ cvs commit -m "Included R1fix"<BR><BR>　　一个需要注意的问题是"update -j tagname"同样能<img src ="http://www.blogjava.net/nighTuner/aggbug/3878.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nighTuner/" target="_blank">nighTuner</a> 2005-04-28 10:15 <a href="http://www.blogjava.net/nighTuner/articles/3878.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用MRTG检测Linux网络性能</title><link>http://www.blogjava.net/nighTuner/articles/3407.html</link><dc:creator>nighTuner</dc:creator><author>nighTuner</author><pubDate>Mon, 18 Apr 2005 05:09:00 GMT</pubDate><guid>http://www.blogjava.net/nighTuner/articles/3407.html</guid><wfw:comment>http://www.blogjava.net/nighTuner/comments/3407.html</wfw:comment><comments>http://www.blogjava.net/nighTuner/articles/3407.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/nighTuner/comments/commentRss/3407.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/nighTuner/services/trackbacks/3407.html</trackback:ping><description><![CDATA[　随着Linux应用的日益广泛，有大量的网络服务器使用Linux操作系统。为了全面衡量网络运行状况，就需要对网络状态做更细致、更精确的测量。SNMP协议的制订为互联网测量提供了有力支持。MRTG(MultiRouter Traffic Grapher, MRTG)就是基于SNMP的典型网络流量统计分析工具。它耗用的系统资源很小，因此有很多外挂的程序也依附在MRTG下。它通过SNMP协议从设备得到其流量信息，并将流量负载以包含JPEG格式图形的HTML文档的方式显示给用户，以非常直观的形式显示流量负载。 <BR>　　<B>工作原理</B> <BR><BR>　　网络服务器的资料总流量（网卡的资料传送总数）、CPU使用率以及特殊服务（例如Squid的代理服务）等的封包传送率（或者说是流量）是网络管理人员所必须要注意的事项。因为当主机的CPU使用率过高时，系统可能呈现不稳定的状态，这就需要注意是哪一个服务或者谁在尝试窃取我们的资料。因此，网络管理方面，有必要了解我们主机的流量状态，并视流量来加以限制或者是加大带宽。 <BR><BR>　　我们可以从MRTG的主页：http://www.mrtg.org下载MRTG软件。在网站：http://www.stat.ee.ethz.ch/mrtg/可以得到MRTG流量监测图的输出结果。示例如图1所示。 <BR><BR>　　<IMG src="http://developer.ccidnet.com/pub/attachment/2002/10/38318.gif"> <BR><BR>　　图1 MRTG流量监测图的输出结果 <BR><BR>　　MRTG是用Perl写成的，并且使用了zlib、gd以及png等函数（zlib用来压缩图表、gd用来绘制图表）。服务器中已经含有下列的软件：perl(perl-5.0xx以上)、zlib(zlib-1.1.3-xx以上)、gd(gd-1.3.xx以上)、libpng和Apache。 <BR><BR>　　可以用RPM来确认它们： <BR><BR><CCID_NOBR />
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=#000000 border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><CCID_CODE />rpm -qa | grep perl
rpm -qa | grep zlib
rpm -qa | grep gd
rpm -qa | grep libpng</CCID_CODE /></PRE></TD></TR></TBODY></TABLE></CCID_NOBR /><BR><BR>　　另外，由于MRTG以HTTP的格式输出成图表来显示，因此必须要安装好Apache。以下，我们使用了预设的Apache路径，为/usr/local/apache/htdocs这个路径来安装MRTG输出的图表。要注意，如果没有Apache，虽然仍可以强行执行MRTG，但那就无法显示图表了。 <BR><BR>　　<B>安装MRTG</B> <BR><BR>　　由于MRTG是通过SNMP通讯协议来要求资料，因此Linux上需要先安装相应的软件，通常是安装ucd-snmp这套软件。 <BR><BR>　　1．下载ucd-snmp-4.2.1.tar.gz,mrtg-2.9.17.tar.gz。 <BR><BR>　　2．安装ucd-snmp-4.2.1.tar.gz。 <BR><BR><CCID_NOBR />
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=#000000 border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><CCID_CODE />[root@tsai/root]#cd /usr/local/src
[root@tsaisrc]#cp /root/ucd-snmp-4.2.1.tar.gz
[root@tsaisrc]#tar -zxvfucd-snmp-4.2.1.tar.gz
[root@tsaisrc]#cd ucd-snmp-4.2.1
[root@tsaiucd-snmp-4.2.1]# ./configure--prefix=/usr/local/snmp
[root@tsaiucd-snmp-4.2.1]# make
[root@tsaiucd-snmp-4.2.1]# makeinstall</CCID_CODE /></PRE></TD></TR></TBODY></TABLE></CCID_NOBR /><BR><BR>　　3．启动ucd-snmp。 <BR><BR>　　直接在shell下面打上/usr/local/snmp/sbin/snmpd即可，或者直接加在/etc/rc.d/rc.local当中，就可以自动开机启动了。 <BR><BR>　　4．安装。 <BR><BR><CCID_NOBR />
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=#000000 border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><CCID_CODE />[root@tsai/root]# cd/usr/local/src
[root@tsaisrc]# cp/root/mrtg-2.9.17.tar.gz.
[root@tsaisrc]# tar-zxvfmrtg-2.9.17.tar.gz
[root@tsaisrc]# cdmrtg-2.9.17
[root@tsaimrtg-2.9.17]# ./configure--prefix=/usr/local/mrtg-2
&gt;--with-gd=/usr/include
&gt;--with-gd-lib=/usr/lib
&gt;--with-gd-inc=/usr/include
&gt;--with-png=/usr/include
&gt;--with-zlib=/usr/include
[root@tsaimrtg-2.9.17]# make;makeinstall
[root@tsaimrtg-2.9.17]# mkdir/usr/local/apache/htdocs/mrtg(请注意，
这里与你的WWW主页的放置地点有关，请按照你的系统来设定，另外，由于我们
需要设定网络流量、CPU使用率，因此在mrtg中，再建立两个子目录，比较容易管理。)
[root@tsaimrtg-2.9.17]# mkdir/usr/local/apache/htdocs/mrtg/net
[root@tsaimrtg-2.9.17]# cp images/*/usr/local/apache/htdocs/mrtg/net</CCID_CODE /></PRE></TD></TR></TBODY></TABLE></CCID_NOBR /><BR><BR>　　到现在我们就已经正确地安装了MRTG系统。 <BR><BR>　　<B>检测网卡流量</B> <BR><BR>　　要使用MRTG来作图非常简单，只要几个小步骤就可以自动监测流量。首先以MRTG附的程序来制作一个参数项（预设为mrtg.cfg），然后修改一下mrtg.cfg这个参数项，再直接执行三次参数文件，之后用MRTG程序的小软件直接制作成首页，就可以察看图表了。 <BR><BR>　　设定MRTG的方法如下： <BR><BR><CCID_NOBR />
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=#000000 border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><CCID_CODE />[root@tsaimrtg-2.9.17]# cd/usr/local/mrtg-2/bin
[root@tsaibin]#. /cfgmaker --output=/usr/local/apache/htdocs/mrtg/net/mrtg.cfg\<BR>public@vbird.adsldns.org
[root@tsaibin]# vi/usr/local/apache/htdocs/mrtg/net/mrtg.cfg</CCID_CODE /></PRE></TD></TR></TBODY></TABLE></CCID_NOBR /><BR><BR>　　不过由于程序自动设定的mrtg.cfg会有问题，因此，请将下面这三行修改成你自己的样式。 <BR><BR><CCID_NOBR />
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=#000000 border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><CCID_CODE />WorkDir:/usr/local/apache/htdocs/mrtg/net/
Options[_]:growright,bits
Language:GB2312
[root@tsaibin]# ./mrtg /usr/local/apache/htdocs/mrtg/net/mrtg.cfg</CCID_CODE /></PRE></TD></TR></TBODY></TABLE></CCID_NOBR /><BR><BR>　　开始测试你的参数项，要执行三次，就可以正常工作了，不过，若是有问题的话，就需要改mrtg.cfg，再执行直到没有错误发生为止。 <BR><BR><CCID_NOBR />
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=#000000 border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><CCID_CODE />[root@tsaibin]# ./indexmaker\
--output=/usr/local/apache/htdocs/mrtg/net/index.html\
--title=VBird Mrtg\<BR>/usr/local/apache/htdocs/mrtg/net/mrtg.cfg
上面这个程序indexmaker是在制作首页。会自动地输出一个index.html的文件中。</PRE></TD></TR></TBODY></TABLE></CCID_NOBR /><BR><BR>　　注意：在public@vbird. adsldns.org这一行，public是有其意义的（在SNMP这个通讯服务里面的预设搜寻的一个代码）。如果主机的动态DNS名称为your.domain.name，则就一定要写成public@your. domain.name才行。 <BR><BR>　　在设定五分钟检测一次之后，就可以开始检测。然后就可以通过浏览器访问地址http://192.168.0.1/mrtg/，选择适当的接口地址察看流量信息了。如果希望生成类似于http://www.stat.ee.ethz.ch/mrtg/的信息，就需要自己手工编辑一个index.html文档，存放在/var/www/html/mrtg目录下，内容为接口说明以及该接口的日统计信息的图表。 <BR><BR>　　检测CPU负载量 <BR><BR>　　检测CPU负载量时，需要使用到额外的外挂程序，就是sysstat这个程序。 <BR><BR>　　1．下载并安装sysstat-4.0.2-1.i386.rpm： <BR><BR><CCID_NOBR />
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=#000000 border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><CCID_CODE />$ rpm-ivhsysstat-4.0.2-1.i386.rpm</CCID_CODE /></PRE></TD></TR></TBODY></TABLE></CCID_NOBR /><BR><BR>　　2． 编写外挂程序 <BR><BR>　　可以应用安装完sysstat套件后产生的/usr/bin/sar程序进行外挂程序的编写，也可以使用bash写一个监测CPU的小程序。示例如下： <BR><BR><CCID_NOBR />
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=#000000 border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><CCID_CODE />[root@tsaicpu]#vimrtg.cpu
---程序开始----
# !/bin/bash
# 这个程序是用来检测CPU的小外挂程序。
# 1.开始使用sar来监测CPU的user及System负载率
cpuusr=`/usr/bin/sar-u13|grepAverage|awk'{print$3}'`
cpusys=`/usr/bin/sar-u13|grepAverage|awk'{print$5}'`
UPtime=`/usr/bin/uptime|awk'{print$3""$4""$5}'`
#2.列出四个数据（前两个为数字）
echo$cpuusr
echo$cpusys
echo$UPtime
echovbird.adsldns.org（这里写你的主机名称）
----程序结束----
[root@tsaicpu]#chmod755mrtg.cpu（设定成可执行）
[root@tsaicpu]#./mrtg.cpu（测试看可执行否）
2.0
5.4
1day,22:30,
vbird.adsldns.org</CCID_CODE /></PRE></TD></TR></TBODY></TABLE></CCID_NOBR /><BR><BR>　　3．开始设定MRTG参数项，方法如下： <BR><BR><CCID_NOBR />
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=#000000 border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><CCID_CODE />[root@tsaicpu]
# vi mrtg.cfg.cpu
----程序开始----
###GlobalConfigOptions
###Togetbitsinsteadofbytesandgraphs growingtotheright
WorkDir:/usr/local/apache/htdocs/mrtg/cpu/
Language:GB2313
Target[localhost]:`/usr/local/apache/htdocs/mrtg/cpu/mrtg.cpu`
MaxBytes[localhost]:100
Options[localhost]:gauge,nopercent,growright
YLegend[localhost]:CPUloading(%)
ShortLegend[localhost]:%
LegendO[localhost]: CPU使用者负载;
LegendI[localhost]: CPU纯系统负载;
Title[localhost]:CPU?t???v
PageTop[localhost]:&lt;H1&gt;VBird主机CPU负载率&lt;/H1&gt;
&lt;TABLE&gt;
&lt;TR&gt;&lt;TD&gt;System:&lt;/TD&gt;&lt;TD&gt;RedHat7.1inLinuxKernel2.4.9&lt;/TD&gt;&lt;/TR&gt;
&lt;/TABLE&gt;
----程序结束----</CCID_CODE /></PRE></TD></TR></TBODY></TABLE></CCID_NOBR /><BR><BR>　　这之后开始执行参数项，注意，要执行三次以上： <BR><BR><CCID_NOBR />
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=#000000 border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><CCID_CODE />/usr/local/mrtg-2/bin/mrtg/usr/local/apache/htdocs/mrtg/cpu/mrtg.cfg.cpu</CCID_CODE /></PRE></TD></TR></TBODY></TABLE></CCID_NOBR /><BR><BR>　　4．写入到/etc/crontab当中： <BR><BR><CCID_NOBR />
<TABLE cellSpacing=0 borderColorDark=#ffffff cellPadding=2 width=550 align=center borderColorLight=#000000 border=1>
<TBODY>
<TR>
<TD class=code bgColor=#e6e6e6><PRE><CCID_CODE />*/2****root/usr/local/mrtg-2/bin/mrtg/usr/local/apache/htdocs/mrtg/cpu/mrtg.cfg.cpu&gt;/dev/null2&gt;&amp;1</CCID_CODE /></PRE></TD></TR></TBODY></TABLE></CCID_NOBR /><BR><BR>　　这样就OK了，直接将Web指向http://your.host.domain/mrtg/cpu/localhost.html。 <BR><BR>　　再来说说sar。基本上，sar可以用来检测很多的东西，例如：sar－ u 1 5,每一秒钟测一次CPU，共计五次后算平均；sarr 3 3,每三秒看一次实体与虚拟内存用量，三次后算平均。 <BR><img src ="http://www.blogjava.net/nighTuner/aggbug/3407.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nighTuner/" target="_blank">nighTuner</a> 2005-04-18 13:09 <a href="http://www.blogjava.net/nighTuner/articles/3407.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>proc文件系统面面谈</title><link>http://www.blogjava.net/nighTuner/articles/3246.html</link><dc:creator>nighTuner</dc:creator><author>nighTuner</author><pubDate>Wed, 13 Apr 2005 17:45:00 GMT</pubDate><guid>http://www.blogjava.net/nighTuner/articles/3246.html</guid><wfw:comment>http://www.blogjava.net/nighTuner/comments/3246.html</wfw:comment><comments>http://www.blogjava.net/nighTuner/articles/3246.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/nighTuner/comments/commentRss/3246.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/nighTuner/services/trackbacks/3246.html</trackback:ping><description><![CDATA[<P>什么是proc文件系统 </P>
<P>proc文件系统是一个伪文件系统，它只存在内存当中，而不占用外存空间。它以文件系统的方式为访问系统内核数据的操作提供接口。用户和应用程序可以通过proc得到系统的信息，并可以改变内核的某些参数。由于系统的信息，如进程，是动态改变的，所以用户或应用程序读取proc文件时，proc文件系统是动态从系统内核读出所需信息并提交的。它的目录结构如下： </P>
<P>目录名称 目录内容&nbsp; <BR>apm 高级电源管理信息&nbsp; <BR>cmdline 内核命令行&nbsp; <BR>Cpuinfo 关于Cpu信息&nbsp; <BR>Devices 可以用到的设备（块设备/字符设备）&nbsp; <BR>Dma 使用的DMA通道 <BR>Filesystems 支持的文件系统&nbsp; <BR>Interrupts 中断的使用&nbsp; <BR>Ioports I/O端口的使用&nbsp; <BR>Kcore 内核核心印象&nbsp; <BR>Kmsg 内核消息&nbsp; <BR>Ksyms 内核符号表&nbsp; <BR>Loadavg 负载均衡&nbsp; <BR>Locks 内核锁&nbsp; <BR>Meminfo 内存信息&nbsp; <BR>Misc 杂项 <BR>Modules 加载模块列表&nbsp; <BR>Mounts 加载的文件系统&nbsp; <BR>Partitions 系统识别的分区表&nbsp; <BR>Rtc 实时时钟 <BR>Slabinfo Slab池信息 <BR>Stat 全面统计状态表 <BR>Swaps 对换空间的利用情况&nbsp; <BR>Version 内核版本&nbsp; <BR>Uptime 系统正常运行时间&nbsp; </P>
<P>并不是所有这些目录在你的系统中都有，这取决于你的内核配置和装载的模块。另外，在/proc下还有三个很重要的目录：net，scsi和sys。Sys目录是可写的，可以通过它来访问或修改内核的参数（见下一部分），而net和scsi则依赖于内核配置。例如，如果系统不支持scsi，则scsi目录不存在。&nbsp; </P>
<P>除了以上介绍的这些，还有的是一些以数字命名的目录，它们是进程目录。系统中当前运行的每一个进程都有对应的一个目录在/proc下，以进程的PID号为目录名，它们是读取进程信息的接口。而self目录则是读取进程本身的信息接口，是一个link。Proc文件系统的名字就是由之而起。进程目录的结构如下：&nbsp; </P>
<P>目录名称 目录内容&nbsp; <BR>Cmdline 命令行参数&nbsp; <BR>Environ 环境变量值&nbsp; <BR>Fd 一个包含所有文件描述符的目录&nbsp; <BR>Mem 进程的内存被利用情况&nbsp; <BR>Stat 进程状态&nbsp; <BR>Status 进程当前状态，以可读的方式显示出来&nbsp; <BR>Cwd 当前工作目录的链接&nbsp; <BR>Exe 指向该进程的执行命令文件 <BR>Maps 内存映象 <BR>Statm 进程内存状态信息&nbsp; <BR>Root 链接此进程的root目录 </P>
<P>用户如果要查看系统信息，可以用cat命令。例如： </P>
<P># cat /proc/interrupts&nbsp; <BR>CPU0&nbsp; <BR>0: 8728810 XT-PIC timer&nbsp; <BR>1: 895 XT-PIC keyboard&nbsp; <BR>2: 0 XT-PIC cascade&nbsp; <BR>3: 531695 XT-PIC aha152x&nbsp; <BR>4: 2014133 XT-PIC serial&nbsp; <BR>5: 44401 XT-PIC pcnet_cs&nbsp; <BR>8: 2 XT-PIC rtc&nbsp; <BR>11: 8 XT-PIC i82365&nbsp; <BR>12: 182918 XT-PIC Mouse&nbsp; <BR>13: 1 XT-PIC fpu PS/2&nbsp; <BR>14: 1232265 XT-PIC ide0&nbsp; <BR>15: 7 XT-PIC ide1&nbsp; <BR>NMI: 0&nbsp; </P>
<P>用户还可以实现修改内核参数。在/proc文件系统中有一个有趣的目录：/proc/sys。它不仅提供了内核信息，而且可以通过它修改内核参数，来优化你的系统。但是你必须很小心，因为可能会造成系统崩溃。最好是先找一台无关紧要的机子，调试成功后再应用到你的系统上。 </P>
<P>要改变内核的参数，只要用vi编辑或echo参数重定向到文件中即可。下面有一个例子：&nbsp; </P>
<P># cat /proc/sys/fs/file-max&nbsp; <BR>4096&nbsp; <BR># echo 8192 &gt; /proc/sys/fs/file-max&nbsp; <BR># cat /proc/sys/fs/file-max&nbsp; <BR>8192&nbsp; </P>
<P>如果你优化了参数，则可以把它们写成添加到文件rc.local中，使它在系统启动时自动完成修改。 </P>
<P>/proc文件系统中网络参数 </P>
<P>在/proc/sys/net/ipv4/目录下，包含的是和tcp/ip协议相关的各种参数，下面我们就对这些网络参数加以详细的说明。 </P>
<P>ip_forward 参数类型：BOOLEAN <BR>0 - 关闭(默认值) <BR>not 0 - 打开ip转发 </P>
<P>在网络本地接口之间转发数据报。该参数非常特殊，对该参数的修改将导致其它所有相关配置参数恢复其默认值(对于主机参阅RFC1122，对于路由器参见RFC1812) </P>
<P>ip_default_ttl 参数类型：INTEGER <BR>默认值为 64 。表示IP数据报的Time To Live值。 </P>
<P>ip_no_pmtu_disc 参数类型：BOOLEAN <BR>关闭路径MTU探测，默认值为FALSE </P>
<P>ipfrag_high_thresh 参数类型：整型 <BR>用来组装分段的IP包的最大内存量。当ipfrag_high_thresh数量的内存被分配来用来组装IP包，则IP分片处理器将丢弃数据报直到ipfrag_low_thresh数量的内存被用来组装IP包。 </P>
<P>ipfrag_low_thresh 参数类型：整型 <BR>参见ipfrag_high_thresh。 </P>
<P>ipfrag_time 参数类型：整型 <BR>保存一个IP分片在内存中的时间。 </P>
<P>inet_peer_threshold 参数类型：整型 <BR>INET对端存储器某个合适值，当超过该阀值条目将被丢弃。该阀值同样决定生存时间以及废物收集通过的时间间隔。条目越多﹐存活期越低﹐GC 间隔越短 </P>
<P>inet_peer_minttl 参数类型：整型 <BR>条目的最低存活期。在重组端必须要有足够的碎片(fragment)存活期。这个最低存活期必须保证缓冲池容积是否少于 inet_peer_threshold。该值以 jiffies为单位测量。 </P>
<P>inet_peer_maxttl 参数类型：整型 <BR>条目的最大存活期。在此期限到达之后﹐如果缓冲池没有耗尽压力的话(例如﹐缓冲池中的条目数目非常少)﹐不使用的条目将会超时。该值以 jiffies为单位测量。 </P>
<P>inet_peer_gc_mintime 参数类型：整型 <BR>废物收集(GC)通过的最短间隔。这个间隔会影响到缓冲池中内存的高压力。 该值以 jiffies为单位测量。 </P>
<P>inet_peer_gc_maxtime 参数类型：整型 <BR>废物收集(GC)通过的最大间隔，这个间隔会影响到缓冲池中内存的低压力。 该值以 jiffies为单位测量。 </P>
<P>tcp_syn_retries 参数类型：整型 <BR>对于一个新建连接，内核要发送多少个 SYN 连接请求才决定放弃。不应该大于255，默认值是5，对应于180秒左右。 </P>
<P>tcp_synack_retries 参数类型：整型 <BR>对于远端的连接请求SYN，内核会发送SYN ＋ ACK数据报，以确认收到上一个 SYN连接请求包。这是所谓的三次握手( threeway handshake)机制的第二个步骤。这里决定内核在放弃连接之前所送出的 SYN+ACK 数目。&nbsp; </P>
<P>tcp_keepalive_time 参数类型：整型 <BR>当keepalive打开的情况下，TCP发送keepalive消息的频率，默认值是2个小时。 </P>
<P>tcp_keepalive_probes 参数类型：整型 <BR>TCP发送keepalive探测以确定该连接已经断开的次数，默认值是9。 </P>
<P>tcp_keepalive_interval 参数类型：整型 <BR>探测消息发送的频率，乘以tcp_keepalive_probes就得到对于从开始探测以来没有响应的连接杀除的时间。默认值为75秒，也就是没有活动的连接将在大约11分钟以后将被丢弃。 </P>
<P>tcp_retries1 参数类型：整型 <BR>当出现可疑情况而必须向网络层报告这个可疑状况之前﹐需要进行多少次重试。最低的 RFC 数值是 3 ﹐这也是默认值﹐根据RTO的值大约在3秒 - 8分钟之间。 </P>
<P>tcp_retries2 参数类型：整型 <BR>在丢弃激活的TCP连接之前﹐需要进行多少次重试。RFC1122规定，该值必须大于100秒。默认值为15，根据RTO的值来决定，相当于13-30分钟， </P>
<P>tcp_orphan_retries 参数类型：整型 <BR>在近端丢弃TCP连接之前﹐要进行多少次重试。默认值是 7 个﹐相当于 50秒 - 16分钟﹐视 RTO 而定。如果您的系统是负载很大的web服务器﹐那么也许需要降低该值﹐这类 sockets 可能会耗费大量的资源。另外参的考 tcp_max_orphans 。 </P>
<P>tcp_fin_timeout 参数类型：整型 <BR>对于本端断开的socket连接，TCP保持在FIN-WAIT-2状态的时间。对方可能会断开连接或一直不结束连接或不可预料的进程死亡。默认值为 60 秒。过去在2.2版本的内核中是 180 秒。您可以设置该值﹐但需要注意﹐如果您的机器为负载很重的web服务器﹐您可能要冒内存被大量无效数据报填满的风险﹐FIN-WAIT-2 sockets 的危险性低于 FIN-WAIT-1 ﹐因为它们最多只吃 1.5K 的内存﹐但是它们存在时间更长。另外参考 tcp_max_orphans。&nbsp; </P>
<P>tcp_max_tw_buckets 参数类型：整型 <BR>系统在同时所处理的最大timewait sockets 数目。如果超过此数的话﹐time-wait socket 会被立即砍除并且显示警告信息。之所以要设定这个限制﹐纯粹为了抵御那些简单的 DoS 攻击﹐千万不要人为的降低这个限制﹐不过﹐如果网络条件需要比默认值更多﹐则可以提高它(或许还要增加内存)。&nbsp; </P>
<P>tcp_tw_recycle 参数类型：布尔 <BR>打开快速 TIME-WAIT sockets 回收。默认值是1。除非得到技术专家的建议或要求﹐请不要随意修改这个值。&nbsp; </P>
<P>tcp_max_orphans 参数类型：整型 <BR>系统所能处理不属于任何进程的TCP sockets最大数量。假如超过这个数量﹐那么不属于任何进程的连接会被立即reset，并同时显示警告信息。之所以要设定这个限制﹐纯粹为了抵御那些简单的 DoS 攻击﹐千万不要依赖这个或是人为的降低这个限制 </P>
<P>tcp_abort_on_overflow 参数类型：布尔 <BR>当守护进程太忙而不能接受新的连接，就象对方发送reset消息，默认值是false。这意味着当溢出的原因是因为一个偶然的猝发，那么连接将恢复状态。只有在你确信守护进程真的不能完成连接请求时才打开该选项，该选项会影响客户的使用。 </P>
<P>tcp_syncookies 参数类型：整型 <BR>只有在内核编译时选择了CONFIG_SYNCOOKIES时才会发生作用。当出现syn等候队列出现溢出时象对方发送syncookies。目的是为了防止syn flood攻击。默认值是false。 </P>
<P>注意：该选项千万不能用于那些没有收到攻击的高负载服务器，如果在日志中出现synflood消息，但是调查发现没有收到synflood攻击，而是合法用户的连接负载过高的原因，你应该调整其它参数来提高服务器性能。参考: tcp_max_syn_backlog, tcp_synack_retries, tcp_abort_on_overflow. </P>
<P>syncookie严重的违背TCP协议，不允许使用TCP扩展，可能对某些服务导致严重的性能影响(如SMTP转发)。 </P>
<P>tcp_stdurg 参数类型：整型 <BR>使用 TCP urg pointer 字段中的主机请求解释功能。大部份的主机都使用老旧的 BSD解释，因此如果您在 Linux 打开它﹐或会导致不能和它们正确沟通。默认值为为﹕FALSE&nbsp; </P>
<P>tcp_max_syn_backlog 参数类型：整型 <BR>对于那些依然还未获得客户端确认的连接请求﹐需要保存在队列中最大数目。对于超过 128Mb 内存的系统﹐默认值是 1024 ﹐低于 128Mb 的则为 128。如果服务器经常出现过载﹐可以尝试增加这个数字。警告﹗假如您将此值设为大于 1024﹐最好修改 include/net/tcp.h 里面的 TCP_SYNQ_HSIZE ﹐以保持 TCP_SYNQ_HSIZE*16&lt;=tcp_max_syn_backlog ﹐并且编进核心之内。&nbsp; </P>
<P>tcp_window_scaling 参数类型：布尔 <BR>正常来说，TCP/IP 可以接受最大到65535字节的 windows。对于宽带网络，该值可能是不够的，通过调整该参数有助于提高宽带服务器性能。 </P>
<P>tcp_timestamps 参数类型：布尔 <BR>Timestamps 用在其它一些东西中﹐可以防范那些伪造的 sequence 号码。一条1G的宽带线路或许会重遇到带 out-of-line数值的旧sequence 号码(假如它是由于上次产生的)。Timestamp 会让它知道这是个 '旧封包'。&nbsp; </P>
<P>tcp_sack 参数类型：布尔 <BR>使用 Selective ACK﹐它可以用来查找特定的遗失的数据报--- 因此有助于快速恢复状态。 </P>
<P>tcp_fack 参数类型：布尔 <BR>打开FACK拥塞避免和快速重传功能。 </P>
<P>tcp_dsack 参数类型：布尔 <BR>允许TCP发送"两个完全相同"的SACK。 </P>
<P>tcp_ecn 参数类型：布尔 <BR>打开TCP的直接拥塞通告功能。 </P>
<P>tcp_reordering 参数类型：整型 <BR>TCP流中重排序的数据报最大数量默认值是 3 。 </P>
<P>tcp_retrans_collapse 参数类型：布尔 <BR>对于某些有bug的打印机提供针对其bug的兼容性。 </P>
<P>tcp_wmem - 三个整数的向量： min, default, max <BR>min：为TCP socket预留用于发送缓冲的内存最小值。每个tcp socket都可以在建议以后都可以使用它。默认值为4K。 </P>
<P>default：为TCP socket预留用于发送缓冲的内存数量，默认情况下该值会影响其它协议使用的net.core.wmem_default 值，一般要低于net.core.wmem_default的值。默认值为16K。 </P>
<P>max: 用于TCP socket发送缓冲的内存最大值。该值不会影响net.core.wmem_max，今天选择参数SO_SNDBUF则不受该值影响。默认值为128K。 </P>
<P>tcp_rmem - 三个整数的向量： min, default, max <BR>min：为TCP socket预留用于接收缓冲的内存数量，即使在内存出现紧张情况下tcp socket都至少会有这么多数量的内存用于接收缓冲，默认值为8K。 </P>
<P>default：为TCP socket预留用于接收缓冲的内存数量，默认情况下该值影响其它协议使用的 net.core.wmem_default 值。该值决定了在tcp_adv_win_scale、tcp_app_win和tcp_app_win:0是默认值情况下，tcp 窗口大小为65535。 </P>
<P>max：用于TCP socket接收缓冲的内存最大值。该值不会影响 net.core.wmem_max，今天选择参数 SO_SNDBUF则不受该值影响。默认值为 128K。默认值为87380*2 bytes。 </P>
<P>tcp_mem - 三个整数的向量： low, pressure, high <BR>low：当TCP使用了低于该值的内存页面数时，TCP不会考虑释放内存。 </P>
<P>pressure：当TCP使用了超过该值的内存页面数量时，TCP试图稳定其内存使用，进入pressure模式，当内存消耗低于low值时则退出pressure状态。 </P>
<P>high：允许所有tcp sockets用于排队缓冲数据报的页面量。 </P>
<P>一般情况下这些值是在系统启动时根据系统内存数量计算得到的。 </P>
<P>tcp_app_win - 整数 </P>
<P>保留max(window/2^tcp_app_win, mss)数量的窗口由于应用缓冲。当为0时表示不需要缓冲。默认值是31。 </P>
<P>tcp_adv_win_scale - 整数 <BR>计算缓冲开销bytes/2^tcp_adv_win_scale(如果tcp_adv_win_scale &gt; 0)或者bytes-bytes/2^(-tcp_adv_win_scale)(如果tcp_adv_win_scale &lt;= 0），默认值为2。 </P>
<P>ip_local_port_range - 两个整数 <BR>定于TCP和UDP使用的本地端口范围，第一个数是开始，第二个数是最后端口号，默认值依赖于系统中可用的内存数： <BR>&gt; 128Mb 32768-61000 <BR>&lt; 128Mb 1024-4999 or even less. <BR>该值决定了活动连接的数量，也就是系统可以并发的连接数 </P>
<P>icmp_echo_ignore_all - 布尔类型 <BR>icmp_echo_ignore_broadcasts - 布尔类型 <BR>如果任何一个设置为true(&gt;0)则系统将忽略所有发送给自己的ICMP ECHO请求或那些广播地址的请求。 </P>
<P>icmp_destunreach_rate - 整数 <BR>icmp_paramprob_rate - 整数 <BR>icmp_timeexceed_rate - 整数 <BR>icmp_echoreply_rate - 整数(not enabled per default) <BR>限制发向特定目标的ICMP数据报的最大速率。0表示没有任何限制，否则表示jiffies数据单位中允许发送的个数。 </P>
<P>icmp_ignore_bogus_error_responses - 布尔类型 <BR>某些路由器违背RFC1122标准，其对广播帧发送伪造的响应来应答。这种违背行为通常会被以告警的方式记录在系统日志中。如果该选项设置为True，内核不会记录这种警告信息。默认值为False。 </P>
<P>(1) Jiffie: 内核使用的内部时间单位，在i386系统上大小为1/100s，在Alpha中为1/1024S。在/usr/include/asm/param.h中的HZ定义有特定系统的值。 </P>
<P>conf/interface/*:&nbsp; <BR>conf/all/*是特定的，用来修改所有接口的设置，is special and changes the settings for all interfaces. <BR>Change special settings per interface. </P>
<P>log_martians - 布尔类型 <BR>记录带有不允许的地址的数据报到内核日志中。 </P>
<P>accept_redirects - 布尔类型 <BR>收发接收ICMP重定向消息。对于主机来说默认为True，对于用作路由器时默认值为False。 </P>
<P>forwarding - 布尔类型 <BR>在该接口打开转发功能 </P>
<P>mc_forwarding - 布尔类型 <BR>是否进行多播路由。只有内核编译有CONFIG_MROUTE并且有路由服务程序在运行该参数才有效。 </P>
<P>proxy_arp - 布尔类型 <BR>打开proxy arp功能。 </P>
<P>shared_media - 布尔类型 <BR>发送(路由器)或接收(主机) RFC1620 共享媒体重定向。覆盖ip_secure_redirects的值。默认为True。 </P>
<P>secure_redirects - 布尔类型 <BR>仅仅接收发给默认网关列表中网关的ICMP重定向消息，默认值是TRUE。 </P>
<P>send_redirects - 布尔类型 <BR>如果是router，发送重定向消息，默认值是TRUE </P>
<P>bootp_relay - 布尔类型 <BR>接收源地址为0.b.c.d，目的地址不是本机的数据报。用来支持BOOTP转发服务进程，该进程将捕获并转发该包。默认为False，目前还没有实现。 </P>
<P>accept_source_route - 布尔类型 <BR>接收带有SRR选项的数据报。对于主机来说默认为False，对于用作路由器时默认值为True。 </P>
<P>rp_filter 参数类型 <BR>1 - 通过反向路径回溯进行源地址验证(在RFC1812中定义)。对于单穴主机和stub网络路由器推荐使用该选项。 <BR>0 - 不通过反向路径回溯进行源地址验证。 <BR>默认值为0。某些发布在启动时自动将其打开。</P><img src ="http://www.blogjava.net/nighTuner/aggbug/3246.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nighTuner/" target="_blank">nighTuner</a> 2005-04-14 01:45 <a href="http://www.blogjava.net/nighTuner/articles/3246.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何远程安装Linux</title><link>http://www.blogjava.net/nighTuner/articles/3245.html</link><dc:creator>nighTuner</dc:creator><author>nighTuner</author><pubDate>Wed, 13 Apr 2005 17:41:00 GMT</pubDate><guid>http://www.blogjava.net/nighTuner/articles/3245.html</guid><wfw:comment>http://www.blogjava.net/nighTuner/comments/3245.html</wfw:comment><comments>http://www.blogjava.net/nighTuner/articles/3245.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/nighTuner/comments/commentRss/3245.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/nighTuner/services/trackbacks/3245.html</trackback:ping><description><![CDATA[<P>一般情况下，我们都是利用软驱或光驱引导Linux后，再通过本地的光驱安装Linux。但是，这种安装方法在以下的几种情况下就不能适用：</P>
<P>无软驱和光驱：很多公司为了节省成本，计算机一般都不带光驱或软驱，这样就无法通过本地安装Linux； <BR>非标准的软驱和光驱：虽然笔记本都会配置光驱，但是并不一定都是标准的IDE设备，有些是通过USB接口，有些是通过1394接口（例如Samsung的Q10）。在Linux安装时所引导的Linux内核一般都不会带这些接口的驱动，所以也无法通过本地安装Linux； <BR>另外，在一些场合，如机房中，有大量的计算机需要同时安装Linux，如果通过光驱的方式一个个安装，不仅效率低，也不利于维护。 <BR>笔者在工作过程中，就遇到过第二种情况。一台Samsung的Q10笔记本需要安装Redhat Linux 8.0，但是通过光驱引导后发现，安装程序无法访问光盘。针对这个问题，笔者经过查阅资料和摸索，找到了在Q10上安装Linux的方法。在下面的讨论中，如不做特别声明，都将以Q10为例，介绍如何通过PXE Bootrom来远程安装Linux。</P>
<P>2． 基本原理</P>
<P>1） 什么是PXE</P>
<P>PXE(Pre-boot Execution Environment)是由Intel设计的协议，它可以使计算机通过网络启动。协议分为client和server两端，PXE client在网卡的ROM中，当计算机引导时，BIOS把PXE client调入内存执行，并显示出命令菜单，经用户选择后，PXE client将放置在远端的操作系统通过网络下载到本地运行。</P>
<P>PXE协议的成功运行需要解决以下两个问题：</P>
<P>既然是通过网络传输，那么计算机在启动时，它的IP地址由谁来配置； <BR>通过什么协议下载Linux内核和根文件系统 <BR>对于第一个问题，可以通过DHCP Server解决，由DHCP server来给PXE client分配一个IP地址，DHCP Server是用来给DHCP Client动态分配IP地址的协议，不过由于这里是给PXE Client分配IP地址，所以在配置DHCP Server时，需要增加相应的PXE特有配置。</P>
<P>至于第二个问题，在PXE client所在的ROM中，已经存在了TFTP Client。PXE Client使用TFTP Client，通过TFTP协议到TFTP Server上下载所需的文件。</P>
<P>这样，PXE协议运行的条件就具备了，下面我们就来看看PXE协议的工作过程。</P>
<P>2） 工作过程</P>
<P>&nbsp;</P>
<P>&nbsp;</P>
<P>在上图中，PXE client是需要安装Linux的计算机，TFTP Server和DHCP Server运行在另外一台Linux Server上。Bootstrap文件、配置文件、Linux内核以及Linux根文件系统都放置在Linux Server上TFTP服务器的根目录下。</P>
<P>PXE client在工作过程中，需要三个二进制文件：bootstrap、Linux 内核和Linux根文件系统。Bootstrap文件是可执行程序，它向用户提供简单的控制界面，并根据用户的选择，下载合适的Linux内核以及Linux根文件系统。</P>
<P>3． 步骤</P>
<P>有了前面的背景知识，接下来就可以正式操作了，下面按照顺序给出了操作步骤：</P>
<P>1） 配置DHCP Server</P>
<P>选用ISC dhcp-3.0，DHCP Server的配置文件是/etc/dhcpd.conf，配置文件的内容如下：</P>
<P><BR>option space PXE;<BR>option PXE.mtftp-ip code 1 = ip-address; <BR>option PXE.mtftp-cport code 2 = unsigned integer 16;<BR>option PXE.mtftp-sport code 3 = unsigned integer 16;<BR>option PXE.mtftp-tmout code 4 = unsigned integer 8;<BR>option PXE.mtftp-delay code 5 = unsigned integer 8;<BR>option PXE.discovery-control code 6 = unsigned integer 8;<BR>option PXE.discovery-mcast-addr code 7 = ip-address;</P>
<P>class "pxeclients" {<BR>match if substring (option vendor-class-identifier, 0, 9) = "PXEClient";<BR>option vendor-class-identifier "PXEClient";<BR>vendor-option-space PXE;</P>
<P># At least one of the vendor-specific PXE options must be set in<BR># order for the client boot ROMs to realize that we are a PXE-compliant<BR># server. We set the MCAST IP address to 0.0.0.0 to tell the boot ROM<BR># that we can't provide multicast TFTP (address 0.0.0.0 means no<BR># address).</P>
<P>option PXE.mtftp-ip 0.0.0.0;</P>
<P># This is the name of the file the boot ROMs should download.<BR>filename "pxelinux.0";</P>
<P># This is the name of the server they should get it from.<BR>next-server 192.168.0.1;<BR>}<BR>ddns-update-style interim;<BR>ignore client-updates;<BR>default-lease-time 1200;<BR>max-lease-time 9200;<BR>option subnet-mask 255.255.255.0;<BR>option broadcast-address 192.168.0.255;<BR>option routers 192.168.0.254;<BR>option domain-name-servers 192.168.0.1,192.168.0.2;<BR>option domain-name "mydomain.org";<BR>subnet 192.168.0.0 netmask 255.255.255.0 {<BR>range 192.168.0.10 192.168.0.100;<BR>} <BR>host q10 {<BR>hardware ethernet 00:00:F0:6B:38:5B;<BR>fixed-address 192.168.0.22;<BR>}</P>
<P>&nbsp;</P>
<P><BR>dhcpd.conf配置文件中几个关键部分说明如下：host q10{…}定义了笔记本Q10网卡的MAC地址与IP地址的对应关系，表明DHCP Server为Q10分配一个固定的IP：192.168.0.22；filename ""指定bootstrap的文件名；netx-server指定TFTP Server的地址。其它的配置请读者参考DHCP Server的手册。</P>
<P>2） 配置TFTP server</P>
<P>选用tftp-hpa，TFTP Server的配置文件是/etc/xinetd.d/tftp，配置文件的内容如下：</P>
<P><BR>service tftp<BR>{<BR>socket_type = dgram<BR>protocol = udp<BR>wait = yes<BR>user = root<BR>server = /usr/sbin/in.tftpd<BR>server_args = -u nobody -s /tftpboot<BR>disable = no<BR>per_source = 11<BR>cps = 100 2<BR>}</P>
<P>&nbsp;</P>
<P><BR>这里制定了/tftpboot为TFTP Server的根目录位置。</P>
<P>3） 配置bootstrap</P>
<P>bootstrap文件在dhcpd.conf中被指定为pxelinux.0文件，放置在/tftpboot。Linux内核以及Linux根文件系统也放置在/tftpboot。pxelinux.0在执行过程中，要读配置文件，所有的配置文件都放在/tftpboot/pxelinux.cfg/目录下。由于PXElinux具有为不同的PXE Client提供不同的Linux内核以及根文件系统的功能，所以要通过不同的配置文件名来区分出不同的PXE Client的需求。比如一个PXE Client由DHCP Server分配的IP地址为192.168.0.22，那么相对应的配置文件名为/tftpboot/pxelinux.cfg/C0A80016（注：C0A80016为IP地址192.168.0.22的十六进制表示）。如果找不到，就按照顺序C0A80016-&gt; C0A8001-&gt; C0A800-&gt; C0A80-&gt; C0A8-&gt; C0A-&gt; C0-&gt; C-&gt;default查找配置文件。</P>
<P>/tftpboot/pxelinux.cft/C0A80001配置文件的具体内容如下：</P>
<P>DEFAULT install<BR>PROMPT 1<BR>LABEL install<BR>KERNEL vmlinuz<BR>APPEND initrd=initrd.img devfs=nomount ramdisk_size=16384</P>
<P>此配置文件指定了Linux内核以及根文件系统的名称，并给内核传递了一些参数，其中ramdisk_size参数要非常注意，它指定Linux内核启动后建立ramdisk的大小，如果设置太小，Linux的安装过程就可能无法进行。</P>
<P>4） 制作Linux内核/根文件系统</P>
<P>因为需要通过网络安装，所有选择Redhat Linux 8.0安装盘（disk #1）中E:\images\bootnet.img（光驱的盘符为E:）。bootnet.img包括Linux内核、Linux根文件系统（有安装程序在内）。用bootnet.img制作一张引导软盘，方法在DOS命令行运行E:\dosutils\rawrite E:\images\bootnet.img，根据提示制作。制作完毕后，将引导软盘中的vmlinuz（Linux内核）和initrd.img（Linux根文件系统）拷贝到Linux Server的/tftpboot下。</P>
<P>5） 启动DHCP Server/TFTP Server</P>
<P>在Linux Server上，运行service dhcpd start和service xinetd restart。</P>
<P>6） 启动Q10</P>
<P>Q10加电后，在出现Samsung公司徽标时，在左下角会提示用户按F12进入网络引导。按F12后，Q10进入网络引导过程。首先通过DHCP Server获得了IP地址，然后下载并执行bootstrap文件pxelinux.0；在执行中，读入配置文件/tftpboot/pxelinux.cfg/C0A80016。此时屏幕上出现boot:，敲入install，就进入了Redhat Linux 8.0的网络安装界面，一切OK!</P><img src ="http://www.blogjava.net/nighTuner/aggbug/3245.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nighTuner/" target="_blank">nighTuner</a> 2005-04-14 01:41 <a href="http://www.blogjava.net/nighTuner/articles/3245.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>squid 配置详解+认证</title><link>http://www.blogjava.net/nighTuner/articles/3244.html</link><dc:creator>nighTuner</dc:creator><author>nighTuner</author><pubDate>Wed, 13 Apr 2005 17:37:00 GMT</pubDate><guid>http://www.blogjava.net/nighTuner/articles/3244.html</guid><wfw:comment>http://www.blogjava.net/nighTuner/comments/3244.html</wfw:comment><comments>http://www.blogjava.net/nighTuner/articles/3244.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/nighTuner/comments/commentRss/3244.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/nighTuner/services/trackbacks/3244.html</trackback:ping><description><![CDATA[<P>　　在此，我们要配置一个只对内部网络提供代理服务的Proxy Server。它将用户分为高级用户和普通用户两种，对高级用户采用网卡物理地址识别的方法，普通用户则需要输入用户名和口令才能正常使用。高级用户没有访问时间和文件类型的限制，而普通用户只在上班时可以访问以及一些其它的限制。 </P>
<P>　　安装 </P>
<P>　　可以从Squid站点<A href="http://www.squid-cache.org">www.squid-cache.org</A>获取该软件的源代...的发行版，如Red Hat提供的RPM包。 </P>
<P>　　RPM方式安装很简单，命令如下： </P>
<P>　　$ rpm -ivh Squid-2.x.STALBx.i386.rpm </P>
<P><BR>　　不过笔者认为，即便是系统中已经默认安装了Squid，也应当先删掉然后安装最新的源代码包。因为开源软件会不断修正问题、提供更新的功能，使用最新版本可以保证最高的性能及安全，而且源代码方式可以完全定制系统。不过STABLE稳定版、DEVEL版通常是提供给开发人员测试程序的，假定下载了最新的稳定版squid-2.5.STABLE2.tar.gz，用以下命令解开压缩包： </P>
<P>$ tar xvfz squid-2.5.STABLE.tar.gz </P>
<P><BR>　　用bz2方式压缩的包可能体积更小，相应的命令是： </P>
<P>$ tar xvfj squid-2.5.STABLE.tar.bz2 </P>
<P><BR>　　然后，进入相应目录对源代码进行配置和编译，命令如下： </P>
<P>$ cd squid-2.5.STABLE2 </P>
<P><BR>　　配置命令configure有很多选项，如果不清楚可先用“-help”查看。通常情况下，用到的选项有以下几个： </P>
<P>--prefix=/web/squid <BR>#指定Squid的安装位置，如果只指定这一选项，那么该目录下会有bin、sbin、man、conf等目录，而主要的配置文件此时在conf子目录中。为便于管理，最好用参数--sysconfdir=/etc把这个文件位置配置为/etc。 <BR>--enable-storeio=ufs,null <BR>#使用的文件系统通常是默认的ufs，不过如果想要做一个不缓存任何文件的代理服 <BR>务器，就需要加上null文件系统。 <BR>--enable-arp-acl <BR>#这样可以在规则设置中直接通过客户端的MAC地址进行管理，防止客户使用IP欺骗。 <BR>--enable-err-languages="Simplify_Chinese" <BR>--enable-default-err-languages="Simplify_Chinese" <BR>#上面两个选项告诉Squid编入并使用简体中文错误信息。 <BR>--enable-linux-netfilter <BR>#允许使用Linux的透明代理功能。 <BR>--enable-underscore <BR>#允许解析的URL中出现下划线，因为默认情况下Squid会认为带下划线的URL是 <BR>非法的，并拒绝访问该地址。 </P>
<P><BR>　　整个配置编译过程如下： </P>
<P>./configure --prefix=/var/squid <BR>--sysconfdir=/etc <BR>--enable-arp-acl <BR>--enable-linux-netfilter <BR>--enable-pthreads <BR>--enable-err-language="Simplify_Chinese" <BR>--enable-storeio=ufs,null <BR>--enable-default-err-language="Simplify_Chinese" <BR>--enable-auth="basic" <BR>--enable-baisc-auth-helpers="NCSA" <BR>--enable-underscore </P>
<P><BR>　　其中一些选项有特殊作用，将在下面介绍它们。 </P>
<P>　　最后执行make和make install两条命令，将源代码编译为可执行文件，并拷贝到指定位置。 </P>
<P>　　基本配置 </P>
<P>　　安装完成后，接下来要对Squid的运行进行配置（不是前面安装时的配置）。所有项目都在squid.conf中完成。Squid自带的squid.conf包括非常详尽的说明，相当于一篇用户手册，对配置有任何疑问都可以参照解决。 </P>
<P>　　在这个例子中，代理服务器同时也是网关，内部网络接口eth0的IP地址为192.168.0.1，外部网络接口eth1的IP地址为202.103.x.x。下面是一个基本的代理所需要配置选项： </P>
<P>　　http_port 192.168.0.1:3128 </P>
<P><BR>　　默认端口是3128，当然也可以是任何其它端口，只要不与其它服务发生冲突即可。为了安全起见，在前面加上IP地址，Squid就不会监听外部的网络接口。 </P>
<P>　　下面的配置选项是服务器管理者的电子邮件，当错误发生时，该地址会显示在错误页面上，便于用户联系： </P>
<P>cache_mgr <A href="mailto:start@soocol.com">start@soocol.com</A> </P>
<P><BR>　　以下这些参数告诉Squid缓存的文件系统、位置和缓存策略： </P>
<P>cache_dir ufs /var/squid <BR>cache_mem 32MB <BR>cache_swap_low 90 <BR>cache_swap_high 95 </P>
<P><BR>　　在这里，Squid会将/var/squid目录作为保存缓存数据的目录，每次处理的缓存大小是32兆字节，当缓存空间使用达到95%时，新的内容将取代旧的而不直接添加到目录中，直到空间又下降到90%才停止这一活动。如果不想Squid缓存任何文件，如某些存储空间有限的专有系统，可以使用null文件系统（这样不需要那些缓存策略）： </P>
<P>cache_dir null /tmp </P>
<P><BR>　　下面的几个关于缓存的策略配置中，较主要的是第一行，即用户的访问记录，可以通过分析它来了解所有用户访问的详尽地址： </P>
<P>cache_access_log /var/squid/access.log <BR>cache_log /var/squid/cache.log <BR>cache_store_log /var/squid/store.log </P>
<P><BR>　　下面这行配置是在较新版本中出现的参数，告诉Squid在错误页面中显示的服务器名称： </P>
<P>visible_hostname No1.proxy </P>
<P><BR>　　以下配置告诉Squid如何处理用户，对每个请求的IP地址作为单独地址处理： </P>
<P>client_mask 255.255.255.255 </P>
<P><BR>　　如果是普通代理服务器，以上的配置已经足够。但是很多Squid都被用来做透明代理。所谓透明代理，就是客户端不知道有代理服务器的存在，当然也不需要进行任何与代理有关的设置，从而大大方便了系统管理员。相关的选项有以下几个： </P>
<P>httpd_accel_host virtual <BR>httpd_accel_port 80 <BR>httpd_accel_with_proxy on <BR>httpd_accel_user_host_header on </P>
<P><BR>　　在Linux上，可以用iptables/ipchains直接将对Web端口80的请求直接转发到Squid端口3128，由Squid接手，而用户浏览器仍然认为它访问的是对方的80端口。例如以下这条命令： </P>
<P>iptables -t nat -A PREROUTING -s 192.168.0.200/32 -p tcp --dport 80 -j REDIRECT 3128 </P>
<P><BR>　　就是将192.168.0.200的所有针对80端口的访问重定向到3128端口。 </P>
<P>　　所有设置完成后，关键且重要的任务是访问控制。Squid支持的管理方式很多，使用起来也非常简单（这也是有人宁愿使用不做任何缓存的Squid，也不愿意单独使用iptables的原因）。Squid可以通过IP地址、主机名、MAC地址、用户/密码认证等识别用户，也可以通过域名、域后缀、文件类型、IP地址、端口、URL匹配等控制用户的访问，还可以使用时间区间对用户进行管理，所以访问控制是Squid配置中的重点。Squid用ACL（Access Control List，访问控制列表）对访问类型进行划分，用http_access deny 或allow进行控制。根据需求首先定义两组用户advance和normal，还有代表所有未指明的用户组all及不允许上网的baduser，配置代码如下： </P>
<P>acl advance 192.168.0.2-192.168.0.10/32 <BR>acl normal src 192.168.0.11-192.168.0.200/32 <BR>acl baduser src 192.168.0.100/32 <BR>acl baddst dst <A href="http://www.soocol.com">www.soocol.com</A> <BR>acl all src 0.0.0.0/0 </P>
<P>http_access deny baduser <BR>http_access allow advance <BR>http_access allow normal </P>
<P><BR>　　可以看出，ACL的基本格式如下： </P>
<P>　　acl 列表名称 控制方式 控制目标 </P>
<P><BR>　　比如acl all src 0.0.0.0/0，其名称是all，控制方式是src源IP地址，控制目标是0.0.0.0/0的IP地址，即所有未定义的用户。出于安全考虑，总是在最后禁止这个列表。 </P>
<P>　　下面这个列表代表高级用户，包括IP地址从192.168.0.2到192.168.0.10的所有计算机： </P>
<P>acl advance 192.168.0.2-192.168.0.20/32 </P>
<P><BR>　　下面这个baduser列表只包含一台计算机，其IP地址是192.168.0.100： </P>
<P>acl baduser 192.168.0.100/32 </P>
<P><BR>　　ACL写完后，接下来要对它们分别进行管理，代码如下： </P>
<P>http_access deny baduser <BR>http_access allow advance <BR>http_access allow normal </P>
<P><BR>　　上面几行代码告诉Squid不允许baduser组访问Internet，但advance、normal组允许（此时还没有指定详细的权限）。由于Squid是按照顺序读取规则，会首先禁止baduser，然后允许normal。如果将两条规则顺序颠倒，由于baduser在normal范围中，Squid先允许了所有的normal，那么再禁止baduser就不会起作用。 </P>
<P>　　特别要注意的是，Squid将使用allow-deny-allow-deny……这样的顺序套用规则。例如，当一个用户访问代理服务器时，Squid会顺序测试Squid中定义的所有规则列表，当所有规则都不匹配时，Squid会使用与最后一条相反的规则。就像上面这个例子，假设有一个用户的IP地址是192.168.0.201，他试图通过这台代理服务器访问Internet，会发生什么情况呢？我们会发现，他能够正常访问，因为Squid找遍所有访问列表也没有和192.168.0.201有关的定义，便开始应用规则，而最后一条是deny，那么Squid默认的下一条处理规则是allow，所以192.168.0.201反而能够访问Internet了，这显然不是我们希望的。所以在所有squid.conf中，最后一条规则永远是http_access deny all，而all就是前面定义的“src 0.0.0.0”。 </P>
<P>　　高级控制 </P>
<P>　　前面说过，Squid的控制功能非常强大，只要理解Squid的行为方式，基本上就能够满足所有的控制要求。下面就一步一步来了解Squid是如何进行控制管理的。 </P>
<P>　　通过IP地址来识别用户很不可靠，比IP地址更好的是网卡的MAC物理地址。要在Squid中使用MAC地址识别，必须在编译时加上“--enable-arp-acl”选项，然后可以通过以下的语句来识别用户： </P>
<P>acl advance arp 00:01:02:1f:2c:3e 00:01:02:3c:1a:8b ... </P>
<P><BR>　　它直接使用用户的MAC地址，而MAC地址一般是不易修改的，即使有普通用户将自己的IP地址改为高级用户也无法通过，所以这种方式比IP地址可靠得多。 </P>
<P>　　假如不想让用户访问某个网站应该怎么做呢？可以分为两种情况：一种是不允许访问某个站点的某个主机，比如ok的主机是ok.sina.com.cn，而其它的新浪资源却是允许访问的，那么ACL可以这样写： </P>
<P>acl sinapage dstdomain ok.sina.com.cn <BR>... ... <BR>http_access deny ok <BR>... ... </P>
<P><BR>　　由此可以看到，除了ok，其它如<A href="http://www.sina.com.cn">www.sina.com.cn</A>、news.sina.com.cn都可以正常访问。 </P>
<P>　　另一种情况是整个网站都不许访问，那么只需要写出这个网站共有的域名即可，配置如下： </P>
<P>acl qq dstdomain .tcccent.com.cn </P>
<P><BR>　　注意tcccent前面的“.”，正是它指出以此域名结尾的所有主机都不可访问，否则就只有tcccent.com.cn这一台主机不能访问。 </P>
<P>　　如果想禁止对某个IP地址的访问，如202.118.2.182，可以用dst来控制，代码如下： </P>
<P><BR>acl badaddr dst 202.118.2.182 </P>
<P><BR>　　当然，这个dst也可以是域名，由Squid查询DNS服务器将其转换为IP。 </P>
<P>　　还有一种比较广泛的控制是文件类型。如果不希望普通用户通过代理服务器下载MP3、AVI等文件，完全可以对他们进行限制，代码如下： </P>
<P>acl mmxfile urlpath_regex \.mp3$ \.avi$ \.exe$ <BR>http_access deny mmxfile </P>
<P><BR>　　看到regex，很多读者应该心领神会，因为这条语句使用了标准的规则表达式（又叫正则表达式）。它将匹配所有以.mp3、.avi等结尾的URL请求，还可以用-i参数忽略大小写，例如以下代码： </P>
<P>acl mmxfile urlpath_regex -i \.mp3$ </P>
<P><BR>　　这样，无论是.mp3还是.MP3都会被拒绝。当然，-i参数适用于任何可能需要区分大小写的地方，如前面的域名控制。 </P>
<P>　　如果想让普通用户只在上班时间可以上网，而且是每周的工作日，用Squid应当如何处理呢？看看下面的ACL定义： </P>
<P>acl worktime time MTWHF 8:30-12:00 14:00-18:00 <BR>http_access deny !worktime </P>
<P><BR>　　首先定义允许上网的时间是每周工作日（星期一至星期五）的上午和下午的固定时段，然后用http_access 定义所有不在这个时间段内的请求都是不允许的。 </P>
<P>　　或者为了保证高级用户的带宽，希望每个用户的并发连接不能太多，以免影响他人，也可以通过Squid控制，代码如下： </P>
<P>acl conncount maxconn 3 <BR>http_access deny conncount normal <BR>http_access allow normal </P>
<P><BR>　　这样，普通用户在某个固定时刻只能同时发起三个连接，从第四个开始，连接将被拒绝。 </P>
<P>　　总之，Squid的ACL配置非常灵活、强大，更多的控制方式可以参考squid.conf.default。 </P>
<P>　　认证 </P>
<P>　　用户/密码认证为Squid管理提供了更多便利，最常用的认证方式是NCSA。从Squid 2.5版本开始，NCSA认证包含在了basic中，而非以前单独的认证模块。下面来看看实现认证的具体操作。 </P>
<P>　　首先在编译时配置选项应包括以下配置： </P>
<P>--enable-auth="basic" --enable-basic-auth-helpers="NCSA" </P>
<P><BR>　　“make install”以后，需要将“helpers/basic_auth/NCSA/ncsa_auth”拷贝到用户可执行目录中，如/usr/bin（如果在该目录中找不到这个执行文件，在编译时请使用make all而不是make，或者直接在该目录中执行make），然后需要借助Apache的密码管理程序htpasswd来生成用户名/密码对应的文件，就像下面这行代码： </P>
<P>htpasswd -c /var/squid/etc/password guest </P>
<P><BR>　　在输入两遍guest用户的密码后，一个guest用户就生成了。如果以后需要添加用户，把上面的命令去掉-c参数再运行即可。 </P>
<P>　　Squid 2.5在认证处理上有了较大的改变，这里就只讨论2.5版本的处理方法，2.4及以下版本请参考squid.conf.default。在2.5版的squid.conf中，包括以下几个相关选项： </P>
<P>#该选项指出了认证方式（basic)、需要的程序（ncsa_auth）和 <BR>对应的密码文件（password） <BR>auth_param basic program /usr/bin/ncsa_auth /var/squid/etc/password <BR># 指定认证程序的进程数 <BR>auth_param basic children 5 <BR># 浏览器显示输入用户/密码对话框时的领域内容 <BR>auth_param basic realm My Proxy Caching Domain <BR># 基本的认证有效时间 <BR>auth_param basic credentialsttl 2 hours <BR># 普通用户需要通过认证才能访问Internet <BR>acl normal proxy_auth REQUIRED <BR>http_access allow normal </P>
<P><BR>　　通过以上的配置即可完成认证工作。有的读者可能要问：认证只针对普通用户，而高级用户是直接上网的，该怎么处理呢？其实，这两种用户是可以共存的。如前所述，Squid是顺序处理http_access的，所以在http_access处理过程中，如果先处理normal用户，那么当前用户无论是否属于高级用户，都会被要求进行认证；相反如果先处理高级用户，剩下的就只有需要认证的普通用户了。例如以下配置代码： </P>
<P>... <BR>http_access allow normal (需要认证) <BR>http_access allow advance （不需要认证） <BR>... </P>
<P><BR>　　不管是否为noauth用户，都要求进行用户名/密码验证。正确的方法是将二者位置交换，代码如下： </P>
<P>... <BR>http_access allow advance <BR>http_access allow normal <BR>... </P>
<P><BR>　　这时，高级用户不会受到任何影响。 </P>
<P>　　总结 </P>
<P>　　下面把整个squid.conf总结一下： </P>
<P># 服务器配置 <BR>http_port 192.168.0.1:3128 <BR>cache_mgr <A href="mailto:start@soocol.com">start@soocol.com</A> <BR>cache_dir null /tmp <BR>cache_access_log /var/squid/access.log <BR>cache_log /var/squid/cache.log <BR>cache_store_log /var/squid/store.log <BR>visible_hostname No1.proxy <BR>client_mask 255.255.255.255 <BR>httpd_accel_host virtual <BR>httpd_accel_port 80 <BR>httpd_accel_with_proxy on <BR>httpd_accel_user_host_header on </P>
<P># 用户分类 <BR>acl advance arp 00:01:02:1f:2c:3e 00:01:02:3c:1a:8b ... <BR>acl normal proxy_auth REQUIED <BR>acl all src 0.0.0.0 </P>
<P># 行为分类 <BR>acl mmxfile urlpath_regex \.mp3$ \.avi$ \.exe$ <BR>acl conncount maxconn 3 <BR>acl worktime time MTWHF 8:30-12:00 14:00-18:00 <BR>acl sinapage dstdomain ok.sina.com.cn <BR>acl qq dstdomain .tcccent.com.cn </P>
<P># 处理 <BR>http_access allow advance <BR>http_access deny conncount normal <BR>http_access deny !worktime <BR>http_access deny mmxfile <BR>http_access deny sinapage <BR>http_access deny qq <BR>http_access allow normal </P>
<P><BR>　　配置后的状况是，advance组可以不受任何限制地访问Internet，而normal组则只能在工作时间上网，而且不能下载多媒体文件，不能访问某些特定的站点，而且发送请求不能超过3个。 </P>
<P>　　通过本文的介绍，它可以了解Squid的基本能力。当然，它的能力远不止此，可以建立强大的代理服务器阵列，可以帮助本地的Web服务器提高性能，可以提高本地网络的安全性等。要想发挥它的功效，还需要进一步控制。<BR></P><img src ="http://www.blogjava.net/nighTuner/aggbug/3244.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nighTuner/" target="_blank">nighTuner</a> 2005-04-14 01:37 <a href="http://www.blogjava.net/nighTuner/articles/3244.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Redhat AS 3.0上apache2.0.50+tomcat5.0.25+jk2 的安装</title><link>http://www.blogjava.net/nighTuner/articles/3243.html</link><dc:creator>nighTuner</dc:creator><author>nighTuner</author><pubDate>Wed, 13 Apr 2005 17:25:00 GMT</pubDate><guid>http://www.blogjava.net/nighTuner/articles/3243.html</guid><wfw:comment>http://www.blogjava.net/nighTuner/comments/3243.html</wfw:comment><comments>http://www.blogjava.net/nighTuner/articles/3243.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/nighTuner/comments/commentRss/3243.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/nighTuner/services/trackbacks/3243.html</trackback:ping><description><![CDATA[<P>安装j2sdk-1_4_2_02-linux-i586-rpm.bin（或其他版本都ok）<BR>下载后双击安装<BR>_______________________________________________________________________________</P>
<P>配置环境变量<BR>编辑/etc/profile 加入下面句：<BR>PATH=/usr/j2se/bin （改为你安装j2sdk的路径） <BR>JAVA_HOME=/usr/j2se （改为你安装j2sdk的路径） <BR>CLASSPATH=/usr/j2se/lib/tools.jar:/usr/j2se/lib/dt.jar （改为你安装j2sdk的路径）<BR>export PATH JAVA_HOME CLASSPATH </P>
<P>重新启动使之生效<BR>_________________________________________________________________<BR>Tomcat 5.0.25 </P>
<P>在<A href="http://www.apache.org">http://www.apache.org</A>下载得到jakart...t-5.0.25.tar.gz <BR>#gunzip jakarta-tomcat-5.0.25.tar.gz <BR>#tar xvf jakarta-tomcat-5.0.25.tar <BR>#mv jakarta-tomcat-5.0.25 /usr/local/tomcat5.0.25 <BR>#cd /usr/local/tomcat5.0.25/bin <BR>#./catalina.sh start </P>
<P>然后测试 <A href="http://localhost:8080">http://localhost:8080</A> 看到那个猫了吧，恭喜你tomcat安装ok</P>
<P>_____________________________________________________________________</P>
<P>安装apache2.0.50<BR>估计用到的工具有：gcc,automake,autoconfig;libtools,m4 大家可以去下载rpm包安装就行了，别忘了写人环境变量噢 :-P</P>
<P>到<A href="http://www.apache.org">http://www.apache.org</A>下载后</P>
<P>gunzip httpd-2.0.50.tar.gz<BR>tar xvf httpd-2.0.50.tar<BR>cd httpd-2.0.50/bin <BR>./configure -prefix=/usr/local/apache2 -enable-so (可改为你自己的目录；-enable-so用于加载connector，不可省略，你还可以加上你自己的其他模块)<BR>make<BR>make install<BR>cd /usr/local/apache2/conf<BR>vi httpd.conf<BR>更改：servername 你的机器ip或域名<BR>group nobody<BR>listen yourip:80 （apache2以后把port已经改成了listen）</P>
<P>保存后，cd ../bin<BR>./apachectl start </P>
<P>测试：<A href="http://localhost">http://localhost</A> 看到apache的欢迎界面了吧，ok</P>
<P>_____________________________________________________________________________________</P>
<P>整合apache2与tomcat5.0.25</P>
<P>用连接器jakarta-tomcat-connectors-jk2-src-current.tar.gz（就是jk2），大家可到<A href="http://jakarta.apache.org/site/sourceindex.cgi">http://jakarta.apache.org/site/sourceindex.cgi</A>下载</P>
<P>gunzip jakarta-tomcat-connectors-jk2-src-current.tar.gz<BR>tar xvf jakarta-tomcat-connectors-jk2-src-current.tar<BR>cd jakarta-tomcat-connectors-jk2-src-current/jk/native2<BR>./configure --with-apxs2=/usr/local/apache2/bin/apxs (注意改为你的apache安装目录)<BR>make<BR>cd ../build/jk2/apache2<BR>/usr/local/apache2/bin/apxs -n jk2 -i mod_jk2.so<BR>现在大家可以看到mod_jk2.so文件已经在你的apache/modules/ 中了</P>
<P>编辑apache/conf/httpd.conf <BR>LoadModule jk2_module modules/mod_jk2.so 保存</P>
<P>在apache/conf/中新建文件workers2.properties，内容为下（注意其中目录要改为你的目录噢）：</P>
<P>[shm] <BR>file=/usr/local/apache2/logs/shm.file <BR>size=1048576 <BR># Example socket channel， override port and host. <BR>[channel.socket:localhost:8009] <BR>port=8009 <BR>host=127.0.0.1 <BR># define the worker <BR>[ajp13:localhost:8009] <BR>channel=channel.socket:localhost:8009 <BR># Uri mapping <BR>[uri:/*] <BR>worker=ajp13:localhost:8009</P>
<P>保存后，就快大功告成啦，呵呵</P>
<P>cd apache2/bin<BR>./apachectl start</P>
<P>测试：<A href="http://localhost">http://localhost</A></P><img src ="http://www.blogjava.net/nighTuner/aggbug/3243.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nighTuner/" target="_blank">nighTuner</a> 2005-04-14 01:25 <a href="http://www.blogjava.net/nighTuner/articles/3243.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>LVS 集群服务器实施详解</title><link>http://www.blogjava.net/nighTuner/articles/3241.html</link><dc:creator>nighTuner</dc:creator><author>nighTuner</author><pubDate>Wed, 13 Apr 2005 17:04:00 GMT</pubDate><guid>http://www.blogjava.net/nighTuner/articles/3241.html</guid><wfw:comment>http://www.blogjava.net/nighTuner/comments/3241.html</wfw:comment><comments>http://www.blogjava.net/nighTuner/articles/3241.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/nighTuner/comments/commentRss/3241.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/nighTuner/services/trackbacks/3241.html</trackback:ping><description><![CDATA[<P>Linux Virtual Server矛简称LVS。是由中国一个Linux程序员发起的开发项目计划，其实现目标是创建一个具有良好的扩展性、高可靠性、高性能和高可用性的，基于Linux系统的服务器集群。 <BR><BR>1.LVS系统结构与特点 </P>
<P><BR>使用LVS架设的服务器集群系统从体系结构上看是透明的，最终用户只感觉到一个虚拟服务器.物理服务器之间可以通过高速的LAN或分布在各地的WAN相连。最前端是负载均衡器，它负责将各种服务请求分发给后面的物理服务器，让整个集群表现得象一个服务于同一IP地址的虚拟服务器。 </P>
<P>LVS集群系统具有良好的可扩展性和高可用性。 </P>
<P>可扩展性是指，LVS集群建立后，可以很容易地根据实际的需要增加或减少物理服务器。而高可用性是指当检测到服务器节点或服务进程出错、失效时，集群系统能够自动进行适当的重新调整系统。 </P>
<P>cente2.LVS是如何工作的 </P>
<P><BR>Linux Virtual Server的主要是在负载均衡器上实现的，负载均衡器是一台加了LVS Patch的2.2.x版内核的Linux系统。LVS Patch可以通过重新编译内核的方法加入内核，也可以当作一个动态的模块插入现在的内核中。 </P>
<P>负载均衡器可以运行在以下三种模式下中的一种或几种： 1）Virtual Server via NAT（VS-NAT）：用地址翻译实现虚拟服务器；2）Virtual Server via IP Tunneling （VS-TUN）：用IP隧道技术实现虚拟服务器；3）Virtual Server via Direct Routing（VS-DR）：用直接路由技术实现虚拟服务器。 </P>
<P>另外，还需要根据LVS应用对物理服务器进行恰当的配置。 </P>
<P>以下将分别讲述一下三种模式的工作原理和优缺点。 </P>
<P>2.1.Virtual server via NAT（VS-NAT） </P>
<P>Virtual Server via NAT方法的最大优点是集群中的物理服务器可以使用任何支持TCP/IP操作系统，物理服务器可以分配Internet的保留私有地址，只有负载均衡器需要一个合法的IP地址。 </P>
<P>这种实现方法的最大的缺点是扩展性有限。当服务器节点（普通PC服务器）数据增长到20个或更多时,负载均衡器将成为整个系统的瓶颈，因为所有的请求包和应答包都需要经过负载均衡器再生。假使TCP包的平均长度是536字节的话，平均包再生延迟时间大约为60us（在Pentium处理器上计算的，采用更快的处理器将使得这个延迟时间变短），负载均衡器的最大容许能力为8.93M/s，假定每台物理服务器的平台容许能力为400K/s来计算，负责均衡器能为22台物理服务器计算。 </P>
<P>Virtual Server via NAT能够满足许多服务器的服务性能需求。即使是是负载均衡器成为整个系统的瓶颈，如果是这样也有两种方法来解决它。一种是混合处理，另一种是采用Virtual Server via IP tunneling或Virtual Server via direct routing。如果采用混合处理的方法，将需要许多同属单一的RR DNS域。你采用Virtual Server via IP tunneling或Virtual Server via direct routing以获得更好的可扩展性。也可以嵌套使用负载均衡器，在最前端的是VS-Tunneling或VS-Drouting的负载均衡器，然后后面采用VS-NAT的负载均衡器。 </P>
<P>2.2.Virtual server via IP tunneling（VS-TUN） </P>
<P>采用VS-NAT方式，请求与应答包都需要经过负载均衡器，那么当服务器节点增长到20个或更多时，这个负载均衡器就可能成为新的瓶颈。我们发现，许多Internet服务（例如WEB服务器）的请求包很短小，而应答包通常很大。 </P>
<P>而使用VS-TUN方式的话，负载均衡器只负责将请求包分发给物理服务器，而物理服务器将应答包直接发给用户。所以，负载均衡器能处理很巨大的请求量，这种方式，一台负载均衡能为超过100台的物理服务器服务，负载均衡器不再是系统的瓶颈。使用VS-TUN方式，如果你的负载均衡器拥有100M的全双工网卡的话，就能使得整个Virtual Server能达到1G的吞吐量。 </P>
<P>IP tunneling（IP隧道）能够用于架构一个高性能的virtual server，非常适合构建virtual proxy server，因为当代理服务器收到了请求，能够让最终用户直接与服务器联系。 </P>
<P>但是，这种方式需要所有的服务器支持IP Tunneling(IP Encapsulation)协议，我仅在Linux系统上实现了这个，如果你能让其它操作系统支持，还在探索之中。 </P>
<P>2.3.Virtual Server via Direct Routing（VS-DR） </P>
<P>就象VS-TUN一下，在VS-DR方式下，负载均衡器也只是分发请求，应答包通过单独的路由方法返回给客户端。这种方式能够大大提高Virtual Server的可扩展性。与VS-TUN相比，VS-DR这种实现方式不需要隧道结构，但它要求负载均衡器的网卡必须与物理网卡在一个物理段上。 </P>
<P>而且VS-DR模式，可以使用大多数操作系统做为物理服务器，其中包括：Linux 2.0.36、2.2.9、2.2.10、2.2.12；Solaris 2.5.1、2.6、2.7；FreeBSD 3.1、3.2、3.3；NT4.0无需打补丁；IRIX 6.5；HPUX11等 </P>
<P>&nbsp;</P>
<P><BR>3.安装配置LVS </P>
<P><BR>LVS的安装配置主要可以分成以下三个步骤： <BR>1） 下载LVS软件； <BR>2） 安装、配置负载均衡器； <BR>3） 安装、配置物理服务器； </P>
<P>3.1. 安装前的准备 </P>
<P>1).下载LVS软件： <BR>大家可以到LVS的主页（<A href="http://www.linuxvirtualserver.org">http://www.linuxvirtualserver.org</A>），选择“Software”链接，选取最新版的补丁包（tar包）下载。这个包里包含了内核补丁和源程序。 </P>
<P>2).安装的指导思想 </P>
<P>如果你选用了VS-NAT模式的话，则可以使用所有支持TCP/IP协议的操作系统构建的机器作物理服务器，并且无须做任何修改。 </P>
<P>如果你选用了VS-TUN模式的话，则选择Linux作物理服务器的操作系统，并根据后面的介绍做相应的设置。 </P>
<P>如果你选用了VS-DR模式的话，则可以选择大多数操作系统（如上节所述）作物理服务器，并根据后面的介绍做相应的设置。 </P>
<P>3).各种操作系统作物理服务器的要点详解 </P>
<P>a）Linux 2.0.36 <BR>这种操作系统无需做任何修改，就可以运行在VS-NAT、VS-Tun、VS-DR三种模式下。 </P>
<P>b）Linux 2.2.x </P>
<P>无需任何修改就可运行VS-NAT模式。而使用VS-DR和VS-Tun两种模式可能会引起ARP问题。这种情况 <BR>就必须：¨ 为2.2.x内核打补丁 </P>
<P>· Stephen WillIams的补丁包： <BR>你可以在<A href="http://www.linuxvirtualserver.org/sdw_fullarpfix.patch">http://www.linuxvirtualserver.org/sdw_fullarpfix.patch</A>获取，它的原理十分简单：让物理服务器不响应对虚拟IP的ARP请求。 </P>
<P>· Julian Anastasov的补丁包： <BR>你可以在<A href="http://www.linuxvirtualserver.org/arp_invisible-2213-2.diff">http://www.linuxvirtualserver.org/arp_invisible-2213-2.diff</A>处获取，然后用以下方法使其生效： <BR>echo 1 /proc/sys/net/ipv4/conf/interface_name/arp_invisible </P>
<P>¨ 新添一块网卡承载虚拟IP地址： <BR>你可以选择一块ISA网卡或廉价的PCI网卡来用于这个功能。你可以将这个接口的ARP功能关闭。 </P>
<P>¨ 将物理服务器放置于与虚拟IP地址不同的网络上，并且确认客户端无法直接路由到物理服务器所在网段。这种方法需要在负载均衡器上有两块网卡象防火墙一样工作。 </P>
<P>¨ 在客户端或路由器将虚拟IP地址与负载均衡器的物理MAC地址绑定。 </P>
<P>¨ 使用IPCHINA重写每一个进入的包，将其从lo接口送入。 </P>
<P>c）其它操作系统 <BR>如果是VS-NAT的话，无需修改。如果是VS-DR的话，需要采取一些相应的配置方法设置物理服务器的IP地址，使其拥有LVS的虚拟IP地址。用其它操作系统的话不能使用VS-Tun方法。 </P>
<P>4).准备硬件环境 <BR>构建服务器集群系统，至少需要3台机器，1台用于负载均衡器，2台用于物理服务器。少于这个数字的话就没有意义了。 </P>
<P>负载均衡器：运行在打了补丁的2.2.x核心Linux系统。 </P>
<P>物理服务器： <BR>VS-NAT：任何机器、任何操作系统，运行Internet网络服务，如 HTTP、FTP、Telnet、SMTP、NNTP、DNS等。 <BR>VS-TUN：任何机器、支持IP隧道的操作系统（迄今为止仅有Linux） <BR>VS-DR：任何机器、大多操作系统。 </P>
<P>3.2. 理解LVS的相关术语 </P>
<P>1).ipvsadm <BR>ipvsadm是LVS的一个用户界面。在负载均衡器上编译、安装ipvsadm： <BR>ipvsadm sets </P>
<P>2).调度算法 <BR>LVS的负载均衡器有以下几种调度规则： <BR>Round-robin，简称rr，weighted Round-robin，简称wrr，每个新的连接被轮流指派到每个物理服务器。 <BR>Least-connected，简称lc，weighted Least-connected，简称wlc，每个新的连接被分配到负担最小的服务器。 <BR>Persistent client connection，简称pcc，（持续的客户端连接，内核2.2.10版以后才支持）。所有来自同一个IP的客户端将一直连接到同一个物理服务器。超时时间被设置为360秒。Pcc是为https和cookie服务设置的。在这处调度规则下，第一次连接后，所有以后来自相同客户端的连接（包括来自其它端口）将会发送到相同的物理服务器。但这也会带来一个问题，大约有25％的Internet可能具有相同的IP地址（AOL的 <BR>客户是通过位于美国弗吉尼亚洲的一台服务器连入Internet的），这种情况下只要有一个AOL的客户连接到一个物理服务器上，那么所有来自AOL的客户连接将都被连到这一台物理服务器上。这将多么可怕呀！ </P>
<P>3).Persistent port connection调度算法 <BR>在内核2.2.12版以后，pcc功能已从一个调度算法（你可以选择不同的调度算法：rr、wrr、lc、wlc、pcc）演变成为了一个开关选项（你可以让rr、 wrr、lc、wlc具备pcc的属性）。在设置时，如果你没有选择调度算法时，ipvsadm将默认为wlc算法。 </P>
<P>在Persistent port connection(ppc)算法下，连接的指派是基于端口的，例如，来自相同终端的80端口与443端口的请求，将被分配到不同的物理服务器上。 <BR>不幸的是，如果你需要在的网站上采用cookies时将出问题，因为http是使用80端口，然而cookies需要使用443端口，这种方法下，很可能会出现cookies不正常的情况。 </P>
<P>3.3. 配置实例 </P>
<P>1).例一：https only <BR>a）在lvs_dr.conf 文件写入： <BR>SERVICE=t https ppc 192.168.1.1 <BR>b）Ipvsadm设置： <BR>IP Virtual Server version 0.9.4 (size=4096) <BR>Prot LocalAddress:Port Scheduler Flags <BR>- RemoteAddress:Port Forward Weight ActiveConn InActConn <BR>TCP ssl.mack.net:https wlc persistent 360 <BR>- di.mack.net:https Route 1 0 0 </P>
<P>2).例二：All ports sticky，超时为30分，wrr调度算法 <BR>a）在lvs_dr.conf 文件写入： <BR>SERVICE=t 0 wrr ppc -t 1800 192.168.1.1 <BR>#ppc persistent connection, timeout 1800 sec <BR>/sbin/ipvsadm -A -t 192.168.1.110:0 -s wrr -p 1800 <BR>echo adding service 0 to realserver 192.168.1.1 using connection <BR>（接上行） type dr weight 1\" <BR>/sbin/ipvsadm -a -t 192.168.1.110:0 -R 192.168.1.1 -g -w 1 <BR>b）Ipvsadm设置： <BR># ipvsadm <BR>IP Virtual Server version 0.9.4 (size=4096) <BR>Prot LocalAddress:Port Scheduler Flags <BR>- RemoteAddress:Port Forward Weight ActiveConn InActConn <BR>TCP ssl.mack.net:https wrr persistent 1800 <BR>- di.mack.net:https Route 1 0 0 </P>
<P>3.4. 配置方法 </P>
<P>1).准备 <BR>用配置脚本*.conf作为输入产生rc.lvs脚本，然后放置在/etc/init.d或/etc/rc.d目录下。 </P>
<P>早期版本的配置脚本可以运行在任何机器上。然而现在的配置脚本，针对不同的内核版本是有些不同的。你必须在负载均衡器上运行、检测内核版本。将在负载均衡器上的配置文件和目录，通过nfs输出这个 <BR>目录到物理服务器上以供配置需要。 必须先在负载均衡器上运行脚本rc.lvs，然后在物理服务器上运行。 </P>
<P>根据你选择的LVS工作模式（VS-NAT、VS-Tun、VS-DR）选择适当的conf文件模板（lvs_nat.conf、 <BR>lvs_tun.conf、lvs_dr.conf），然后根据实际情况修改IP地址与服务。在缺省状态下只配置了telnet服务。 <BR>telnet服务能够很方便地用于测试：当客户机telnet登录时，根据提示符就可以知道登录到的是哪一台物理 <BR>服务器。 </P>
<P>你可以编辑conf配置文件来增加其它的服务。在配置文件中提供了集群内部的IP地址建议值 <BR>（192.168.1.x/24、10.1.1.x/24）。 </P>
<P>在配置文件中，你可以使用名称（如telnet）或端口（如23）来标识服务。使用名称时要注意，须与 <BR>/etc/services中匹配。/etc/services文件内容如下所示： <BR>ssh 22/tcp <BR>domain 53/tcp nameserver dns #the string dns needs to be added here <BR>domain 53/tcp nameserver dns #and here <BR>https 443/tcp <BR>https 443/udp </P>
<P>在多种情况下，一台机器常需要多个IP地址，你可以使用IP别名（内核支持的可选项，一般情况下已含在内核中）来为一块网卡指定多个IP地址。 </P>
<P>2).运行配置脚本 <BR>$ ./configure.pl lvs_nat.conf </P>
<P>这将产生一个rc.lvs_xxx脚本（例如：rc.lvs_nat、rc.lvs_tun、rc.lvs_dr）以及mon_xxx.cf脚本。（稍后将rc.lvs_xxx放到/etc/rc.d或/etc/init.d中去，将mon_xxx.cf放在/etc/mon目录下）。 </P>
<P>3).rc.lvs脚本选项 <BR>a). 为负载均衡器与物理服务器增加以太网设备和路由器； <BR>b).使用fping检查连接； <BR>c).运行ipchains（VS-NAT方式）； <BR>d).激活ipforward； <BR>e).关闭ICMP重定向功能（VS-DR和VS-Tun方式）； <BR>f).增加ipvsadm服务。 </P>
<P>4).继续 <BR>在物理服务器上运行： <BR>$ . ./rc.lvs_nat 或 <BR>$sh rc.lvs_nat </P>
<P>rc.lvs脚本能够自动判断是运行在负载均衡器（tests x /sbin/ipvsadm）还是物理服务器上（检查ifconfig）。 </P>
<P>检查ipvsadm、ifconfig a和netstat rn的输出，检查服务/IP地址是否正确。如果不正确的话，请重 <BR>新编辑然后再运行一次。 </P>
<P>3.5.测试LVS </P>
<P>检查每一台物理服务器上运行的服务，看它们的IP是不是LVS的虚拟IP—VIP（使用netstat an）。如果运行rc.lvs_xxx脚本没有出错的话，你从客户端telnet到VIP（在本文中是192.168.1.110），你将会登录到其中的一台物理服务器上，并看到这台物理服务器的登录提示。 </P>
<P>在负载均衡器上查看ipvsadm的输出，你会在23端口上看到一个与物理服务器的连接。而在物理服务器上执行：$ netstat -an | grep 23命令查看到相关信息。客户端logout退出后，再次登录虚拟IP时，你将会看到另一台物理服务器的登录提示符。 </P>
<P>&nbsp;</P>
<P>4 VS-NAT模式 </P>
<P><BR>VS-NAT是基于CISCO的负载均衡器：LocalDirector实现的。 </P>
<P>4.1.安装VS-NAT </P>
<P>根据下表设置客户端、负载均衡器、物理服务器的IP地址： </P>
<P>表21-2.客户端、负载均衡器、物理服务器的IP地址 </P>
<P><BR>机 器 IP地址 <BR>客户端 192.168.1.254 <BR>负载均衡器的虚拟IP 192.168.1.110(LVS表现的IP) <BR>负载均衡器内部网卡 10.1.1.1 <BR>物理服务器1 10.1.1.2 <BR>物理服务器2 10.1.1.3 <BR>物理服务器3 10.1.1.4 <BR>…… …… <BR>物理服务器n 10.1.1.n+1 <BR>物理服务器的默认 <BR>网关 10.1.1.1 </P>
<P>对于VS-NAT方法来说，物理服务器必须位于与客户机、LVS的虚拟IP地址不同的网段上，也就是说在物理服务器上不能直接PING通客户机。 <BR>由于负载均衡器有两个IP地址，一个是LVS的虚拟IP地址，另一个IP地址是内部地址--所有物理服务器默认网关。当数据包从物理服务器发送到负载均衡器时，负载均衡器根据地址翻译（NAT）规则将包转发到客户端。（由于负载均衡器是一个地址翻译器，所以ICMP的重定向功能失效，PING无法应用）。可以采用IP别名的方法，也可以使用双网卡方法来实现这个。 </P>
<P>配置脚本将会配置IP伪装。以下是在configure.pl脚本中的程序段： <BR>echo turning on masquerading <BR>#setup masquerading <BR>echo 1 /proc/sys/net/ipv4/ip_forward <BR>echo installing ipchain rules <BR>/sbin/ipchains -A forward -j MASQ -s 10.1.1.0/24 -d 0.0.0.0/0 <BR>echo ipchain rules <BR>/sbin/ipchains L <BR>所有与NAT有关的规则设置都在rc.lvs_nat文件中表现。 </P>
<P>4.2.配置VS-NAT </P>
<P>在负载均衡器以及每一台物理服务器上分别执行rc.lvs_xxx脚本程序，使用lvs_nat.conf这个模板来生成rc.lvs_nat配置文件。 </P>
<P>VS-NAT将会对端口重新映射，一个来自于80端口的请求，负载均衡器会将其发给物理服务器的8000端口。由于数据包的源地址和目标地址已经被重写，所以无需对重新端口增加额外的开销。很低的重写数据包速度（60us/包）限制了VS-NAT的最大处理能力，而且VS-NAT的最大处理能力不是与增加的物理服务器成正比的。 </P>
<P>VS-NAT实现方法的最大优点是物理服务器可以是任何一种操作系统，无需为了完成LVS而作任何修改，而且可以实现一些在Linux上不存在服务。 </P>
<P>4.33.VS-NAT与Linux核心支持的NAT </P>
<P>当然可以使用ipchains或ipfw构建基于Linux内核的NAT防火墙。而使用了基于2.0.36版内核的LVS补丁包后，常规的内核模块（如ip_masq_ftp等）不再工作（而且不再需要装载）。 </P>
<P>&nbsp;</P>
<P>5.VS-DR模式 </P>
<P><BR>5.1.总论 </P>
<P>VS-DR是基于IBM的NetDispathcer实现的。NetDispatcher位于WEB服务器的前端，对于客户端来说就象一台WEB服务器。NetDispatcher曾服务于奥运会、卡斯帕罗夫与深蓝电脑的国际象棋比赛。 </P>
<P>这里有一个VS-DR的IP地址设置的实例。注意：物理服务器与VIP位于同一个网络上。 </P>
<P>VS-DR模式在以下几方面受到了限制 <BR>1） 物理服务器和负载均衡器必须在同一个网段上（它们之间必须能使用arp协议），它们之间在数据链路层上传递数据包； <BR>2） 客户端必须通过负载均衡器的VIP访问集群； <BR>3） 物理服务器必须有到客户端的路由（即使客户端没有到物理服务器的路由）。因为从物理服务器返回到客户商的包，将直接发送，无须通过负载均衡器转发。 </P>
<P>VS-DR模式下，客户端通常与负载均衡器和物理服务器位于不同的网络中，而且每一个物理服务器拥有自己对外的路由表。在下面这个简单的例子中，所有的机器都在192.168.1.0这个网络，物理服务器不需要设置默认路。网络拓扑结构如下图所示： </P>
<P><BR>IP分配如下表所示： </P>
<P><BR>表21-3 .IP分配 </P>
<P><BR>机 器 IP 地 址 <BR>客户端 本机IP：CIP 192.168.1.254 </P>
<P>负载均衡器 本机IP：DIP 192.168.1.1 <BR>虚拟IP：VIP 192.168.1.110（ARP与客户端使用） </P>
<P>物理服务器1 本机IP：RIP 192.168.1.2 <BR>虚拟IP：VIP 192.168.1.110（不ARP） </P>
<P>物理服务器2 本机IP：RIP 192.168.1.3 <BR>虚拟IP：VIP 192.168.1.110（不ARP） </P>
<P>物理服务器3 本机IP：RIP 192.168.1.4 <BR>虚拟IP：VIP 192.168.1.110（不ARP） </P>
<P><BR>5.2.VS-DR良好的扩展性 </P>
<P>VS-NAT方法受限于经过负载均衡器的每一包都必须重写，用这种方法最大的数据吞吐量受限于负载均衡器的环境。（如一台Pentium机器，快速以太网，最大的数据吞吐量为80M/秒）而且增加物理服务器的数量并不能增加这个最大数据吞吐量。而使用VS-DR模式，速度限制则在每个物理服务器与Internet连接的包处理能力，而对负载均衡器的要求不大，因为其只需处理简单的包。在VS-DR的模式下，能够增加更多物理服务器以提高系统能力。 </P>
<P><BR>6 VS-TUN模式 </P>
<P><BR>6.1.总论 </P>
<P>VS-Tun是LVS独创的的，它是基于VS-DR发展的。具有良好的可扩展性和服务吞吐量。 </P>
<P>使用VS-Tun方式的话，必须采Linux作为物理服务器，而负载均衡器将IP请求重新包装成IPIP包后发给 <BR>物理服务器。所以物理服务器必须能够解IPIP包装才能，现在只有Linux操作系统能处理IPIP包（IP隧道技 <BR>术）。 </P>
<P>不同于VS-DR，VS-Tun方案允许物理服务器与负载均衡器在不同的网络上，甚至允许所有的机器都在 <BR>单独的网络上，那怕物理服务器位于不同的国家（例如：做一个项目的FTP站点镜像）。在这种情况下物理 <BR>服务器将产生源地址=虚拟IP地址，目标地址=客户机IP地址的IP包。 </P>
<P>如果物理服务器与负载均衡器位于相同的网络上，那么VS-DR和VS-Tun是等价的。VS-DR更具有灵活 <BR>性，因为大多数操作系统都可以用来构建物理服务器。 </P>
<P>6.2. VS-Tun实例 </P>
<P>以下是一个VS-Tun的IP配置实例。VS-Tun提供的最大方便性就是不需要服务器与客户端位于同一个网络上，仅需要客户端能寻径（有路由）到负载均衡器，物理服务器能寻径（有路由）到客户机。（返回的包直接从物理服务器到客户端，无须再经过负载均衡器） </P>
<P>通常使用VS-Tun模式时，客户端是与负载均衡器、物理服务器位于不同网络上的，而且每一台服务器 <BR>有一个通往外界的路由。 </P>
<P>IP分配如下表所示： </P>
<P><BR>表21-4.IP分配 </P>
<P><BR>机 器 IP 地 址 <BR>客户端 本机IP：CIP 192.168.1.254 </P>
<P>负载均衡器 本机IP：DIP 192.168.1.1 <BR>虚拟IP：VIP 192.168.1.110（ARP与客户端使用） </P>
<P>物理服务器1 本机IP：RIP 192.168.1.2 <BR>虚拟IP：VIP 192.168.1.110（隧道技术，不ARP） </P>
<P>物理服务器2 本机IP：RIP 192.168.1.3 <BR>虚拟IP：VIP 192.168.1.110（隧道技术，不ARP） </P>
<P>物理服务器3 本机IP：RIP 192.168.1.4 <BR>虚拟IP：VIP 192.168.1.110（隧道技术，不ARP） </P>
<P>…… …… …… <BR>物理服务器n 本机IP：RIP 192.168.1.n+1 <BR>虚拟IP：VIP 192.168.1.110（隧道技术，不ARP） </P>
<P><BR>6.3.配置VS-Tun </P>
<P>1）编辑配置文件模板lvs_tun.conf后，进行配置： <BR>$ ./configure_lvs.pl lvs_nat.conf <BR>2）在物理服务器上运行： <BR>$ . ./etc/rc.d/rc.lvs_tun <BR>3）将配置文件放到/etc/rc.d或/etc/init.d目录下。 <BR>4）检查ipvsadm、ifconfig a和netstat rn的输出，检查服务/IP地址是否正确，如果有误，请修改后重新运行脚本。 </P><img src ="http://www.blogjava.net/nighTuner/aggbug/3241.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nighTuner/" target="_blank">nighTuner</a> 2005-04-14 01:04 <a href="http://www.blogjava.net/nighTuner/articles/3241.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>系统时间同步及ntp服务的提供</title><link>http://www.blogjava.net/nighTuner/articles/3240.html</link><dc:creator>nighTuner</dc:creator><author>nighTuner</author><pubDate>Wed, 13 Apr 2005 16:52:00 GMT</pubDate><guid>http://www.blogjava.net/nighTuner/articles/3240.html</guid><wfw:comment>http://www.blogjava.net/nighTuner/comments/3240.html</wfw:comment><comments>http://www.blogjava.net/nighTuner/articles/3240.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/nighTuner/comments/commentRss/3240.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/nighTuner/services/trackbacks/3240.html</trackback:ping><description><![CDATA[电脑的时间放置不理的话过不久就会出现误差。 <BR>这个误差会反映在email送信时刻的time stamp上，会反映在你的论坛帖子发表时刻上。至少我遇到过这个问题。 <BR>网络上有ntp(network time protocol)服务器，提供当前的时刻。我们可以将本地的时刻与ntp服务器的时刻进行同步。<BR><BR>目的如下： <BR>1，启动时用ntpdate进行时刻修正。 <BR>2，启动中，通过ntpd进行时刻校正的同时，将各个客户端电脑的时刻也进行同期校正。 <BR>3，如果不能找到ntp服务器，那么就使用local time，同时同步客户。<BR><BR>全世界约有100多个ntp服务器，从下面地址找一个离你最近的 <BR>
<DIV class=code>http://www.eecis.udel.edu/~mills/ntp/clock1a.html </DIV>我选择了两个 <BR>
<DIV class=code>clock.nc.fukuoka-u.ac.jp 133.100.9.2 <BR>clock.tl.fukuoka-u.ac.jp 133.100.11.8 <BR></DIV>步骤： <BR><BR>FreeBSD中有两个标准的ntp程序，其一为ntpdate。<BR>ntpdate通过从ntp服务器获取时刻，调整本地时刻。 <BR>
<DIV class=code># ntpdate clock.nc.fukuoka-u.ac.jp <BR>9 Oct 18:12:23 ntpdate: step time server 133.100.9.2 offset -19.112674 </DIV>大约有19秒钟的误差 <BR><BR>自动设定 <BR>
<DIV class=code># grep ntpdate /etc/defaults/rc.conf &gt;&gt;/etc/rc.conf <BR># vi /etc/rc.conf <BR>ntpdate_enable="YES" # Run ntpdate to sync time on boot (or NO). <BR>ntpdate_program="ntpdate" # path to ntpdate, if you want a different one. <BR>ntpdate_flags="clock.nc.fukuoka-u.ac.jp" # Flags to ntpdate (if enabled). </DIV>重新启动以后就运行了，当然设定没有完，不必急着启动 <BR>FreeBSD的另一个标准ntp程序，ntp <BR>ntp程序使的获取ntp时刻的同时，向其他pc提供时刻。<BR><BR>添加文件ntp.conf： <BR><BR>用来作为标准时刻的ntp服务器我选择了两个 <BR>
<DIV class=code>clock.nc.fukuoka-u.ac.jp 133.100.9.2 <BR>clock.tl.fukuoka-u.ac.jp 133.100.11.8 <BR></DIV>同时指定复数个服务器也没有问题，系统会自动选择一个可以信赖的。 <BR>这里，为避免多余的DNS数据包传递，我们直接指定IP地址。 <BR>server行 server 127.127.1.0 为参考本地时刻时用的地址。然后用fudge指定阶层编号为5，降低其优先度。<BR><BR>接着用restrict对每一个IP地址指定相应的规则。 <BR>最后，指定波长校正用的drift文档保存地址。关于这个命令行，具体的含义不太清楚。不过如果没有的话，时间校正起来就会比较慢 <BR>
<DIV class=code># vi /etc/ntp.conf <BR>server 133.100.9.2 #clock.nc.fukuoka-u.ac.jp <BR>server 133.100.11.8 #clock.tl.fukuoka-u.ac.jp <BR>server 127.127.1.0 <BR>fudge 127.127.0.1 stratum 5 <BR>restrict default ignore <BR>restrict 127.0.0.0 mask 255.0.0.0 <BR>restrict 192.168.1.0 mask 255.255.255.0 noquery nopeer notrust <BR>restrict 133.100.9.2 noquery <BR>restrict 133.100.11.8 noquery <BR>driftfile /etc/ntpd.drift </DIV>启动测试 <BR>
<DIV class=code># ntpd -p /var/run/ntpd.pid <BR># tail /var/log/messages <BR>Oct 9 16:46:56 chiwawa ntpd[89409]: ntpd 4.1.0-a Thu Apr 3 08:26:24 GMT 2003 (1) <BR>Oct 9 16:46:56 chiwawa ntpd[89409]: kernel time discipline status 2040 <BR>...... <BR>Oct 9 16:50:10 chiwawa ntpd[89409]: time set -0.189546 s </DIV>看到类似的结果就可以了。<BR><BR>运行测试<BR>ntpd的运行用ntpq命令 <BR>
<DIV class=code># ntpq -p <BR>remote refid st t when poll reach delay offset jitter <BR>============================================================================== <BR>*clock.nc.fukuok .GPS. 1 u 43 64 37 19.067 -6.884 10.339 <BR>+clock.tl.fukuok .GPS. 1 u 36 64 35 19.670 -3.259 2.341 <BR>LOCAL(0) LOCAL(0) 5 l 45 64 37 0.000 0.000 0.001 </DIV>启动后到时刻校正完成需要一点时间。*是第一候补，+是第二。 <BR>本地时刻校正完成以后就可以为其他PC提供时刻校正服务了。 <BR><BR>自动启动的设定 <BR>完成以上设定，确认运行无误以后： <BR>
<DIV class=code># grep ntpd /etc/defaults/rc.conf &gt;&gt;/etc/rc.conf <BR># vi /etc/rc.conf <BR>xntpd_enable="YES" # Run ntpd Network Time Protocol (or NO). <BR>xntpd_program="ntpd" # path to ntpd, if you want a different one. <BR>xntpd_flags="-p /var/run/ntpd.pid" # Flags to ntpd (if enabled). </DIV><BR>往rc.conf追加上面3行内容，并修改。 <BR>客户端PC设定： <BR>UNIX OS<BR>
<DIV class=code># vi /etc/ntp.conf <BR>server [local ntp server IP] prefer <BR>driftfile /etc/ntpd.drift <BR>或者追加下面内容到crontab，这样，每过一个小时0分的时候就自动更新。 <BR># vi /etc/crontab <BR>0 * * * * root ntpdate [ntp server IP] &gt;/dev/null 2&gt;&amp;1 <BR>当然，你的主机其实也是一个客户机，这些内容也可以用上。 </DIV><img src ="http://www.blogjava.net/nighTuner/aggbug/3240.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nighTuner/" target="_blank">nighTuner</a> 2005-04-14 00:52 <a href="http://www.blogjava.net/nighTuner/articles/3240.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Integrating Tomcat and Apache on Red Hat Linux 9 or Red Hat Enterprise Linux 3</title><link>http://www.blogjava.net/nighTuner/articles/3199.html</link><dc:creator>nighTuner</dc:creator><author>nighTuner</author><pubDate>Tue, 12 Apr 2005 16:20:00 GMT</pubDate><guid>http://www.blogjava.net/nighTuner/articles/3199.html</guid><wfw:comment>http://www.blogjava.net/nighTuner/comments/3199.html</wfw:comment><comments>http://www.blogjava.net/nighTuner/articles/3199.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/nighTuner/comments/commentRss/3199.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/nighTuner/services/trackbacks/3199.html</trackback:ping><description><![CDATA[<H2><A name=1_0>1.0 Introduction</A></H2>
<P>Java servlets are a powerful tool for building websites and web based applications. One skill that every Java web developer should have is the ability to install and configure the Tomcat servlet engine. Many thanks to the <A href="http://www.apache.org/" target=_blank>Apache Software Foundation</A> for providing this mbature, stable, open source software. It was recently voted the <A href="http://www.infoworld.com/article/03/07/25/29FErcamain_1.html?s=feature" target=_blank>Best Application Server of 2003</A> by InfoWorld readers.</P>
<P>This article discusses how to integrate Tomcat with the Apache web server on Red Hat Linux 9 or Red Hat Enterprise Linux 3. The goal is to provide a simple, stable configuration that will allow users to gain confidence using Tomcat.</P>Please note the following code conventions: 
<UL>
<LI>All commands are issued as root unless otherwise noted. 
<LI>Highlighted values should be customized to your setup. </LI></UL>
<H2><A name=2_0>2.0 Installing Apache</A></H2>
<P>I chose to install Apache using the Red Hat RPM. Using the RPM instead of compiling Apache from source simplifies system administration in the following ways:</P>
<UL>
<LI>Updates and bug fixes can be installed automatically from the <A href="http://rhn.redhat.com/" target=_blank>Red Hat Network</A>. 
<LI>Startup and shutdown scripts are already configured and available. </LI></UL>
<P>I recommend using the Red Hat up2date command line utility to install Red Hat RPMs. It eliminates a multitude of headaches by ensuring the software you install is the correct version and you have the right dependencies installed on your system.</P>
<P>Red Hat RPMs that must be installed:</P>
<UL>
<LI>httpd: the Apache web server 
<LI>httpd-devel: development tools that will be needed to create the mod_jk connector </LI></UL>
<P>To install these packages using up2date, make sure you are connected to the Internet, and enter the following:</P>
<DIV class=code><PRE>up2date -i httpd
up2date -i httpd-devel
</PRE></DIV>
<P>You should now be able to start/stop/restart Apache as follows:</P>
<DIV class=code><PRE>service httpd start
service httpd stop
service httpd restart
</PRE></DIV>
<P>Verify that Apache is working by starting Apache and typing http://localhost/ into your browser. You should see the default Apache install page with links to documentation.</P>
<H2><A name=3_0>3.0 Installing Tomcat</A></H2>
<P>The only requirements to run Tomcat are that a Java Development Kit (JDK), also called a Java Software Development Kit (SDK), be installed and the JAVA_HOME environment variable be set.</P>
<H3><A name=3_1>3.1 Java SDK</A></H3>
<P>I chose to install Sun's Java 2 Platform, Standard Edition, which can be downloaded from <A href="http://java.sun.com/j2se/" target=_blank>http://java.sun.com/j2se/)</A>. I chose the J2SE v1.4.2 SDK Linux self-extracting binary file.</P>
<P>Change to the directory where you downloaded the SDK and make the self-extracting binary executable:</P>
<DIV class=code><PRE>chmod +x j2sdk-1_4_2-linux-i586.bin
</PRE></DIV>
<P>Run the self-extracting binary:</P>
<DIV class=code><PRE>./j2sdk-1_4_2-linux-i586.bin
</PRE></DIV>
<P>There should now be a directory called j2sdk1.4.2 in the download directory. Move the SDK directory to where you want it to be installed. I chose to install it in /usr/java. Create /usr/java if it doesn't exist. Here is the command I used from inside the download directory:</P>
<DIV class=code><PRE>mv j2sdk1.4.2 /usr/java
</PRE></DIV>
<P>Set the JAVA_HOME environment variable, by modifying /etc/profile so it includes the following:</P>
<DIV class=code><PRE>JAVA_HOME="/usr/java/j2sdk1.4.2"
export JAVA_HOME
</PRE></DIV>
<P>/etc/profile is run at startup and when a user logs into the system, so you will need to log out and log back in for JAVA_HOME to be defined.</P>
<DIV class=code><PRE>exit
su -
</PRE></DIV>
<P>Check to make sure JAVA_HOME is defined correctly using the command below. You should see the path to your Java SDK.</P>
<DIV class=code><PRE>echo $JAVA_HOME
</PRE></DIV>
<H3><A name=3_2>3.2 Tomcat Account</A></H3>
<P>You will install and configure Tomcat as root; however, you should create a group and user account for Tomcat to run under as follows:</P>
<DIV class=code><PRE>groupadd tomcat
useradd -g tomcat tomcat
</PRE></DIV>
<P>This will create the /home/tomcat directory, where I will install my Tomcat applications.</P>
<H3><A name=3_3>3.3 Download Tomcat</A></H3>
<P>Download the latest release binary build from <A href="http://www.apache.org/dist/jakarta/tomcat-4/" target=_blank>http://www.apache.org/dist/jakarta/tomcat-4/</A>. Since Tomcat runs directly on top of a standard JDK, I cannot think of any reason to building it from source.</P>
<P>The Tomcat binary is available in two different flavors:</P>
<OL>
<LI>non-LE 
<UL>
<LI>Full binary distribution 
<LI>Includes all optional libraries and an XML parser (Xerces) 
<LI>Can be run on JDK 1.2+ </LI></UL>
<LI>LE 
<UL>
<LI>Lightweight binary distribution 
<LI>Designed to be run on JDK 1.4 
<LI>Does not include an XML parser because one is included in JDK 1.4 
<LI>Can be run on JDK 1.2 by adding an XML parser 
<LI>All the components of this distribution are open source software 
<LI>Does not include any of the following optional binaries: JavaMail, Java Activation Framework, Xerces, JNDI, or the JDBC Standard Extension </LI></UL></LI></OL>
<P>There are a number of different download formats. I chose the LE version gnu zipped tar file (jakarta-tomcat-4.1.31-LE-jdk14.tar.gz).</P>
<H3><A name=3_4>3.4 Tomcat Standalone</A></H3>
<P>Unzip Tomcat by issuing the following command from your download directory:</P>
<DIV class=code><PRE>tar xvzf jakarta-tomcat-4.1.31-LE-jdk14.tar.gz
</PRE></DIV>
<P>This will create a directory called jakarta-tomcat-4.1.31. Move this directory to wherever you would like to install Tomcat. I chose /usr/local. Here is the command I issued from inside the download directory:</P>
<DIV class=code><PRE>mv jakarta-tomcat-4.1.31 /usr/local/
</PRE></DIV>
<P>The directory where Tomcat is installed is referred to as CATALINA_HOME in the Tomcat documentation. In this case CATALINA_HOME=/usr/local/jakarta-tomcat-4.1.31.</P>
<P>I recommend setting up a symbolic link to point to your current Tomcat version. This will save you from having to change your startup and shutdown scripts each time you upgrade Tomcat or set a CATALINA_HOME environment variable. It also allows you to keep several versions of Tomcat on your system and easily switch amongst them. Here is the command I issued from inside /usr/local to create a symbolic link called /usr/local/jakarta-tomcat that points to /usr/local/jakarta-tomcat-4.1.31:</P>
<DIV class=code><PRE>ln -s jakarta-tomcat-4.1.31 jakarta-tomcat
</PRE></DIV>
<P>Change the group and owner of the /usr/local/jakarta-tomcat and /usr/local/jakarta-tomcat-4.1.31 directories to tomcat:</P>
<DIV class=code><PRE>chown tomcat.tomcat /usr/local/jakarta-tomcat
chown -R tomcat.tomcat /usr/local/jakarta-tomcat-4.1.31
</PRE></DIV>
<P>It is not necessary to set the CATALINA_HOME environment variable. Tomcat is smart enough to figure out CATALINA_HOME on its own.</P>
<P>You should now be able to start and stop Tomcat from the CATALINA_HOME/bin directory by typing ./startup.sh and ./shutdown.sh respectively. Test that Tomcat is working by starting it and typing http://localhost:8080 into your browser. You should see the Tomcat welcome page with links to documentation and sample code. Verify Tomcat is working by clicking on some of the examples links.</P>
<H2><A name=4_0>4.0 Installing the Connector</A></H2>
<H3><A name=4_1>4.1 Connector Benefits</A></H3>
<P>At this point, Apache and Tomcat should be working separately in standalone mode. You can run Tomcat in standalone mode as an alternative to Apache. In fact, in some cases, it is said that Tomcat standalone is faster than serving static content from Apache and dynamic content from Tomcat. However, there are compelling reasons to use Apache as the front end. If you run Tomcat standalone:</P>
<OL>
<LI>You will have to run Tomcat as root on port 80. This is a security concern. 
<LI>You will not be able to use a connector such as mod_jk to load balance amongst several Tomcat instances. 
<LI>You will not be able to take advantage of Apache features such as cgi and PHP. 
<LI>You will not be able to take advantage of Apache modules such as mod_rewrite. 
<LI>You will not be able to isolate virtual hosts in their own Tomcat instances. </LI></OL>
<P>I think the increased functionality obtained by using Apache on the front end far outweighs the effort required to install and configure a connector.</P>
<H3><A name=4_2>4.2 Selecting a Connector</A></H3>
<P>Development on the mod_jk2 connector was shut down on 11/15/2004; therefore, you no longer have to decide between the mod_jk and mod_jk2 connectors. Use the mod_jk connector. It has been around a long while and is very stable.</P>
<H3><A name=4_3>4.3 Building the mod_jk Connector</A></H3>
<P>The mod_jk connector is the communication link between Apache and Tomcat. It listens on a defined port for requests from Apache.</P>
<P>Download the jk connector source from <A href="http://www.apache.org/dist/jakarta/tomcat-connectors/jk/" target=_blank>http://www.apache.org/dist/jakarta/tomcat-connectors/jk/</A>. I used jakarta-tomcat-connectors-1.2.8-src.tar.gz.</P>
<P>Unzip the contents of the file into your download directory as follows:</P>
<DIV class=code><PRE>tar xvzf jakarta-tomcat-connectors-1.2.8-src.tar.gz
</PRE></DIV>
<P>This will create a folder called jakarta-tomcat-connectors-1.2.8-src. Move this folder to wherever you store source files on your system. I chose /usr/src. Here is the command I issued from inside the download directory:</P>
<DIV class=code><PRE>mv jakarta-tomcat-connectors-1.2.8-src /usr/src
</PRE></DIV>
<P>I refer to the folder where the connector source is installed as CONN_SRC_HOME. In my case CONN_SRC_HOME = /usr/src/jakarta-tomcat-connectors-1.2.8-src.</P>
<P>Run the buildconf script to to create the CONN_SRC_HOME/jk/native/configure file.</P>
<DIV class=code><PRE>CONN_SRC_HOME/jk/native/buildconf.sh
</PRE></DIV>
<P>Run the configure script with the path to the apxs file on your system and the options below:</P>
<DIV class=code><PRE>./configure --with-apxs=/usr/sbin/apxs
</PRE></DIV>
<P>Build mod_jk with the following command:</P>
<DIV class=code><PRE>make
</PRE></DIV>
<P>If you see missing object errors, try this alternate command:</P>
<DIV class=code><PRE>make LIBTOOL=/etc/httpd/build/libtool
</PRE></DIV>
<P>If all went well, the mod_jk.so file was successfully created. Manually copy it to Apache's shared object files directory:</P>
<DIV class=code><PRE>cp CONN_SRC_HOME/jk/native/apache-2.0/mod_jk.so /etc/httpd/modules
</PRE></DIV>
<H2><A name=5_0>5.0 Configuring Tomcat</A></H2>
<H3><A name=5_1>5.1 workers.properties</A></H3>
<P>The workers.properties file contains information so mod_jk can connect to the Tomcat worker processes.</P>
<P>Place the following workers.properties file in the /etc/httpd/conf directory:</P>
<DIV class=code><PRE># workers.properties - ajp13
#
# List workers
worker.list=wrkr
#
# Define wrkr
worker.wrkr.port=8009
worker.wrkr.host=localhost
worker.wrkr.type=ajp13
worker.wrkr.cachesize=10
worker.wrkr.cache_timeout=600
worker.wrkr.socket_timeout=300
</PRE></DIV>
<P>Notes</P>
<OL>
<LI>There is an example workers.properties file located in the CONN_SRC_HOME/jk/conf directory. The example file provides a lot of useful information and insight into the workers.properties file, but it contains so much information that it can be confusing. I recommend using it as a learning tool but creating your own workers.properties file from scratch. 
<LI>The configuration above assumes Apache and Tomcat are located on the same box and requests are forwarded to Tomcat using type ajp13 workers. Type ajp13 workers forward requests to out-of-process Tomcat workers using the ajpv13 protocol over TCP/IP sockets. 
<LI>The name of the worker in the JkMount directive in httpd.conf must match the name of the worker in worker.list ("wrkr" in the configuration above). </LI></OL>
<H3><A name=5_2>5.2 server.xml</A></H3>
<P>The server.xml file contains Tomcat server configuration information. The default CATALINA_HOME/conf/server.xml file that comes with Tomcat contains so much information that I recommend saving it for future reference (e.g. server.xml.bak) and starting from scratch. The default server.xml is great for verifying that Tomcat works in standalone mode and for viewing the examples that come with the application, but I have found it is not the best starting point when you want to integrate Apache with Tomcat. Instead, create a bare bones server.xml file as follows:</P>
<DIV class=code><PRE><SERVER debug="0" shutdown="0fbb9aebcbfbef203eca71b6be367859" port="8005">

	<SERVICE name="Tomcat-Apache">
	
		<CONNECTOR debug="0" port="8009" acceptCount="10" enableLookups="false" maxProcessors="75" minProcessors="5" address="127.0.0.1" className="org.apache.ajp.tomcat4.Ajp13Connector" />
			
		<ENGINE name="<SPAN class=highlight><FONT style=" #ffff00? BACKGROUND-COLOR:>your_engine</FONT></SPAN>" debug="0" defaultHost="<SPAN class=highlight><FONT style="BACKGROUND-COLOR: #ffff00">your_domain</FONT></SPAN>"&gt;
			<LOGGER className="org.apache.catalina.logger.FileLogger" timestamp="true" suffix=".txt" prefix="catalina_log." />
			<HOST name="<SPAN class=highlight><FONT style=" #ffff00? BACKGROUND-COLOR:>your_domain</FONT></SPAN>" debug="0"&gt;
				
				<CONTEXT #ffff00? BACKGROUND-COLOR: docBase="/home/tomcat/<SPAN class=highlight><FONT style=" path="">your_application</FONT></SPAN>" 
				debug="0" reloadable="true" /&gt;
				
			</HOST>
		</ENGINE>

	</SERVICE>

</SERVER>
</PRE></DIV>
<P>This setup assumes you will put your Tomcat applications in /home/tomcat, not CATALINA_HOME/webapps. This will allow you to easily upgrade Tomcat and back up your Tomcat applications.</P>
<P>If you do keep the default server.xml, make sure you comment out any other connectors besides mod_jk that are listening on port 8009. The default file comes with the Coyote/JK2 connector enabled for the Tomcat-Standalone service. This will conflict with the mod_jk connector in your Tomcat-Apache service. You should comment this connector out. It isn't needed when you connect directly to Tomcat in standalone mode (port 8080), so I'm not sure why this connector is enabled by default.</P>
<P>The Server address defines the interface that Tomcat will listen on for mod_jk requests from Apache. In my configuration, Apache and Tomcat reside on the same box, so I have set the address to the loopback address. The default is for Tomcat to listen on all interfaces, so restricting it to the loopback interface improves security.</P>
<P>The Server shutdown property is the text string that is sent over a socket connection to stop Tomcat. The default value is "SHUTDOWN". The shutdown port is always on the loopback interface, which provides host-level protection. However, there is the possibility that the host could be compromised and someone could send the command SHUTDOWN to all ports and knock Tomcat offline. To prevent this, replace the default value with one that is difficult to guess. <STRONG>Do not use the example string above.</STRONG> Create your own by feeding random bytes into md5sum as follows:</P>
<P>Setting the Context reloadable property to true tells Tomcat to automatically load new and changed application class files found in /WEB-INF/classes and /WEB-INF/lib. This feature is very useful during development. However, it is recommended to <STRONG>set reloadable to false in production environments</STRONG> because monitoring class file changes requires significant server resources.</P>
<DIV class=code><PRE>head -1024c /dev/random | md5sum</PRE></DIV>
<P>Change the permissions on server.xml so no one can read the shutdown string:</P>
<DIV class=code><PRE>chmod 600 $CATALINA_HOME/conf/server.xml</PRE></DIV>
<H2><A name=6_0>6.0 Configuring Apache</A></H2>
<P>Apache is configured with directives placed in the main Apache configuration file, /etc/httpd/conf/httpd.conf. In addition, Apache 2 has configuration files for perl, php, and ssl located in /etc/httpd/conf.d/.</> 
<P>Rename the /etc/httpd/conf.d/ssl.conf file to ssl.conf.bak. The default Red Hat Apache 2 installation comes with ssl support enabled. If ssl is needed, you can re-enable it after you have successfully integrated Apache and Tomcat.</P>
<H3><A name=6_1>6.1 httpd.conf</A></H3>
<P>You will notice that there are three sections labeled in the httpd.conf file supplied by Red Hat: (1) Global Environment, (2) Main Server Configuration, and (3) Virtual Hosts.</P>
<P>Add the following to the bottom of the existing LoadModule directives in the Global Environment section:</P>
<DIV class=code><PRE>LoadModule jk_module modules/mod_jk.so
</PRE></DIV>
<P>Add the following to the bottom of the Main Server Configuration section:</P>
<DIV class=code><PRE>JkWorkersFile "/etc/httpd/conf/workers.properties"
JkLogFile "/etc/httpd/logs/mod_jk.log"
JkLogLevel info
JkLogStampFormat "[%a %b %d %H:%M:%S %Y]"
</PRE></DIV>
<P>Set up a Virtual Host directive in the Virtual Hosts section of httpd.conf. Below is an example of how to set up the your_domain website so Tomcat handles all jsp pages and requests with "servlet" in the path:</P>
<DIV class=code><PRE>NameVirtualHost 127.0.0.1:80

<VIRTUALHOST 127.0.0.1:80>
	ServerAdmin webmaster@<SPAN class=highlight><FONT style="BACKGROUND-COLOR: #ffff00">your_domain</FONT></SPAN>
	ServerName <SPAN class=highlight><FONT style="BACKGROUND-COLOR: #ffff00">your_domain</FONT></SPAN>
	DocumentRoot /usr/www/<SPAN class=highlight><FONT style="BACKGROUND-COLOR: #ffff00">your_domain</FONT></SPAN>/html
	ErrorLog /usr/www/<SPAN class=highlight><FONT style="BACKGROUND-COLOR: #ffff00">your_domain</FONT></SPAN>/logs/error_log
	CustomLog /usr/www/<SPAN class=highlight><FONT style="BACKGROUND-COLOR: #ffff00">your_domain</FONT></SPAN>/logs/access_log common
	JkMount /*.jsp wrkr
	JkMount /servlet/* wrkr
	# Deny direct access to WEB-INF
	<LOCATIONMATCH ?.*WEB-INF.*?>
		AllowOverride None
		deny from all
	</LOCATIONMATCH>
</VIRTUALHOST>
</PRE></DIV>
<P>The configuration above assumes that your application's static html files will be served from the /usr/www/your_domain/html directory.</P>
<P>I have deliberately chosen to serve static html files and servlets/jsps from different locations for learning purposes (so there was no confusion over which server is serving which files). Typically, all application files would be located in the same directory tree.</P>
<P>The argument for the NameVirtualHost directive must match exactly the argument for the VirtualHost directive (127.0.0.1:80).</P>
<P>You can test your Apache configuration by typing the following:</P>
<DIV class=code><PRE>httpd -t -D DUMP_VHOSTS
</PRE></DIV>
<P>You should get something like the following response:</P>
<DIV class=code><PRE>127.0.0.1:80           is a NameVirtualHost
         default server your_domain (/etc/httpd/conf/httpd.conf:1056)
         port 80 namevhost your_domain (/etc/httpd/conf/httpd.conf:1056)
Syntax OK
</PRE></DIV>
<H2><A name=7_0>7.0 Setting Up your_domain</A></H2>
<P>your_domain does not need to be a domain name with a DNS entry. For testing purposes, you can set up any domain you want in the /etc/hosts file of the machine that you will be using to access your_application.</P>
<P>The example below shows the entry for your_domain when running Apache and Tomcat on a single machine, typical for a development computer.</P>
<DIV class=code><PRE>127.0.0.1	<SPAN class=highlight><FONT style="BACKGROUND-COLOR: #ffff00">your_domain</FONT></SPAN>
</PRE></DIV>
<H2><A name=8_0>8.0 Testing Apache</A></H2>
<P>We will create and install a simple Hello World html page so we can test to make sure Apache handles requests for static html pages.</P>
<H3><A name=8_1>8.1 Hello World HTML</A></H3>
<P>Copy the following text into a file called HelloWorld.html and install the file in the /usr/www/your_domain/html directory.</P>
<DIV class=code><PRE><HTML>
<HEAD>




<H1>Hello World HTML!</H1>


</PRE></DIV>
<P>If Apache has not been restarted since you added your virtual host, do so as follows:</P>
<DIV class=code><PRE>service httpd restart
</PRE></DIV>
<P>You should now be able to type http://your_domain/HelloWorld.html into your browser and see the always-exciting "Hello World" message.</P>
<H2><A name=9_0>9.0 Testing Tomcat</A></H2>
<P>We will create and install a simple Hello World servlet so we can test to make sure Apache forwards servlet requests to Tomcat for handling.</P>
<H3><A name=9_1>9.1 Hello World JSP</A></H3>
<P>Copy the following into a file called HelloWorld.jsp:</P>
<DIV class=code><PRE><%@ page contentType="text/html;charset=WINDOWS-1252"%>

<HTML>
<HEAD>




<H1><% out.println(" Hello World JSP!"); %></H1>


</PRE></DIV>
<P>Copy the HelloWorld.jsp file to the /home/tomcat/your_application/ directory.</P>
<H3><A name=9_2>9.2 Hello World Servlet</A></H3>
<P>Copy the following into a file called HelloWorld.java:</P>
<DIV class=code><PRE>import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloWorld
    extends HttpServlet {
    public void doGet(HttpServletRequest request, 
                       HttpServletResponse response)
                throws IOException, ServletException {
		
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		
		out.println("Hello World Servlet!");

	}

}
</PRE></DIV>
<P>Compile the source into a class file as follows:</P>
<DIV class=code><PRE>javac -classpath /usr/local/jakarta-tomcat/common/lib/servlet.jar HelloWorld.java
</PRE></DIV>
<P>This will create a file called HelloWorld.class. Copy the HelloWorld.class file to the /home/tomcat/your_application/WEB-INF/classes directory.</P>
<H3><A name=9_3>9.3 Tomcat Application</A></H3>
<P>Create the following directories and files in /home/tomcat/your_application:</P>
<DIV class=code><PRE>/home/tomcat/<SPAN class=highlight><FONT style="BACKGROUND-COLOR: #ffff00">your_application</FONT></SPAN>/WEB-INF
/home/tomcat/<SPAN class=highlight><FONT style="BACKGROUND-COLOR: #ffff00">your_application</FONT></SPAN>/WEB-INF/classes
/home/tomcat/<SPAN class=highlight><FONT style="BACKGROUND-COLOR: #ffff00">your_application</FONT></SPAN>/WEB-INF/web.xml
</PRE></DIV>
<P>The web.xml file is where you map the name of your servlet to a URL pattern so Tomcat can run your servlet when requested. Below is the web.xml file that runs the HelloWorld servlet whenever the URL http://your_domain/servlet/HelloWorld is entered in the browser:</P>
<DIV class=code><PRE><?xml version="1.0" encoding="ISO-8859-1"?>



<WEB-APP>

	<SERVLET>
		<SERVLET-NAME>HelloWorld</SERVLET-NAME>
		<SERVLET-CLASS>HelloWorld</SERVLET-CLASS>
	</SERVLET>
	<SERVLET-MAPPING>
		<SERVLET-NAME>HelloWorld</SERVLET-NAME>
		<URL-PATTERN>/servlet/HelloWorld</URL-PATTERN>
	</SERVLET-MAPPING>
                
</WEB-APP>
</PRE></DIV>
<P>Restart Tomcat as follows:</P>
<DIV class=code><PRE>/CATALINA_HOME/bin/shutdown.sh
/CATALINA_HOME/bin/startup.sh
</PRE></DIV>
<P>Restart Apache as follows:</P>
<DIV class=code><PRE>service httpd restart
</PRE></DIV>
<P>You should now be able to type the following into your browser and see the always-exciting "Hello World" message:<BR>http://your_domain/HelloWorld.jsp<BR>http://your_domain/servlet/HelloWorld</P>
<H2><A name=10_0>10.0 Advanced Configuration</A></H2>
<P>The following steps are not mandatory, but are suggested for a better, tighter Tomcat installation.</P>
<H3><A name=10_1>10.1 Tomcat Startup Script</A></H3>
<P>If you want to automatically start Tomcat when your system boots and manage it using the service command as we do Apache, you must create an initialization script.</P>
<P>Create the following Tomcat initialization script as /etc/rc.d/init.d/tomcat</P>
<DIV class=code><PRE>#!/bin/sh
#
# Startup script for Tomcat, the Apache Servlet Engine
#
# chkconfig: 345 80 20
# description: Tomcat is the Apache Servlet Engine
# processname: tomcat
# pidfile: /var/run/tomcat.pid
#
# Mike Millson <MMILLSON@MERITONLINESYSTEMS.COM>
#
# version 1.02 - Clear work directory on shutdown per John Turner suggestion.
# version 1.01 - Cross between Red Hat Tomcat RPM and Chris Bush scripts

# Tomcat name :)
TOMCAT_PROG=tomcat
 
# if TOMCAT_USER is not set, use tomcat like Apache HTTP server
if [ -z "$TOMCAT_USER" ]; then
 TOMCAT_USER="tomcat"
fi

RETVAL=0

# start and stop functions
start() {
    echo -n "Starting tomcat: "

    chown -R $TOMCAT_USER:$TOMCAT_USER /usr/local/jakarta-tomcat/*    
    chown -R $TOMCAT_USER:$TOMCAT_USER /home/tomcat/*
    su -l $TOMCAT_USER -c '/usr/local/jakarta-tomcat/bin/startup.sh'
    RETVAL=$?
    echo
    [ $RETVAL = 0 ] &amp;&amp; touch /var/lock/subsys/tomcat
    return $RETVAL
}

stop() {
    echo -n "Stopping tomcat: "
    su -l $TOMCAT_USER -c '/usr/local/jakarta-tomcat/bin/shutdown.sh'
    RETVAL=$?
    echo
    [ $RETVAL = 0 ] &amp;&amp; rm -f /var/lock/subsys/tomcat /var/run/tomcat.pid    
    rm -rf /usr/local/jakarta-tomcat/work/*
}

# See how we were called.
case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  restart)
        stop
	# Ugly hack
	# We should really make sure tomcat
	# is stopped before leaving stop
        sleep 2	
        start
        ;;
  *)
	echo "Usage: $0 {start|stop|restart}"
	exit 1
esac

exit $RETVAL
</PRE></DIV>
<P>Add the startup script to your system as follows: </P>
<DIV class=code><PRE>chkconfig --add tomcat
</PRE></DIV>
<P>You will be able to start/stop/restart it using the following commands:</P>
<DIV class=code><PRE>service tomcat start
service tomcat stop
service tomcat restart
</PRE></DIV>
<P>If you want Tomcat to start automatically when your system boots, you need to add tomcat to your runlevel as follows:</P>
<DIV class=code><PRE>chkconfig --level <SPAN class=highlight><FONT style="BACKGROUND-COLOR: #ffff00">5</FONT></SPAN> tomcat on
</PRE></DIV>
<P>Runlevel 5 is the X Window System, typical for a development computer. Runlevel 3 is typical for a dedicated web server.</P>
<P>Apache and Tomcat can be started and restarted in any order. In the past (specifically with the 1.2.5 connector), if Tomcat was restarted, Apache would have to be restarted. This was because the AJP13 protocol maintains open sockets between Apache and Tomcat, and when Tomcat was restarted the connections would be hung in CLOSE_WAIT status until Apache was restarted. This has been fixed starting with the 1.2.6 connector.</P>
<H3><A name=10_2>10.2 Development Setup</A></H3>
<P>During development, you will need access to your tomcat application directory. Add the user account under which you will be doing development to the tomcat group in /etc/group. For example, this is what the tomcat entry might look like in /etc/group if you do development under the <SPAN class=cmd><FONT face="Courier New">yourname</FONT></SPAN> account:</P>
<DIV class=code><PRE>tomcat:x:502:yourname
</PRE></DIV>
<P>Make sure the tomcat group has permission to publish files (e.g. using ant) to your Tomcat application in /home/tomcat/your_application. Issue the following command as root:</P>
<DIV class=code><PRE>chmod g+rw /home/tomcat
</PRE></DIV>
<H2><A name=11_0>11.0 Troubleshooting</A></H2>
<H3><A name=11_1>11.1 Log Files To Watch</A></H3>
<H4>/usr/www/<SPAN class=highlight><FONT style="BACKGROUND-COLOR: #ffff00">your_domain</FONT></SPAN>/logs/error_log</H4>
<P>Look here for clues to Apache httpd.conf configuration issues, for example VirtualHost setup.</P>
<H4>$CATALINA_HOME/logs/catalina.out</H4>
<P>Look here for clues to Tomcat server.xml configuration issues. This file is written to when Tomcat starts and stops. It also catches System.out and System.err.</P>
<H4>$CATALINA_HOME/logs/mod_jk.log</H4>
<P>Look here for clues to mod_jk configuration issues.</P>
<H3><A name=11_2>11.2 Monitoring Connections</A></H3>
<P>The following command can be used to monitor the Apache, Tomcat, and mod_jk connections:</P>
<DIV class=code><PRE>netstat -vatn | grep 80
</PRE></DIV>
<P>Below is output from running this command. Line numbers have been added to the beginning of each line for discussion purposes.</P>
<DIV class=code><PRE>1 tcp        0      0 127.0.0.1:8005          0.0.0.0:*               LISTEN
2 tcp        0      0 127.0.0.1:8009          0.0.0.0:*               LISTEN
3 tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN
4 tcp        0      0 127.0.0.1:8009          127.0.0.1:34449         ESTABLISHED
5 tcp        0      0 127.0.0.1:34449         127.0.0.1:8009          ESTABLISHED
</PRE></DIV>
<P>Notes</P>
<OL>
<LI>Line 1 shows Tomcat listening on port 8005 for the shutdown command. 
<LI>Line 2 shows Tomcat listening on port 8009 for requests from Apache. 
<LI>Line 3 shows Apache listening on port 80 for user requests. 
<LI>Line 4 shows the Tomcat end of a mod_jk connection. 
<LI>Line 5 shows the Apache end of a mod_jk connection. </LI></OL><img src ="http://www.blogjava.net/nighTuner/aggbug/3199.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/nighTuner/" target="_blank">nighTuner</a> 2005-04-13 00:20 <a href="http://www.blogjava.net/nighTuner/articles/3199.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>