zzz 的个人资料Magic 's Forest , ...照片日志列表更多 工具 帮助

日志


11月26日

NTP配置

NTP客户端

 

> service ntpd stop

> ntpdate {服务器IP}
3遍

>crond –e
    0-59/10 * * * * /usr/sbin/ntpdate {IP}

每隔10分钟同步一次时间

 

================

 

NTP服务端

    ntp-4.2.2p1-9.el5.centos.2.i386

 

> vi /etc/ntp.conf

  restrict 10.0.10.0 mask 255.255.255.0 nomodify notrap  #允许client端
  server cn.pool.ntp.org    #与国际NTP server同步时间

>service ntpd restart

 

~~~~~~~~~~~~~~~~

 

一些可以用的NTP服务器

cn.pool.ntp.org
ntp.sjtu.edu.cn (上海交通大学网络中心NTP服务器地址)202.120.2.101

133.100.11.8 prefer
210.72.145.44
203.117.180.36
131.107.1.10
time.asia.apple.com
64.236.96.53
130.149.17.21
66.92.68.246
www.freebsd.org
18.145.0.30
clock.via.net
137.92.140.80
133.100.9.2
128.118.46.3
ntp.nasa.gov

Memcached

wget http://www.monkey.org/~provos/libevent-1.4.13-stable.tar.gz

有可能还要libevent-devel的包

wget http://memcached.googlecode.com/files/memcached-1.4.3.tar.gz

 

memcached有用到libevent包,所以要先装下。

编译都没什么花头,

./configure && make && make install

默认是安装到/usr/local/bin下面

 

自己做个启动脚本

 

start() {
        /usr/local/bin/memcached -p 11211 -m 128m -d -u memcached -P /tmp/memcached.pid > /var/log/memcached.log &
}

stop() {
        kill -9 `cat /tmp/memcached.pid`

 

启动脚本里面如果要调试信息就加一个 –vv 的参数。

 

-p    端口11211

-m   使用的缓存大小

-d    作为后台运行

-u    指定用户,由于不能用root启动 所以要adduser

-P    记录下pid,给stop用

-vv  详细信息显示

基本的 service 脚本

#!/bin/sh

RETVAL=0

start() {
        service memcached start
        ~/xxx/user.sh
        ~/xxx/server.sh
}

stop() {
       ~/xxx/server_stop.sh
        service memcached stop
}

restart() {
        stop
        start
}
# See how we were called.
case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;

  restart|reload)
        restart
        ;;

  *)
        echo $"Usage: xxx {start|stop|restart}"
        exit 1
esac

exit $RETVAL

 

这是一个最基本的service脚本 只要把要做的事情放到start和stop函数里面去就OK了。

更完善一点么就把路径什么的做成变量,做一些判断。

Java Installer Builder

这2天做掉一个大项目,忙的这是~ 今天似乎没什么后续的任务 大概比计划完成的提早了吧 呵呵

领导们在开会,那就抓紧时间写点小结吧~

先从小的项目开始

 

 

Java Installer Builder

 

打包程序,还蛮好玩的~

   就是制作安装程序的程序,我们以前装的游戏啊、程序啊 原来都是这么打包出来的,蛮好玩的~呵呵

 

用到的工具,Install4j,破解版下载地址

http://down1.3ddown.com//Crack/2009/05/EJ.Technologies.Install4j.MultiPlatform.Edition.v4.2.2.Incl.Keygen-FALLEN.rar

这个东东破解竟然还用到java代码,crack目录下面有个keygen.class 拷到安装路径

运行java keygen 就会有注册码出来了

我用的是这个

L-FLN#77002-1sx2e2c1spj1zb#325

 

………………………………………………

 

其实只要跟着一路next就ok了,不过在实际操作过程中还是有碰到些问题。

 

 

   第一页 General Settings

      这个是安装程序的名字,起的体面一点比较好。全小写的难看

      Java版本,如果后面选择打包里面自带Java,就无所谓了。

      安装过程用的Language,第一个是默认,下面可以增加多选,记得不要把默认的选进去

           每个语言的文档其实都在${install4j}\resource\messages路径下面

           可以把里面的install4j替换成想要的文字

      打包好的安装程序放置的路径,下面还有默认生成文件名的格式、压缩方式、timestamp等

      项目变量的设置 ~应该一般用不到吧。。

 

 

   第二页 Files

      要打包的文件夹,Add Files 然后选上整个目录

      预览一下 readonly~

      指定要打包进去的文件 当然全选的话就不用改了

 

 

   第三页 Launchers

 

      New Launcher->

         我是用Generated Launcher的

           执行安装的方式,其中有可以把这个程序做成Service的选项

             输入执行程序的名字 这里就可以用一般文件名的格式了~还有设置执行的目录等。

             下面有个Advanced Options,有一些细节的东西可以设置,

               比如安装日志、服务启动的方式、Dependency等

 

         icon

            选择图标 要准备2个,16*16的和32*32的。大小不符合它会用自带那个,狠难看~

 

        Java invocation

           这个是最麻烦的地方了

           先选Class Path,把根目录选进去。

              然后记得把Main class要用到的Jar文件指定添加进去,指定目录的话是不会自动搜索的~

           然后选程序的Main class 下面可以填它的Parameters

           下面有个Advanced Options,如果有的话 记得还要把Native Library Directory选进去

 

        splash screen

           启动程序时用的画面,就是那种刚启动时,屏幕中间会出来一段版权所有的这种半透明淡入淡出的图片

 

 

    第四页 Installer

        这个是安装过程的每个页面设置。

          看是很多,其实仔细研究了一下基本没什么地方可以改动的,直接next好了

        Custom Code,JAR文件的自定义代码

        Application ID,Update用的

        GUI 的一些选项 比如窗口大小、标题栏之类的

          下面竟然有个 add install4j watermark to installer screens 的多选项。。记得去掉~

          Installer Icon也可以自定义

         Advanced里面有用console方式安装的后门参数等设置

 

 

   第五页 Media

        选For Windows还是For Mac、Unix/Linux 的

          或者下面的archive 可以打包安装的那种,不用图形化。

        安装路径 先勾上custom installation base directory的选项 后面填入C:\program File或者D:\之类的

                    上面填后续的程序目录名

        中间没有什么 一直到第6部分 Bundled JRE

          可以把JRE的包打在安装程序里,省的客户端没有安装环境什么的还要自己去找

            先下载 然后就可以在选项里面选择了。

        最后有个全面自定义的地方 几乎什么都可以再改一下。

 

 

    第六页 Bulid

        好,OK了 在这里Start就可以了。要看过程么可以把Enable extra verbose output勾出来看一看

             Test Build貌似没什么用 还特费时间 不做也罢。

11月18日

Apache停止和重启(转)


 

本文档叙述了在类Unix系统上如何停止和重启Apache 。 Windows NT/2000/XP/2003的用户请参见以服务方式运行Apache ,Windows 9x/ME用户则参见在控制台中运行Apache

top

简介

为了停止或者重新启动Apache ,你必须向正在运行的httpd进程发送信号。有两种发送信号的方法。第一种方法是直接使用UNIX的kill命令向运行中的进程发送信号。你也许你会注意到你的系统里运行着很多httpd进程。但你不应该直接对它们中的任何一个发送信号,而只要对已经在PidFile中记载下了自身PID的父进程发送信号。也就是说,你不必对父进程以外的任何进程发送信号。你可以向父进程发送三种信号:TERMHUPUSR1 ,我们过一会儿再进行详细的说明。

你可以用下面这样的命令来向父进程发送信号:

kill -TERM `cat /usr/local/apache2/logs/httpd.pid`

第二种方法是使用下面将要描述的httpd二进制可执行文件的 -k 命令行选项:stoprestartgracefulgraceful-stop 。不过我们推荐你使用apachectl控制脚本来向httpd二进制可执行文件传递这些选项。

当你向httpd发送信号后,你可以这样来读取它的进行过程:

tail -f /usr/local/apache2/logs/error_log

你可以修改这些示例以适应你的ServerRootPidFile设置。

 

立即停止

信号:TERM
apachectl -k stop

发送TERMstop信号到父进程可以使它立刻杀死所有子进程。这将花费一些时间来杀死所有子进程。然后父进程自己也退出。所有进行中的请求将被强行中止,而且不再接受其它请求。

 

优雅重启

信号:USR1
apachectl -k graceful

USR1graceful信号使得父进程建议子进程在完成它们现在的请求后退出(如果他们没有进行服务,将会立刻退出)。父进程重新读入配置文件并重新打开日志文件。每当一个子进程死掉,父进程立刻用新的配置文件产生一个新的子进程并立刻开始伺服新的请求。

重启代码的设计能够确保MPM进程控制指令的正常运作,也就是在重启过程中确保有适当数量的进程和线程以响应客户端的请求。它是这样StartServers的:如果在一秒钟以后还没有新创建StartServers个子进程,则创建出足够完成现在任务的子进程个数。因此,代码除了保有能够维持服务器的现有负载数量的子进程外,也确保StartServers按你的意愿运作。

使用mod_status的用户会注意到在USR1信号发出后,服务器的统计信息没有被清零。代码被写成既能将你服务器无法伺服新请求的时间降至最少(这些请求将被操作系统放到队列里,使得它们不会丢失),又能遵从你的参数优化。为了做到这一点,它将在重新生成子进程的过程中,在scoreboard上保存所有子进程的状态。

mod_status还会将那些在优雅重启前就已经开始而没有结束伺服请求的子进程用一个"G"来标志。

目前,日志滚动脚本还无法使用USR1来确定所有写入预重启日志的子进程都已结束。我们建议你在发出了USR1信号后等待一个适当的时间,然后再对旧的日志做处理。比如说如果对于一个窄带用户来说,大部分的点击处理将在10分钟之内完成,那么你应该在处理旧的日志前等待15分钟。

如果Apache重启时发现配置文件有误,那么父进程将不会重启,而是报错并退出。在优雅重启的情况下,它将在处理中的子进程存在的情况下维持它的存在(就是那些被要求在处理完它们的请求后"优雅退出"的子进程)。如果你要重启服务器,这将导致一些问题:它将不能绑定到它的监听端口。在执行重启之前,你可以用 -t 命令行参数来检查配置文件语法的正确性(参见httpd)。但这仍然不能保证服务器一定可以正确的重启。为了从语法和语义两方面检查配置文件,你可以用一个非root用户来启动httpd。如果没有错误,它将尝试去打开套接字和日志文件,继而因没有root权限而失败(或是因为现在运行的httpd已经绑定了这些端口)。如果是因为其他原因那么就可能是一个配置文件产生的错误,你就应当在进行优雅重启之前改正这个错误。

 

立即重启

信号:HUP
apachectl -k restart

向父进程发送HUPrestart信号会使它象收到TERM信号一样杀掉所有的子进程,不同之处在于父进程本身并不退出。它重新读入配置文件、重新打开日志文件。然后产生一系列新的子进程来继续服务。

使用mod_status的用户会注意到在HUP信号发出后,服务器统计信息会被清零。

如果你重启时配置文件有误,那么父进程将不会重启,而是报错并退出。参见上文中避免的方法。

 

优雅停止

信号:WINCH
apachectl -k graceful-stop

WINCHgraceful-stop信号使得父进程建议子进程在完成它们现在的请求后退出(如果他们没有进行服务,将会立刻退出)。然后父进程删除PidFile并停止在所有端口上的监听。父进程仍然继续运行并监视正在处理请求的子进程,一旦所有子进程完成任务并退出或者超过由GracefulShutdownTimeout指令规定的时间,父进程将会退出。在超时的情况下,所有子进程都将接收到TERM信号并被强制退出。

在"优雅"状态下,TERM信号将会立即中止父进程和所有子进程。由于PidFile已经被删除,你将无法使用apachectlhttpd发送该信号。

graceful-stop允许你同时运行多个相同配置的httpd实例。这在对Apache进行平滑升级的时候是一个非常有用的特性。不过它在某些配置的情况下同样可能会导致死锁和竞争条件。

必须注意确保诸如LockfileScriptSock之类的磁盘文件包含服务器的PID ,并且能够安全的共存。然而如果一个配置指令、第三方模块或持久CGI使用任何磁盘锁或状态文件,必须注意确保多个httpd运行实例之间不会争抢文件。

你还必须防止潜在的竞争条件,比如使用rotatelogs风格的管道日志。运行中的多个rotatelogs实例企图同时滚动同一个日志文件可能会导致互相破坏对方的日志文件。

 

附录:信号和竞争条件

在Apache 1.2b9 之前,有很多关于重启和死亡信号的竞争条件。关于竞争条件的一个简单描述是:一个时间敏感的问题,如果一些事情在不适当的时间或以不恰当的顺序发生,它将作出你不期望的反应;如果同样的事情在恰当的时间发生,则不会出现异常。凭借那些拥有"正确"特性设置的体系结构,我们尽量避免了它们的出现。但值得注意的是,仍然有一些竞争条件存在于这样的体系结构中。

使用物理磁盘的ScoreBoardFile就有损坏ScoreBoard的潜在危险。这将发生在"bind: Address already in use"(HUP之后)或"long lost child came home!"(USR1之后)时。前者是一个致命错误,而后者则会使服务器丢失ScoreBoard的一个记录。所以我们建议多使用优雅重启,偶尔使用硬重启。这些问题很难解决,但幸运的是大多数结构并不需要ScoreBoard文件。而如果你需要这样的结构,你可以参考ScoreBoardFile文档。

当每个子进程在一个HTTP的持续连接(KeepAlive)中涉及到第二个并发的请求时,所有的结构都会或多或少存在竞争状态的问题。它将在读取了请求而没有读取任何请求头之后立刻退出。这个修复对于1.2来说来得太晚了。但因为持续连接的客户端已经考虑到网络延时和服务器超时会造成类似的情况,所以理论上说,这不是一个太大的问题。而实际上似乎也没有任何影响:在一个测试案例中服务器在一秒之内被重启了20次,而客户端却成功的浏览了网站,而且没有任何破损的图片或空文档。

11月16日

evasive limitipconn bandwidth 模块 (apache安全性,转)

 

mod_evasive防DDoS攻击

  为了防止Web服务器被DDoS攻击,我们需要安装mod_evasive这个防DDoS的模块

mod_evasive 1.10.x防DDoS模块的下载与安装
下载地址:http://www.zdziarski.com/projects/mod_evasive/

解压后进入解压目录,执行
/home/apache/bin/apxs -cia mod_evasive20.c

编译完成后,/home/apache/modules下会生成一个mod_evasive20.so文件

然后kate /home/apache/conf/httpd.conf
加入以下选项(如果没有的话)

#启用mod_evasive for Apache 2.x防DDoS模块
LoadModule evasive20_module modules/mod_evasive20.so (这一句通常会被自动加入)

<IfModule mod_evasive20.c>
#记录和存放黑名单的哈西表大小,如果服务器访问量很大,可以加大该值
DOSHashTableSize 3097
#同一个页面在同一时间内可以被统一个用户访问的次数,超过该数字就会被列为攻击,同一时间的数值可以在DosPageInterval参数中设置。
DOSPageCount 3
#同一个用户在同一个网站内可以同时打开的访问数,同一个时间的数值在DOSSiteInterval中设置。
DOSSiteCount 40
#设置DOSPageCount中时间长度标准,默认值为1。
DOSPageInterval 2
#DOSSiteInterval 2 设置DOSSiteCount中时间长度标准,默认值为1。
DOSSiteInterval 2
#被封时间间隔秒,这中间会收到 403 (Forbidden) 的返回。
DOSBlockingPeriod 10
#设置受到攻击时接收攻击信息提示的邮箱地址。
#DOSEmailNotify you@yourdomain.com
#受到攻击时Apache运行用户执行的系统命令
#DOSSystemCommand “su - someuser -c ‘/sbin/… %s …’”
#攻击日志存放目录,BSD上默认是 /tmp
#DOSLogDir “/var/lock/mod_evasive”
</IfModule>

 

 

mod_limitipconn限制Apache的并发连接数

  mod_limitipconn可以控制每个IP地址同时连接服务器某一个目录的并发连接数,是一个非常有用的模块,其官方网页是http: //dominia.org/djao/limitipconn.html,最新版本为for Apache 1.3.7的0.04,并且还有支持Apache 2.x的模块下载,由于本人使用Apache 1.3.7版本,所以请使用2.x版本Apache的朋友到其官方网站察看具体的使用方法。

  mod_limitipconn for Apache 1.3x提供三种安装方式,分别是tar包、rpm安装文件和rpm源文件,由于rpm包只能用在 RedHat 7.x 版本,并且不支持检测代理服务器,所以我们一般都使用tar包的安装方式。

  以管理员方式登陆服务器,然后在服务器上运行 wget http://dominia.org/djao/limit/mod_limitipconn-0.04.tar.gz 将mod_limitipconn的tar包下载到服务器,然后按照再运行tar zxvf mod_limitipconn-0.04.tar.gz将tar包解压缩,会在当前目录下生成mod_limitipconn-0.04目录,然后cd mod_limitipconn-0.04进入此目录,下一步就是使用apxs将目录中的mod_limitipconn.c编译。这时,我们需要确定自己的Apache安装在那个目录,并且找到apxs命令放在哪里。

  通过命令whereis apxs,我们可以确定apxs命令的路径,如我的apxs命令所在为/usr/sbin/apxs,则输入/usr/sbin/apxs -c -i -a mod_limitipconn.c对mod_limitipconn.c进行编译,此命令会自动在你Apache的配置文件httpd.conf中加入需要的信息,并且将生成的mod_limitipconn.so模块拷贝到Apache的模块目录。不过为了确认此命令是否正常运作,请首先检查自己的 Apache模块目录(我的是/usr/lib/apache),看内部是否含有mod_limitipconn.so文件,没有的话请将 mod_limitipconn-0.04目录中生成的文件拷贝到此处。

  刚才命令自动生成的httpd.conf可能有些错误,在我的系统中,它将LoadModule limitipconn_module modules/mod_limitipconn.so放在了

<IfDefine HAVE_PYTHON>
LoadModule python_module modules/mod_python.so
</IfDefine>
之间,而将AddModule mod_limitipconn.c放在了

<IfDefine HAVE_PYTHON>
AddModule mod_python.c
</IfDefine>
之间,直接造成了mod_limitipconn模块不能正常运行,所以请将这两行分别移动到没有<IfDefine>< /IfDefine>的相应行中,然后请确认mod_status模块已经加载,并且在mod_status下添加了ExtendedStatus On这一行。这时我们的mod_limitipconn模块就安装完毕,下一步就是对某个目录进行并发连接数的设置了。

  mod_limitipconn可以对全局和虚拟主机进行不同的限制,其语法结构都是

<IfModule mod_limitipconn.c>
<Location /> #所限制的目录所在,此处表示主机的根目录
MaxConnPerIP 3 #所限制的每个IP并发连接数为3个
NoIPLimit image/* #对图片不做IP限制
</Location>
<Location /mp3> #所限制的目录所在,此处表示主机的/mp3目录
MaxConnPerIP 1 #所限制的每个IP并发连接数为1个
OnlyIPLimit audio/mpeg video #该限制只对视频和音频格式的文件
</Location>
</IfModule>


  当对全局进行限制时,将这段代码放在httpd.conf文件没有VirtualHost的地方,若是对某个虚拟主机进行限制,请将其放在 <VirtualHost xxx.xxx.xxx.xxx>和</VirtualHost>之间,我们可以通过更改Location以及 MaxConnPerIP方便的控制所限制的目录和并发连接数。

  最后,只要重新启动Apache服务,并发连接数的限制就可以生效。

 

 

mod_bandwidth控制Apache的带宽

  Apache 1.3.7实际上带有mod_bandwidth支持,只是没有此模块的so文件,我们所做的就是下载mod_bandwidth的源文件进行编译,并对mod_bandwidth进行相应的设置。

  在下载之前,请先确认自己的Apache配置文件httpd.conf中是否含有

<IfDefine HAVE_BANDWIDTH>
LoadModule bandwidth_module modules/mod_bandwidth.so
</IfDefine>


以及

<IfDefine HAVE_BANDWIDTH>
AddModule mod_bandwidth.c
</IfDefine>


若是没有,请加上

LoadModule bandwidth_module
libexec/apache/mod_bandwidth.so
AddModule mod_bandwidth.c


  并且这两行必须分别加在相应区域的最前面,使得这个模块以最低的优先级运行。(不过1.3.7的Apache应该有,呵呵)。

 

  确认后,请输入 wget ftp://ftp.cohprog.com/pub/apache/module/1.3.0/mod_bandwidth.c 将源文件下载到服务器,然后请使用apxs对其进行编译,编译方法和mod_limitipconn的基本相同,如我输入/usr/sbin/apxs -c mod_bandwidth.c -o /usr/lib/apache(Apache的模块目录),编译程序会自动将编译成功的mod_bandwidth.so文件放到Apache的模块目录,您也可以自己确认一下,若是不正常,拷贝过去即可。

 

  mod_bandwidth运行时需要一些特定的目录,按照默认情况,请运行以下命令创建并更改目录的权限:

mkdir /tmp/apachebw
mkdir /tmp/apachebw/link
mkdir /tmp/apachebw/master
chmod -R 777 /tmp/apachebw


  然后再打开httpd.conf文件,加上以下内容

<IfModule mod_bandwidth.c>
BandWidthDataDir "/tmp/apachebw/"
BandWidthModule on
</IfModule>


  这时,我们就能够对所需要限制带宽的目录进行相应的设置,此处的目录请使用服务器的绝对路径。如我们想限制服务器 /home/www/thinkjam/download/soft目录的下载速度,也就是限制网址http: //download.thinkjam.org/soft目录下软件的下载速度,则为httpd.conf文件增加以下内容

<Directory /home/www/thinkjam/download/soft>
BandWidth thinkjam.org 0 #来自thinkjam.org的下载不受速度限制
BandWidth 210.51.21 0 #来自210.51.21网段的下载不受速度限制
BandWidth all 327680 #来自其它网段的速度都限制为327680Byte,即30KB/s
</Directory>


  设置完毕后,重新启动Apache服务,即可生效。

  mod_bandwidth还有许多其它有用的参数,如在中间加上MaxConnection 120则可以限制某个目录的最多连接数,当超过指定连接数时,拒绝新的连接,此参数与mod_limitipconn模块结合可以控制某个目录的最多连接人数。

  其它的参数请朋友们到其官方网站 http://www.cohprog.com/v3/bandwidth/doc-en.html 察看相关的文档。

  Apache的功能确实强大,很多功能都可以通过添加模块来实现,在 http://modules.apache.org/ 可以找到更多的模块,我们也可以编写自己的模块来实现相应的功能。

11月13日

单服务器多Mysql服务配置

之前弄完了主从数据库的配置,考虑到每一台主服务器要一台从服务器好像有点夸张

于是接着准备在一台从服务器上备份多台服务器的工作。

 

$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

 

Mysql确实提供了这样的命令 mysqld_multi

 

~   ~   ~   ~   ~

 

不过执行这个脚本的时候会调用几个其他mysql的脚本,所以先要把mysql/bin路径做到PATH变量里面

# vi ~/.bash_profile

     path=$path:/usr/local/mysql/bin

 

~   ~   ~   ~   ~

 

接着就是最重要的my.cnf配置,出错了很久,基本就是这里面配置的不对。

   我把现在配好的配置贴在这里~

 

[client]
#password    = your_password
#port        = 3306
#socket        = /tmp/mysql.sock

[mysqld1]
port        = 3306
socket        = /tmp/mysql.sock

pid-file=/opt/data/proxy.pid
datadir = /opt/data/
user = mysql

#log-slow-queries=/usr/local/mysql/data2/slowquery.log
#long_query_time = 10
skip-locking
key_buffer = 256M
max_allowed_packet = 1M
table_cache = 256
sort_buffer_size = 1M
read_buffer_size = 1M
read_rnd_buffer_size = 4M
myisam_sort_buffer_size = 64M
thread_cache_size = 8
query_cache_size= 16M
thread_concurrency = 8
log-bin=mysql-bin
server-id    = 10
replicate-do-db=222222

[mysqld2]
port = 3307
socket = /tmp/mysql.sock2
pid-file = /opt/222.22.2.185/185.pid
datadir = /opt/222.22.2.185/

#log=/usr/local/mysql/data2/net-app1.log
user = mysql
#log-slow-queries=/usr/local/mysql/data2/slowquery.log
#long_query_time = 10
key_buffer = 128M
max_allowed_packet = 1M
table_cache = 512
sort_buffer_size = 1M
read_buffer_size = 1M
myisam_sort_buffer_size = 32M
thread_cache = 32
query_cache_size = 16M
thread_concurrency = 2
max_connections=300
log-bin
log-bin=/opt/222.22.2.185/185-bin
server-id       = 10

replicate-do-db=22222

[mysqldump]
quick
max_allowed_packet = 16M

[mysql]
no-auto-rehash
# Remove the next comment character if you are not familiar with SQL
#safe-updates

[isamchk]
key_buffer = 128M
sort_buffer_size = 128M
read_buffer = 2M
write_buffer = 2M

[myisamchk]
key_buffer = 128M
sort_buffer_size = 128M
read_buffer = 2M
write_buffer = 2M

[mysqlhotcopy]
interactive-timeout

 

multi脚本是看my.cnf里面的[mysqldX] 下面的配置,所以这个配置名一定要改成相应。

 

加粗的几个文档路径是一定要配的,其余的比如relay-log之类的倒不是必要。而且要给予相应的权限,

这个配置已经做好了slave的从数据库命令,不过change master命令还是一定要登上去做的

 

接着初始化数据库,直接拉一个过来也可以。反正就和之前没有什么区别了。

 

好了,把脚本起一下

# /usr/local/mysq/bin/mysqld_multi   --config-file=/etc/my.cnf [start|stop|report] 1-X

 

接着登陆

# mysql -p -P3307 -uroot –h192.168.2.2

 

这里有一个问题,如果-h参数用localhost的话是登陆到3306端口的,即使是-P指定了也不行 这点现在也没有搞懂

     要注意的是现在登陆的是root@192.168.2.2的账号 和root@localhost账号权限是有区别的噢

 

登上去之后就和之前主从服务器一样操作了,结果就是一台服务器上起了多个mysql服务了咯。

 

~   ~   ~   ~

最后我们把几个服务都做到启动项里去

    # vi /etc/rc.local

/usr/local/mysql/bin/mysqld_multi   --config-file=/etc/my.cnf start 1-2 &
/usr/local/bin/mysql-proxy.sh &

 

 

OK了。

 

 

 

9

11月11日

Apache性能优化技巧

 

升级 Apache 到最新版本,新版本往往包含性能提升和安全更新。

在 httpd.conf 中设置 "HostNameLookups off" 能避免针对每个访问者的 DNS 域名的反向查询。

对于繁忙的网站,在 httpd.conf 中设置 "MaxClients 230" 或者更高。这项设置让更多的 httpd 进程同时响应请求,并避免了处理器排队的情况发生。

采用另外一台服务器处理图片文件。

缺保您的 Web 页面和 CGI 页面采用了浏览器缓冲技术。具体的文章可以参考本站:采用 mod_gzip 加速 Zope 和 Apache

保持您的 Apache 苗条,编译那些仅仅需要的模块,在编译之前,修改 src/Configuration 文件,在那些不需要的模块之前用 # 号注释掉。

如果不需要流量日志,那么把 httpd.conf 中的 TransferLog 指向到 /dev/null/

除非你确定使用 .htaccess 文件来控制一些目录的权限,否则设置 "AllowOverride None" ,这样就免去 Apache 在每个目录搜索 .htaccess 文件的劳役之苦。

不要让不需要的后台进程运行。

千万不要把页面或者日志文件写到网络磁盘上,例如 NFS。

不要让 Apache (httpd) 运行于 inetd 模式。

不要让 X Windows 运行在你的 Web 服务器上,用 Ctrl-Alt-Backspace 关闭 X 。

避免使用 SSI tag。

在 CGI 脚本中:

文件 I/O:打开的文件数目越少越好。
Shell 命令:采用全路径来调用 shell 命令。
如果你的网站主要以 CGI 来驱动,那么请使用 mod_perl。
在你的 Web 页面目录中,不要让文件数超过 1000 个,文件越多花费在定位上的时间也越多。

在 Web 服务器上的图片越少越好,保证每个图片都经由图片压缩器运行。

对你的网站做压力测试,建议采用 Apache 自带的 ab 命令来测试。

为了最好的性能,最好把网线拔掉,这样你的 Web 服务器就十分安全,而且负载马上降为 0,

Apache优化管理(另一篇,还是有些区别,转)

版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明
http://www.chedong.com/tech/apache_install.html

 

     Apache是一个历史悠久并且功能十分强大的WEB服务器,但其丰富的功能对于一个新手来说往往不知道从何下手。我个人感觉Apache的设计充分体现了模块化设计的优势,通过在动态模块加载(DSO)模式下的安装,任何子应用模块都可以通过配置文件的简单修改进行积木式的灵活配置。安装的过程可以从简单的静态html服务开始,一个模块一个模块的学习使用。从单纯的HTML静态服务(core),到复杂的动态页面服务(core + php, core + resin, core + php + mod_gzip, core + resin + mod_expire)。

     本文主要从简化安装==>性能调优==>维护方便的角度,介绍了WEB服务的规划、HTTPD安装/应用模块配置、升级/维护等过程。让Apache和PHP,Resin等应用模块的独立升级,完全互不影响。

  1. WEB应用容量规划:根据硬件配置和WEB应用的特点进行WEB服务的规划及一些简单的估算公式;
  2. Apache安装过程:apache的通用的简化安装选项,方便以后的应用的模块化配置;
    修改 HARD_SERVER_LIMIT:
    vi /path/to/apache_src/src/include/httpd.h
    #define HARD_SERVER_LIMIT 2560 <===将原来的 HARD_SERVER_LIMIT 256 后面加个“0”
    apache编译:
    ./configure --prefix=/home/apache --enable-shared=max --enable-module=most
  3. 可选应用模块/工具的安装:php resin mod_gzip mod_expire及各个模块之间的配合;
    mod_php安装:./configure --with-apxs=/home/apache/bin/apxs --enable-track-vars --with-mysql
    mod_resin安装:./configure --with-apxs=/home/apache/bin/apxs
    mod_gzip安装:修改Makefile中的 apxs路径:然后make make install
    工具:日志轮循工具cronolog安装:http://www.cronolog.org
  4. 升级/维护:看看通用和模块化的安装过程如何简化了日常的升级/维护工作;
    按照以上的方法:系统管理员和应用管理员的职责可以清楚的分开,互相独立。
    系统安装:系统管理员的职责就是安装好一台DSO模式的Apache,然后COLON即可,
    应用安装:由应用管理员负责具体应用所需要的模块,比如PHP Resin等,并设置httpd.conf中相关的配置。
    系统升级:系统管理员:升级操作系统/升级Apache
    应用升级:应用管理员:升级应用模块,PHP Resin等。

 

WEB应用的容量规划

     Apache主要是一个内存消耗型的服务应用,我个人总结的经验公式:
apache_max_process_with_good_perfermance < (total_hardware_memory / apache_memory_per_process ) * 2
apache_max_process = apache_max_process_with_good_perfermance * 1.5

     为什么会有一个apache_max_process_with_good_perfermance和apache_max_process呢?原因是在低负载下系统可以使用更多的内存用于文件系统的缓存,从而进一步提高单个请求的响应速度。在高负载下,系统的单个请求响应速度会慢不少,而超过 apache_max_process,系统会因为开始使用硬盘做虚拟内存交换空间而导致系统效率急剧下降。此外,同样的服务:2G内存的机器的 apache_max_process一般只设置到1G内存的1.7倍,因为Apache本身会因为进程过多导致性能下降。

例子1:
一个apache + mod_php的服务器:一个apache进程一般需要4M内存
因此在一个1G内存的机器上:apache_max_process_with_good_perfermance < (1g / 4m) * 2 = 500
apache_max_process = 500 * 1.5 = 750
所以规划你的应用让服务尽量跑在500个进程以下以保持比较高的效率,并设置Apache的软上限在800个。

例子2:
一个apache + mod_resin的服务器: 一个apache进程一般需要2M内存
在一个2G内存的机器上:
apache_max_process_with_good_perfermance < (2g / 2m ) * 2 = 2000
apache_max_process = 2000 * 1.5 = 3000

     以上估算都是按小文件服务估算的(一个请求一般大小在20k以下)。对于文件下载类型站点,可能还会受其他因素:比如带宽等的影响。

 

Apache安装过程

     服务器个数的硬上限HARD_SERVER_LIMIT的修改:

在Apache的源代码中缺省的最大进程数是256个,需要修改apache_1.3.xx/src/include/httpd.h
#ifndef HARD_SERVER_LIMIT
#ifdef WIN32
#define HARD_SERVER_LIMIT 1024
#elif defined(NETWARE)
#define HARD_SERVER_LIMIT 2048
#else
#define HARD_SERVER_LIMIT 2560 <===将原来的HARD_SERVER_LIMIT 256 后面加个“0”
#endif
#endif

     解释:
     Apache缺省的最大用户数是256个:这个配置对于服务器内存还是256M左右的时代是一个非常好的缺省设置,但随着内存成本的急剧下降,现在大型站点的服务器内存配置一般比当时要高一个数量级不止。所以256个进程的硬限制对于一台1G内存的机器来说是太浪费了,而且 Apache的软上限 max_client是受限于HARD_SERVER_LIMIT的,因此如果WEB服务器内存大于256M,都应该调高Apache的 HARD_SERVER_LIMIT。根据个人的经验:2560已经可以满足大部分小于2G内存的服务器的容量规划了(Apache的软上限的规划请看后面)。

 

 

     Apache的编译:以下通用的编译选项能满足以后任意模块的安装

./configure --prefix=/another_driver/apache/ --enable-shared=max --enable-module=most
比如:
./configure --prefix=/home/apache/ --enable-shared=max --enable-module=most

 

     解释:
     --prefix=/another_driver/apache/:建议将apache服务安装在另外一个驱动设备上的目的在于硬盘往往是一个系统使用寿命最低的设备,因此:将服务数据和系统完全分开,不仅能提高了数据的访问速度,更重要的,大大方便系统升级,应用备份和恢复过程。

     --shared-module=max:使用动态加载方式载入子模块会带来5%的性能下降,但和带来的配置方便相比更本不算什么:比如模块升级方便,系统升级风险降低,安装过程标准化等

     --enable-module=most:用most可以将一些不常用的module编译进来,比如后面讲到的mod_expire是就不在 apache的缺省常用模块中

如果不想build so, 也可以这样:
./configure \
"--with-layout=Apache" \
"--prefix=/path/to/apache" \
"--disable-module=access" \
"--disable-module=actions" \
"--disable-module=autoindex" \
"--disable-module=env" \
"--disable-module=imap" \
"--disable-module=negotiation" \
"--disable-module=setenvif" \
"--disable-module=status" \
"--disable-module=userdir" \
"--disable-module=cgi" \
"--disable-module=include" \
"--disable-module=auth" \
"--disable-module=asis"

     但结果会发现,这样编译对服务性能只能有微小的提高(5%左右),但却失去了以后系统升级和模块升级的灵活性,无论是模块还是Apache本身升级都必须把Apache和PHP的SOURCE加在一起重新编译。

     apache的缺省配置文件一般比较大:可以使用去掉注释的方法精简一下:然后再进入具体的培植过程能让你更快的定制出你所需要的。
grep -v "#" httpd.conf.default >httpd.conf

 

     需要修改的通用项目有以下几个:

#服务端口,缺省是8080,建议将整个Apache配置调整好后再将服务端口改到正式服务的端口
Port 8080 => 80

#服务器名:缺省没有
ServerName name.example.com
#最大服务进程数:根据服务容量预测设置
MaxClients 256 => 800

#缺省启动服务后的服务进程数:等服务比较平稳后,按平均负载下的httpd个数设置就可以
StartServers 5 => 200

不要修改:
以前有建议说修改:
MinSpareServers 5 => 100
MaxSpareServers 10 => 200

但从我的经验看来:缺省值已经是非常优化的了,而且让Apache自己调整子共享进程个数还是比较好的。

特别修改:
在solaris或一些比较容易出现内存泄露的应用上:
MaxRequestsPerChild 0 =>3000

 

 

应用模块和工具的安装配置:

     由于使用模块动态加载的模式,所以可以方便的通过简单的配置调整来把Apache定制成你需要的:最好把不常用模块全部清除(无论处于安全还是效率)。
比如:对于静态页面服务器:就什么其他子模块都不加载,对于PHP应用就加上PHP模块,对于JAVA应用就把Resin模块加载上。而且各种模块的插拔非常简单,这样调试过程中就可以简单的通过注释掉不需要的模块,而不用重新编译。

     一般说来,可以不需要的模块包括:

#LoadModule env_module libexec/mod_env.so
#LoadModule negotiation_module libexec/mod_negotiation.so
#LoadModule status_module libexec/mod_status.so
#server side include已经过时了
#LoadModule includes_module libexec/mod_include.so
#不需要将没有缺省index文件的目录下所有文件列出
#LoadModule autoindex_module libexec/mod_autoindex.so
#尽量不使用CGI:一直是Apache安全问题最多的地方
#LoadModule cgi_module libexec/mod_cgi.so
#LoadModule asis_module libexec/mod_asis.so
#LoadModule imap_module libexec/mod_imap.so
#LoadModule action_module libexec/mod_actions.so
#不使用安全认证可以大大提高访问速度
#LoadModule access_module libexec/mod_access.so
#LoadModule auth_module libexec/mod_auth.so
#LoadModule setenvif_module libexec/mod_setenvif.so

     最好保留的有:

#用于定制log格式
LoadModule config_log_module libexec/mod_log_config.so
#用于增加文件应用的关联
LoadModule mime_module libexec/mod_mime.so
#用于缺省index文件:index.php等
LoadModule dir_module libexec/mod_dir.so

     可用可不用的有:

#比如:需要在~/username/下调试php可以将
LoadModule userdir_module libexec/mod_userdir.so
#比如:需要将以前的URL进行转向或者需要使用CGI script-alias
LoadModule alias_module libexec/mod_alias.so

     常用的模块:

最常用的可能就是php和JAVA应用服务器的前端,此外,从性能上讲利用mod_gzip可以减少40%左右的流量,减少机器用于传输的负载,而 mod_expires可以减少10%左右的重复请求,让重复的用户对指定的页面请求结果都CACHE在本地,根本不向服务器发出请求。

     建议将所有MODULE的配置都放到相应模块的配置内部:<IfModule some_module.c>some_module config </IfModule>

 

PHP的安装:
/path/to/php_src/configure --with-apxs=/path/to/apache/bin/apxs --with-other-modules-you-need
需要修改的配置:
AddType application/x-httpd-php .php .php3 .any_file_in_php

resin的安装设置:
/path/to/resin/src/configure --with-apxs=/path/to/apache/bin/apxs
具体的resin设置放在另外一个文件中:比如/home/resin/conf/resin.conf
<IfModule mod_caucho.c>
CauchoConfigFile /path/to/apache/conf/resin.conf
</IfModule>

mod_expires的安装配置:
<IfModule mod_expires.c>
    ExpiresActive on
    ExpiresByType image/gif "access plus 1 month"
    ExpiresByType text/css "now plus 1 month"
    ExpiresDefault "now plus 1 day"
</IfModule>

注释:
所有的.gif文件1个月以后过期
所有的文件缺省1天以后过期

mod_gzip的安装
http://www.chedong.com/tech/compress.html

 

日志的轮循:cronolog的安装和设置

     cronolog可以非常整齐的将日志按天轮循存储

     缺省编译安装到/usr/local/bin/下,只需要将配置改成:

CustomLog "|/usr/local/sbin/cronolog /home/apache/logs/%w/access_log" combined

     日志将按天截断并存放在以星期为目录名的目录下:比如:log/1是周一,log/5是周五, log/0是周日

用gzip压缩每天的日志:
30 4 * * * /usr/bin/gzip -f /home/apache/logs/`date -d yesterday +%w`/access_log

日志的定期删除:
30 5 * * */usr/bin/find /home/apache/logs/ -name access_log.gz -mtime +3 |xargs -r /bin/rm –f

 

升级维护

     由于使用动态模块加载方式(DSO模式)安装Apache,Apache的HTTPD核心服务和应用模块以及应用模块之间都变的非常灵活,建议将所有独立模块的配置都放在

<IfModule mod_name>
CONFIGURATIONS..
</IfModule>

     里,这样配置非常容易通过屏蔽某个模块来进行功能调整:比如:

#AddModule mod_gzip.c
就屏蔽了mod_gzip,而其他模块不首任何影响。

 

安装和维护过程:

  • 系统安装:系统管理员的职责就是安装系统和一个按照DSO模式安装的Apache,然后COLON。
  • 应用安装:由应用管理员负责具体应用所需要的模块并设置HTTPD。
  • 系统升级:系统管理员:升级系统/升级Apache
  • 应用升级:应用管理员:升级应用模块:PHP CAUCHO等
  • 系统备份/恢复:如果Apache不在缺省的系统盘上,只需要将Apache目录备份就可以了,遇到系统分区的硬件问题直接使用预先准备好的系统COLON,再直接将Apache所在物理盘恢复就行了。

 

系统管理员:Apache的最简化安装
OS + Apache (httpd core only)

 

应用管理员:应用模块定制
纯静态页面服务
core
PHP动态页面
core+so
+php
JAVA应用
core+so
+caucho
+ssl

 

应用例子:
www.example.com
image.example.com
bbs.example.com
mall.example.com

 

例子:Apache和PHP模块的独立升级。

如果Apache是按照以下方式安装:

./configure --prefix=/home/apache --enable-shared=max --enable-module=most

     PHP是按照以下方式安装:

./configure --with-apxs=/home/apache/bin/apxs --enable-track-vars --with-mysql

     以后单独升级Apache的时候,仍然是:

./configure --prefix=/home/apache --enable-shared=max --enable-module=most
make
su
#/home/apache/bin/apachectl stop
#make install

     单独升级php时,仍然是:

./configure --with-apxs=/home/apache/bin/apxs --enable-track-vars --with-mysql
make
su
#/home/apache/bin/apachectl stop
#make install
#/home/apache/bin/apachectl start

     基于反相代理的WEB加速:

squid和mod_proxy都可以实现反相代理加速。而基于缓存的代理加速比起原有WEB服务,速度会有数量级的提升。

 

小提示:

Apache安装后,缺省根目录下没有但很有用的2个文件:

  • favicon.ico: favicon.ico是一个16x16的站点图标文件,如果浏览器发现有这个文件,在地址栏中会用这个图标替换调浏览器的网页图标。IE6和 MOZILLA等主流浏览器都支持这个功能。
    例如: http://www.chedong.com/favicon.ico
  • robots.txt: 用于告诉搜索引擎的爬虫程序(spider)网站那些页面可以被索引,那些不可以。
    具体说明请参考:http://www.robotstxt.org/wc/robots.html

apache2配置优化以及性能测试小结(貌似还算基础的优化,转)

 

一、优化目的:

     公司中现有多个apache平台,其中网元管理系统、升级和注册授权系统、离线浏览系统和应用组所开发的系统都是运行在专用的服务器中,他们都是以业务为主的系统,所拥有的硬件资源比较多,可以着重优化apache的运行速度,以适当的资源换取更高的运行速度

     但是设备中运行的各个配置程序,他们是以性能为主的系统,所运行的环境就要相对恶劣,硬件资源限制非常多,不能供web程序随意使用,他们的优化方向应该是保证运行速度的基础上尽力压低资源消耗

     受限于此,很多外挂式加速程序都无法使用了,比如memcache、eaccelerator等,使用这些工具的前提就是内存足够大,或者资源足够多,通常是专用的apache服务器上才会用到,也就是我们的第一类系统中才可以使用的,在一个嵌入系统中使用其实是得不尝失的。下面将着重研究两种情况都使用的优化方法。

 

二、运行环境

     无论何时,apache所运行的硬件环境都是对性能影响最大的因素,即使不能对硬件进行升级,也最好给apache一个单独的主机以免受到其他应用的干扰。但很明显,我们的配置页面程序无法满足这个要求。

     各个硬件指标中,对性能影响最大的是内存,对于静态内容(图片、javascript文件、css文件等),它决定了apache可以缓存多少内容,它缓存的内容越多,在硬盘上读取内容的机会就越少,而存取硬盘上的特定文件是一件很费时的操作,大内存可以极大提高静态站点的速度;对动态高负载站点来说,每个请求保存的时间更多一些,apache的mpm模块会为每个请求派生出相应的进程或线程分别处理,而进程或线程的数量与内存的消耗近似成正比,因此增大内存对提高动态站点的负载和运行速度也极为有利

     其次是硬盘的速度,静态站点尤为突出,apache不断的在读取文件并发送给相应的请求,硬盘的读写是极其频繁的;动态站点也要不断的加载web程序(php等),一个请求甚至要读取十几个文件才能处理完成,因此尽可能的提高硬盘速度和质量对提高apache的性能是有积极意义的。

     最后是cpu和网络,cpu影响的是web程序执行速度,网络影响流量大小。

     影响性能的另一因素是操作系统,php程序在类unix环境中的执行速度仍然比windows中要快,我们的系统都能满足这个要求了。

 

三、apache普通配置参数

1、静态还是动态

  使用apache的动态载入模块非常方便,因为在需要时模块才会被载入。虽然有些性能开销,但同时有利于减少服务器对内存的需求。

     静态载入虽然一次性载入所有需要的模块,增加内存消耗。因此我们全部采用动态载入的方法。

2、hhostnamelookups off

     域名查找:这增加了处理每个请求的开销,首先,服务器会对dns系统做一个反向查询以找出客户系统的主机名,然后又进行正向查询看获得的主机名是否真实指向客户的ip。大多数情况下,你可以简单的关闭这个功能,如果你经常处理服务器日志,这个工作完全可以在以后进行。你可以通过在设置文件中加入指示hostnamelookups off来关闭这个功能。

3、options -followsymlinks

     符号连接:当打开这个选项时,apache将检查每个请求中是否包含对符号连接的引用,这将对请求中包含的每个路径调用一次lstat()系统调用。除非你准备使用符号连接,否则用 options -followsymlinks 来关掉它。

4、sethandler server-status

     服务器状态信息,默认已经关闭。该模块尽管这对测试与监控服务器很有用,但它也为服务器带来了额外的开销,你可以通过寻找任何类似sethandler server-status的指示来关闭,如果可能,你可以在安装apache时移除这个模块。

5、options -indexes

     关闭目录浏览

6、directoryindex index.php index.html

     在可以更精确的时候尽可能不要使用通配符之类的灵活选项,删除不需要的选项,明确的指定设置文件列表,最常用的放在最前。

7、cgi模块

     除非你有很好的理由否则就允许cgi的执行,将似有的cgi文件放到一个特定的目录并为之设定正确的权限,这避免了apache对每一个请求都要判断一次要求的是一个静态文件还是一个动态文件。

8、写入日志

     写入日志信息是一个很花费时间的工作,apache保持日志文件的打开状态以节省打开文件的时间,如果没有必要存储日志信息,你可以关闭这个选项以节省出更多的处理器时间,只需要在设置文件中把日志那一行注释掉就可以关掉它。

  如果必须保留日志,你可以关闭hostnamelookups选项(见上文)然后把日志文件拷备到另一台机器上做进一步分析。

9、allowoverride none

     .htaccess文件可以极大的扩展apache的设置参数,而无需每次你改变设计都要编辑apache主设置文件,但对这个文件的使用也降低了服务器的性能。

  如果使用这个文件,apache必需首先在当前目录中查找是否存在这个文件,如果存在就解析这个文件并在当前目录中应用文件中的设置。更坏的是,apache不仅要查看当前的目录,还要查看当前目录的所有上层目录是否包括htaccess文件以根据所有这些文件最终确定设置。

  如果你想最优化服务器的性能,你应该禁止使用htaccess文件,任何基本目录的设置都可以在主设置文件中进行,而主设置文件仅在服务器启动时解析一次。为了禁用htaccess文件,在任何节里加上指示allowoverride none。

10、timeout 5

     timeout 设置 apache 等待一个连接读写操作的时间长度,也就是连接建立后,apache 等待客户端完成请求发送的时间,或者是响应开始之后,apache 写出数据到客户端连接的时间长度。

     无论对于哪种应用来说,300秒的缺省值都有些过长了,因为这就意味着,如果客户端发生了某种未知因素导致的迟滞的话,服务器的一个连接和与之对应的所有资源都要维持 300 秒,这个对于重载的服务器来说是在是有些过长,所以,我建议将其设置得小一些,这个长度只要足够保证各种客户端的应用能够正常传递数据即可。这里需要考虑的因素主要有各种客户端的连接状况和服务器的繁忙程度。一般来说,我建议设置为 3~5。

11、keepalive on

     这个选项明确 httpd 进程对每个请求的链接是否保持长链接。如果保持长链接,则从同一个客户端的连续两次请求会使用同一个连接,而不用重复发送请求。

     对于下载类的应用,因为连接时间都比较长,因此这个值设置成 on 还是 off 关系不大,从节约每一滴资源角度考虑,可以设置为 off。

     对于网页类应用来说,如果你的静态页面上有一些图标、图片、和js、css等东西的话,并且如果有超过两个的资源的话,我建议是设置为 on。

12、maxkeepaliverequests 100

     最多保持多少个活动的长链接

13、 keepalivetimeout 5

     连接的保持时间,超过时间就回收

     apache进程在使用内存时,是“渐长”的。也就是说,直到这个进程死掉,使用内存的数量是一直增长而不会减少的。这样的话,apache进程使用内存的多少,就决定于你的应用程序最大使用内存量了。

     keepalivetimeout 这个参数决定了,在什么都不做之前,一个http进程能够等待多长时间?设想一下,如果keepalive设置为on,而 keepalivetimeout设置为一个比较大的数字,apache占用内存会很快的增长。这是因为,一个apache进程完成了一个任务(并达到了一定的内存占用,想一下“渐进”模式),并不会马上退出,而是等待一个keepalivetimeout时间。假设用户的链接请求持续不断的到来,则积累起来的无用的apache进程就会相当多,直到timeout,这些进程才会被杀死。

     但是,keepalive的确对于静态的文件,比如图像文件的传送是很有效的,因此,keepalive要设置为on,但是keepalvietimeout要设置的小些,比如5s

14、serversignature off

     默认情况下,很多apache安装时会显示版本号及操作系统版本,甚至会显示服务器上安装的是什么样的apache模块。这些信息可以为黑客所用,并且黑客还可以从中得知你所配置的服务器上的很多设置都是默认状态。

     所以,请加入如下两条:

serversignature off

servertokens prod

     serversignature 出现在apache所产生的像404页面、目录列表等页面的底部。servertokens目录被用来判断apache会在server http响应包的头部填充什么信息。如果把servertokens设为prod,那么http响应包头就会被设置成:server:apache

 

四、MPM模块

     多处理方式(multi-processing module/mpm)他允许特定平台处理多个并发连接

     apache的mpm模块可运行在多种模式之下,其中beos、mpmt_os2分别是beos和os/2上缺省的mpm, perchild主要设计目的是以不同的用户和组的身份来运行不同的子进程。这在运行多个需要cgi的虚拟主机时特别有用,会比1.3版中的suexec 机制做得更好。leader和threadpool都是基于worker的变体,还处于实验性阶段,某些情况下并不会按照预期设想的那样工作,所以 apache官方也并不推荐使用。因此,我们主要阐述prefork和worker这两种和性能关系最大的产品级mpm ( 有关其它的mpm详细说明,请参见apache官方文档:http://httpd.apache.org/docs-2.0/mod/)。

 

1、prefork的工作原理及配置

     prefork就是unix平台上缺省的mpm。它所采用的预派生子进程方式也是 apache 1.3中采用的模式。prefork本身并没有使用到线程,2.0版使用它是为了与1.3版保持兼容性;另一方面,prefork用单独的子进程来处理不同的请求,进程之间是彼此独立的,这也使其成为最稳定的mpm之一。

  如果是使用debian的apt安装的apache,使用"apache2ctl -l"来确定当前使用的mpm,应该会看到prefork.c(如果看到worker.c说明使用的是worker mpm,依此类推),在apache2.conf中可以找到这一段配置

<IfModule mpm_prefork_module>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 150
MaxRequestsPerChild 0
</IfModule>

     prefork的工作原理是,控制进程在最初建立"StartServers"个子进程后,为了满足"MinSpareServers"设置的需要创建一个进程,等待一秒钟,继续创建两个,再等待一秒钟,继续创建四个……如此按指数级增加创建的进程数,最多达到每秒32个,直到满足 MinSpareServers设置的值为止。这就是预派生(prefork)的由来。这种模式可以不必在请求到来时再产生新的进程,从而减小了系统开销以增加性能。

     MaxSpareServers设置了最大的空闲进程数,如果空闲进程数大于这个值,apache会自动kill掉一些多余进程。这个值不要设得过大,但如果设的值比MinSpareServers小,apache会自动把其调整为MinSpareServers+ 1。如果站点负载较大,可考虑同时加大MinSpareServers和MaxSpareServers。

     MaxRequestsPerChild设置的是每个子进程可处理的请求数。每个子进程在处理了"MaxRequestsPerChild" 个请求后将自动销毁。0意味着无限,即子进程永不销毁。虽然缺省设为0可以使每个子进程处理更多的请求,但如果设成非零值也有两点重要的好处:

      可防止意外的内存泄漏;

      在服务器负载下降的时侯会自动减少子进程数。

      因此,可根据服务器的负载来调整这个值。但也不能太小,不然系统不断的开启新的apache进程,造成资源浪费。

     MaxClients是这些指令中最为重要的一个,设定的是apache可以同时处理的请求,是对apache性能影响最大的参数。其缺省值 150是远远不够的,如果请求总数已达到这个值(可通过ps -ef|grep http|wc -l来确认),那么后面的请求就要排队,直到某个已处理请求完毕。这就是系统资源还剩下很多而http访问却很慢的主要原因。系统管理员可以根据硬件配置和负载情况来动态调整这个值。虽然理论上这个值越大,可以处理的请求就越多,但apache默认的限制不能大于256。如果把这个值设为大于256,那么 apache将无法起动。事实上,256对于负载稍重的站点也是不够的。在apache 1.3中,这是个硬限制。如果要加大这个值,必须在“configure”前手工修改的源代码树下的src/include/httpd.h中查找 256,就会发现“#define hard_server_limit 256”这行。把256改为要增大的值(如4000),然后重新编译apache即可。在apache 2.0中新加入了serverlimit指令,使得无须重编译apache就可以加大maxclients。

<IfModule mpm_prefork_module>
StartServers 10
MinSpareServers 10
MaxSpareServers 15
ServerLimit 600
MaxClients 300
MaxRequestsPerChild 600
</IfModule>

2、worker的工作原理及配置

  相对于prefork,worker是2.0 版中全新的支持多线程和多进程混合模型的mpm。由于使用线程来处理,所以可以处理相对海量的请求,而系统资源的开销要小于基于进程的服务器。但是, worker也使用了多进程,每个进程又生成多个线程,以获得基于进程服务器的稳定性。这种mpm的工作方式将是apache 2.0的发展趋势。

<IfModule mpm_worker_module>
StartServers 2
MaxClients 150
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25
MaxRequestsPerChild 0
</IfModule>

     worker的工作原理是,由主控制进程生成"startservers"个子进程,每个子进程中包含固定的"threadsperchild"线程数,各个线程独立地处理请求。同样,为了不在请求到来时再生成线程,minsparethreads和maxsparethreads设置了最少和最多的空闲线程数;而maxclients设置了所有子进程中的线程总数。如果现有子进程中的线程总数不能满足负载,控制进程将派生新的子进程。

     minsparethreads和maxsparethreads的最大缺省值分别是75和250。这两个参数对apache的性能影响并不大,可以按照实际情况相应调节。

     threadsperchild是worker mpm中与性能相关最密切的指令。threadsperchild的最大缺省值是64,如果负载较大,64也是不够的。这时要显式使用 threadlimit指令,它的最大缺省值是20000。上述两个值位于源码树server/mpm/worker/worker.c中的以下两行:

     究竟是选取prefork还是worker需要具体分析,相对而言高负载下perfork拥有更高的稳定性和运行速度,而worker的资源消耗更小。也已经有人在对两种工作模式作了各种测试:http://jed.dzhope.com/read.php/298.htm

     实际情况看来,worker现在还没能达到所期望的效果,性能比frefork差一些,资源消耗少一点。更可惜的是debian下worker还不能与PHP5完美结合,所以只能选用perfork了。

 

五、性能测试

     为了获得优化有性能提高的幅度,评估优化工作的成效,需要对apache2服务器进行测试。

     测试环境:

apache2和php5服务器:debian4.0、apache2.2.3、 php5.2.0-8+etch0、256M内存

     在另一台机器上使用apachebench工具模拟多个浏览器向服务器的测试页面发起HTTP请求,为了减少网络带宽的影响,测试页面的返回值尽可能的小,此处只有1 byte,并为发起测试的机器和服务器组建了一个单独的局域网。每种并发测试11次,以后10次的结果为准,取平均值。

     以下是测试的数据:其中并发数是指apachebench同时发起的请求个数,优化前和优化后是指平均每个请求花费的处理时间,单位毫秒

并发数     优化前(毫秒)    优化后(毫秒)
10          2.048              1.7549
50          2.1389             1.927
100        2.2084             1.9238
200        2.7689             2.5915
400        3.0523             2.797

 

     由图中可以看出,优化后的效果还是很明显的,无论是在低并发还是高并发下,都有效的提高了请求的相应时间。

     需要指出的是,尽管高负载时优化后性能提高的百分比并不明显,但在并发数400时,测试18次失败7次,而优化后测试14次失败3次。优化不仅仅提高了服务器的性能,还提高了负载的能力。

 

六、结论

     优化可以有效的提高apache2的性能。

     对于WMS等设备上的配置页面,第三部分的“apache普通配置参数”可以应用,MPM主要是以资源换取速度的优化,可以酌情调整。

     对于EM     S、升级系统和应用系统,可以全面优化以提高性能和高负载能力。

11月6日

MySQL主从服务器+读写分离

花了三天时间,把MySQL的主从数据库+读写分离部署好了。感觉对缓解大数据流量的服务器压力还是很有效果的。

最近大把时间都花在了数据库上,幸好之前有自己研究过一段时间的数据库,貌似还是上大学的时候。。现在竟然还能回忆起来些

数据库确实是个值得花费精力的地方,很有用。

 

 

一、搭Mysql主、从服务器

                   安装Mysql不是很复杂。主从主要是备份、后续读写分布事务处理等用途

 

     useradd mysql –s /sbin/nologin                              #生成一个mysql的用户

     tar zxvf mysql-5.0.22.tar.gz

     cd mysql-5.0.22

     ./configure --prefix=/usr/local/mysql --localstatedir=/opt/data && make && make install

     cp support-files/my-large.cnf /etc/my.cnf               #配置文档
                                                                           #/etc/my.cnf 作为全局设置
                                                                            # mysql-data-dir/my.cnf 作为服务器指定设置                                                                                                                                          # ~/.my.cnf 作为用户设置

     cd /usr/local/mysql

     /usr/local/mysql/bin/mysql_install_db --user=mysql

     chown -R mysql:mysql /opt/data

     chown -R mysql:mysql /usr/local/mysql

从服务器修改/etc/my.cnf配置文档,server-id=10

     /usr/local/mysql/bin/mysqladmin –p shutdown            #停服务

     /usr/local/mysql/bin/mysqld_safe &                          #起服务,如果没有起来 多数是权限问题

     /usr/local/mysql/bin/mysqladmin –p password’111111’  #修改密码

     /usr/local/mysql/bin/mysql –p                                  #登陆,新安装应该没有密码

 

主服务器上:

     mysql>grant all privileges on *.* to back@192.168.x.x identified by ‘111111’;

                                                                               #新建一个给从服务器登陆的账号

     mysql> show master status;

+------------------+----------+--------------+------------------+
| File                    | Position    | Binlog_Do_DB | Binlog_Ignore_DB  |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 |   235       |                    |                          |
+------------------+----------+--------------+------------------+

         记下file及position的值,做从服务器操作的时候需要。

 

   配置从服务器

     mysql> change master to master_host='192.168.x.x', master_user='back',
               master_password='111111', master_log_file='mysql-bin.000003', master_log_pos=235;

     mysql> start slave;                                                 #启用slave

     mysql> show slave status\G                                     #显示当前slave状态

         Slave_IO_Running: Yes
         Slave_SQL_Running: Yes                                     #都为Yes,则为正常

 

主数据库若有数据:

mysql> FLUSH TABLES WITH READ LOCK;                #数据库锁表操作,不让数据再进行写入动作。

mysql> show master status;                   

    把主服务器数据文件复制到从服务器,整个目录一起tar过去即可

 

    或者采用如下备份方法:

     mysqldump -u root -p testdb testtab>d:\testdb_testtab.sql

     恢复命令:

     create database testdb;use testdb;

     mysql>source d:\testdb_testtab.sql

 

mysql> UNLOCK TABLES;                                     #取消主数据库锁定

 

    配置从服务器,保证主服务器的position位置和备份保持一致即可

 

 

  以上主从服务器操作关键在于 备份数据position对应 以及change master命令。

 

  #关于/mysql-data/master.info文档,看my.cnf配置文档中的说明

#    Set the variables below. However, in case you choose this method, then
#    start replication for the first time (even unsuccessfully, for example
#    if you mistyped the password in master-password and the slave fails to
#    connect), the slave will create a master.info file, and any later
#    change in this file to the variables' values below will be ignored and
#    overridden by the content of the master.info file, unless you shutdown
#    the slave server, delete master.info and restart the slaver server.
#    For that reason, you may want to leave the lines below untouched
#    (commented) and instead use CHANGE MASTER TO (see above)

   也就是说还是推荐用change master to 命令来修改master.info文档。而不要用my.cnf的从服务器配置。
   在start slave前这个master.info一定要配置在一个正确的状态,除非他不存在。因为master.info为首选配置档

 

 

测试:

    主服务器上

mysql> create database testdb;
mysql> create table testtb(id int(3),name char(10));
mysql> insert into testtb values (001,’1’);
mysql> use testdb;
mysql> select * from testtb;

    从服务器上

mysql> show databases;
mysql> use testdb;
mysql> show tables;
mysql> select * from testtb;

    确认从服务器上有相同的记录即可。

 

 

二、读写分离

    这部分主要有点是用来给服务器做均衡负载的,其实还是蛮有趣的一个功能。

    搭建Mysql-proxy服务可就没那么简单了,如果能够yum一下就全都搞定那就太开心了!

    无所谓这台代理服务搭在哪里,主、从或者第三方都OK,我推荐可以在从上面做,测试比较清楚

        下面基本就用我history里的命令了,省的一句一句打。

 

     安装 lua      

628  wget http://www.lua.org/ftp/lua-5.1.4.tar.gz
638  tar zxvf lua-5.1.4.tar.gz
639  cd lua-5.1.4
640  vi Makefile                                            #这里是修改  INSTALL_TOP= /usr/local/lua
641  make linux
643  make install

     安装 libevent              

644  cd ..
645  wget http://monkey.org/~provos/libevent-1.4.12-stable.tar.gz
647  tar zxvf libevent-1.4.12-stable.tar.gz
648  cd libevent-1.4.12-stable
649  ./configure --prefix=/usr/local/libevent
650  make
651  make install

     安装check

644  cd ..
652  wget ftp://ftp.eenet.ee/pub/FreeBSD/distfiles/check-0.9.6.tar.gz
655  tar zxvf check-0.9.6.tar.gz
656  cd check-0.9.6
657  ./configure
658  make
659  make install

     安装glib2

681  cd ..
682  wget http://ftp.gnome.org/pub/gnome/sources/glib/2.22/glib-2.22.1.tar.gz
683  tar zxvf glib-2.22.1.tar.gz
684  cd glib-2.22.1
685  ./configure --prefix=/usr/local/glib2
686  make
687  make install

     安装mysql-proxy

660  cd ..
662  wget ftp://ftp.swin.edu.au/freebsd/ports/distfiles/mysql-proxy-0.7.1.tar.gz
664  tar zxvf mysql-proxy-0.7.1.tar.gz
665  cd mysql-proxy-0.7.1
./configure --prefix=/usr/local/mysql-proxy --with-mysql=/usr/local/mysql --with-lua

 

     结果提示glib2版本不对

772  cp /usr/local/glib2/lib/pkgconfig/glib-2.0.pc /usr/lib/pkgconfig/

     然后提示lua不对,于是我下了一个lua.pc

# vars from install Makefile

# grep '^V=' ../Makefile
V= 5.1
# grep '^R=' ../Makefile
R= 5.1.1

# grep '^INSTALL_.*=' ../Makefile | sed 's/INSTALL_TOP/prefix/'
prefix= /usr/local/lua
INSTALL_BIN= ${prefix}/bin
INSTALL_INC= ${prefix}/include
INSTALL_LIB= ${prefix}/lib
INSTALL_MAN= ${prefix}/man/man1
INSTALL_LMOD= ${prefix}/share/lua/${V}
INSTALL_CMOD= ${prefix}/lib/lua/${V}

# canonical vars
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include

Name: Lua
Description: An Extensible Extension Language
Version: ${R}
Requires:
Libs: -L${libdir} -llua -lm
Cflags: -I${includedir}

    接着提示libevent错误 研究了半天 直接把安装路径放到/usr/下面

648  cd ~/libevent-1.4.12-stable
853  ./configure --prefix=/usr/ && make && make install
868  cd ..
869  cd mysql-proxy-0.7.1
856  ./configure --prefix=/usr/local/mysql-proxy/ --with-mysql=/usr/local/mysql/ --with-lua --with-libevent=/usr/

    这次总算./configure 通过了

        接着make,结果又出错~~提示找不到什么.h的文件
        到make里面去看,原来是编译的时候需要几个库文件,安装路径里面没有~
        这个做的真不好。。

875  cp ../lua-5.1.4/src/lua*.h .
876  cp ../lua-5.1.4/src/lauxlib.h .

    总算make && make install通过了

892  /usr/local/mysql-proxy/sbin/mysql-proxy –V

    测试一把,又出错了。。。

894  chcon -t texrel_shlib_t /usr/local/mysql-proxy/lib/libmysql-chassis.so.0

    原来是selinux作怪,改了。

896  /usr/local/mysql-proxy/sbin/mysql-proxy –V

    总算OK了。

 

 

 

接着来配服务。

      把 rw-splitting.lua 放到/usr/local/mysql-proxy/share/mysql-proxy/下面

 

rw-splitting.lua:

--[[ $%BEGINLICENSE%$
Copyright (C) 2007-2008 MySQL AB, 2008 Sun Microsystems, Inc

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

$%ENDLICENSE%$ --]]

---
-- a flexible statement based load balancer with connection pooling
--
-- * build a connection pool of min_idle_connections for each backend and maintain
--   its size
-- *
--
--

local commands    = require("proxy.commands")
local tokenizer   = require("proxy.tokenizer")
local lb          = require("proxy.balance")
local auto_config = require("proxy.auto-config")

--- config
--
-- connection pool
if not proxy.global.config.rwsplit then
    proxy.global.config.rwsplit = {
        min_idle_connections = 1,
        max_idle_connections = 1,

        is_debug = false
    }
end

---
-- read/write splitting sends all non-transactional SELECTs to the slaves
--
-- is_in_transaction tracks the state of the transactions
local is_in_transaction       = false

-- if this was a SELECT SQL_CALC_FOUND_ROWS ... stay on the same connections
local is_in_select_calc_found_rows = false

---
-- get a connection to a backend
--
-- as long as we don't have enough connections in the pool, create new connections
--
function connect_server()
    local is_debug = proxy.global.config.rwsplit.is_debug
    -- make sure that we connect to each backend at least ones to
    -- keep the connections to the servers alive
    --
    -- on read_query we can switch the backends again to another backend

    if is_debug then
        print()
                print("[connect_server] " .. proxy.connection.client.dst.name)
    end

    local rw_ndx = 0

    -- init all backends
    for i = 1, #proxy.global.backends do
        local s        = proxy.global.backends[i]
        local pool     = s.pool -- we don't have a username yet, try to find a connections which is idling
        local cur_idle = pool.users[""].cur_idle_connections

        pool.min_idle_connections = proxy.global.config.rwsplit.min_idle_connections
        pool.max_idle_connections = proxy.global.config.rwsplit.max_idle_connections
        if is_debug then
            print("  [".. i .."].connected_clients = " .. s.connected_clients)
            print("  [".. i .."].pool.cur_idle     = " .. cur_idle)
            print("  [".. i .."].pool.max_idle     = " .. pool.max_idle_connections)
            print("  [".. i .."].pool.min_idle     = " .. pool.min_idle_connections)
            print("  [".. i .."].type = " .. s.type)
            print("  [".. i .."].state = " .. s.state)
        end

        -- prefer connections to the master
        if s.type == proxy.BACKEND_TYPE_RW and
           s.state ~= proxy.BACKEND_STATE_DOWN and
           cur_idle < pool.min_idle_connections then
            proxy.connection.backend_ndx = i
            break
        elseif s.type == proxy.BACKEND_TYPE_RO and
               s.state ~= proxy.BACKEND_STATE_DOWN and
               cur_idle < pool.min_idle_connections then
            proxy.connection.backend_ndx = i
            break
        elseif s.type == proxy.BACKEND_TYPE_RW and
               s.state ~= proxy.BACKEND_STATE_DOWN and
               rw_ndx == 0 then
            rw_ndx = i
        end
    end

    if proxy.connection.backend_ndx == 0 then
        if is_debug then
            print("  [" .. rw_ndx .. "] taking master as default")
        end
        proxy.connection.backend_ndx = rw_ndx
    end

    -- pick a random backend
    --
    -- we someone have to skip DOWN backends

    -- ok, did we got a backend ?

    if proxy.connection.server then
        if is_debug then
            print("  using pooled connection from: " .. proxy.connection.backend_ndx)
        end

        -- stay with it
        return proxy.PROXY_IGNORE_RESULT
    end

    if is_debug then
        print("  [" .. proxy.connection.backend_ndx .. "] idle-conns below min-idle")
    end

    -- open a new connection
end

---
-- put the successfully authed connection into the connection pool
--
-- @param auth the context information for the auth
--
-- auth.packet is the packet
function read_auth_result( auth )
    if is_debug then
        print("[read_auth_result] " .. proxy.connection.client.dst.name)
    end
    if auth.packet:byte() == proxy.MYSQLD_PACKET_OK then
        -- auth was fine, disconnect from the server
        proxy.connection.backend_ndx = 0
    elseif auth.packet:byte() == proxy.MYSQLD_PACKET_EOF then
        -- we received either a
        --
        -- * MYSQLD_PACKET_ERR and the auth failed or
        -- * MYSQLD_PACKET_EOF which means a OLD PASSWORD (4.0) was sent
        print("(read_auth_result) ... not ok yet");
    elseif auth.packet:byte() == proxy.MYSQLD_PACKET_ERR then
        -- auth failed
    end
end

---
-- read/write splitting
function read_query( packet )
    local is_debug = proxy.global.config.rwsplit.is_debug
    local cmd      = commands.parse(packet)
    local c        = proxy.connection.client

    local r = auto_config.handle(cmd)
    if r then return r end

    local tokens
    local norm_query

    -- looks like we have to forward this statement to a backend
    if is_debug then
        print("[read_query] " .. proxy.connection.client.dst.name)
        print("  current backend   = " .. proxy.connection.backend_ndx)
        print("  client default db = " .. c.default_db)
        print("  client username   = " .. c.username)
        if cmd.type == proxy.COM_QUERY then
            print("  query             = "        .. cmd.query)
        end
    end

    if cmd.type == proxy.COM_QUIT then
        -- don't send COM_QUIT to the backend. We manage the connection
        -- in all aspects.
        proxy.response = {
            type = proxy.MYSQLD_PACKET_OK,
        }
        if is_debug then
            print("  (QUIT) current backend   = " .. proxy.connection.backend_ndx)
        end

        return proxy.PROXY_SEND_RESULT
    end

    proxy.queries:append(1, packet, {resultset_is_needed = true})
    -- read/write splitting
    --
    -- send all non-transactional SELECTs to a slave
    if not is_in_transaction and
       cmd.type == proxy.COM_QUERY then
        tokens     = tokens or assert(tokenizer.tokenize(cmd.query))

        local stmt = tokenizer.first_stmt_token(tokens)

        if stmt.token_name == "TK_SQL_SELECT" then
            is_in_select_calc_found_rows = false
            local is_insert_id = false

            for i = 1, #tokens do
                local token = tokens[i]
                -- SQL_CALC_FOUND_ROWS + FOUND_ROWS() have to be executed
                -- on the same connection
                -- print("token: " .. token.token_name)
                -- print("  val: " .. token.text)
                if not is_in_select_calc_found_rows and token.token_name == "TK_SQL_SQL_CALC_FOUND_ROWS" then
                    is_in_select_calc_found_rows = true
                elseif not is_insert_id and token.token_name == "TK_LITERAL" then
                    local utext = token.text:upper()

                    if utext == "LAST_INSERT_ID" or
                       utext == "@@INSERT_ID" then
                        is_insert_id = true
                    end
                end

                -- we found the two special token, we can't find more
                if is_insert_id and is_in_select_calc_found_rows then
                    break
                end
            end

            -- if we ask for the last-insert-id we have to ask it on the original
            -- connection
            if not is_insert_id then
                local backend_ndx = lb.idle_ro()

                if backend_ndx > 0 then
                    proxy.connection.backend_ndx = backend_ndx
                end
            else
                print("   found a SELECT LAST_INSERT_ID(), staying on the same backend")
            end
        end
    end

    -- no backend selected yet, pick a master
    if proxy.connection.backend_ndx == 0 then
        -- we don't have a backend right now
        --
        -- let's pick a master as a good default
        --
        proxy.connection.backend_ndx = lb.idle_failsafe_rw()
    end

    -- by now we should have a backend
    --
    -- in case the master is down, we have to close the client connections
    -- otherwise we can go on
    if proxy.connection.backend_ndx == 0 then
        return proxy.PROXY_SEND_QUERY
    end

    local s = proxy.connection.server

    -- if client and server db don't match, adjust the server-side
    --
    -- skip it if we send a INIT_DB anyway
    if cmd.type ~= proxy.COM_INIT_DB and
       c.default_db and c.default_db ~= s.default_db then
        print("    server default db: " .. s.default_db)
        print("    client default db: " .. c.default_db)
        print("    syncronizing")
        proxy.queries:prepend(2, string.char(proxy.COM_INIT_DB) .. c.default_db)
    end

    -- send to master
    if is_debug then
        if proxy.connection.backend_ndx > 0 then
            local b = proxy.global.backends[proxy.connection.backend_ndx]
            print("  sending to backend : " .. b.dst.name);
            print("    is_slave         : " .. tostring(b.type == proxy.BACKEND_TYPE_RO));
            print("    server default db: " .. s.default_db)
            print("    server username  : " .. s.username)
        end
        print("    in_trans        : " .. tostring(is_in_transaction))
        print("    in_calc_found   : " .. tostring(is_in_select_calc_found_rows))
        print("    COM_QUERY       : " .. tostring(cmd.type == proxy.COM_QUERY))
    end

    return proxy.PROXY_SEND_QUERY
end

---
-- as long as we are in a transaction keep the connection
-- otherwise release it so another client can use it
function read_query_result( inj )
    local is_debug = proxy.global.config.rwsplit.is_debug
    local res      = assert(inj.resultset)
      local flags    = res.flags

    -- if inj.id ~= 1 then  -- this was causing some misleading errors
        -- ignore the result of the USE <default_db>
        -- the DB might not exist on the backend, what do do ?
        --
        if inj.id == 2 then
            -- the injected INIT_DB failed as the slave doesn't have this DB
            -- or doesn't have permissions to read from it
            if res.query_status == proxy.MYSQLD_PACKET_ERR then
                proxy.queries:reset()

                proxy.response = {
                    type = proxy.MYSQLD_PACKET_ERR,
                    errmsg = "can't change DB ".. proxy.connection.client.default_db ..
                        " to on slave " .. proxy.global.backends[proxy.connection.backend_ndx].dst.name
                }

                return proxy.PROXY_SEND_RESULT
            end
        end
    --    return proxy.PROXY_IGNORE_RESULT
    -- end

    is_in_transaction = flags.in_trans
    local have_last_insert_id = (res.insert_id and (res.insert_id > 0))

    if not is_in_transaction and
       not is_in_select_calc_found_rows and
       not have_last_insert_id then
        -- release the backend
        proxy.connection.backend_ndx = 0
    elseif is_debug then
        print("(read_query_result) staying on the same backend")
        print("    in_trans        : " .. tostring(is_in_transaction))
        print("    in_calc_found   : " .. tostring(is_in_select_calc_found_rows))
        print("    have_insert_id  : " .. tostring(have_last_insert_id))
    end
end

---
-- close the connections if we have enough connections in the pool
--
-- @return nil - close connection
--         IGNORE_RESULT - store connection in the pool
function disconnect_client()
    local is_debug = proxy.global.config.rwsplit.is_debug
    if is_debug then
        print("[disconnect_client] " .. proxy.connection.client.dst.name)
    end

    -- make sure we are disconnection from the connection
    -- to move the connection into the pool
    proxy.connection.backend_ndx = 0
end

 

    启动mysql-proxy代理

963 touch /var/log/mysql-proxy/mysql-proxy.log

965 /usr/local/mysql-proxy/sbin/mysql-proxy --proxy-read-only-backend-addresses=192.168.1.7:3306 --proxy-backend-addresses=192.168.1.9:3306 --proxy-lua-script=share/mysql-proxy/rw-splitting.lua > /var/log/mysql-proxy/mysql-proxy.log &

968 netstat –antp | grep 4040                              #看看有没有起来

969 ps –aux | grep mysql                                      #看看进程里面有没有 一些配置的路径里面都可以看到

985  /usr/local/mysql/bin/mysql -u root -p -P4040 –hlocalhost

                                                                        #登陆一下看看,

  

读写分离测试

    登陆3306端口,在从服务器testtb上增加几条记录

    客户端做多个连接到mysql-proxy的端口4040。

    insert一条记录,可以看到主服务器也有增加了记录。从服务器是同步过来的数据

    select * from testtb;在一个客户端连接的时候,显示的是主服务器的表内容

                                 而有多个客户端连接之后,就会显示从服务器的testtb表内容

 

 

 

    最后,他是同步所有database的,如果只需要备份指定的数据库,请一定要在my.cnf中加上

     replicate-do-db=dbname 

    不然,他找不到其他数据库,正常的数据库也不会更新了。

 

 

生成一个/usr/local/bin/mysql-proxy.sh

#! /bin/bash
/usr/local/mysql-proxy/sbin/mysql-proxy --proxy-read-only-backend-addresses=192.168.1.7:3306 --proxy-backend-addresses=192.168.1.9:3306 --proxy-lua-script=share/mysql-proxy/rw-splitting.lua > /var/log/mysql-proxy/mysql-proxy.log &

 

在/etc/rc.local 文档中加入一条

       /usr/local/bin/mysql-proxy.sh &

 

参考资料:

http://sery.blog.ccidnet.com/blog-htm-do-showone-uid-3587-itemid-472099-type-blog.html  

                                                                                      MySQL 主从复制读写分离实现

http://www.yayu.org/look.php?id=136                                   MySQL 主从同步关键句

http://butian.org/knowledge/develop/DB/20090520/1124.html    MySQL 主从服务器的一些技巧

http://www.3389hack.com/xueyuan/fuwuqi/MySQL/22601.html  MySQL配置文件my.cnf 例子的最详细翻译

11月5日

Oracle数据库的灾难恢复(转)


     随着办公自动化和电子商务的飞速发展,企业对信息系统的依赖性越来越高,数据库作为信息系统的核心担当着重要的角色。尤其在一些对数据可靠性要求很高的行业如银行、证券、电信等,如果发生意外停机或数据丢失其损失会十分惨重。为此数据库管理员应针对具体的业务要求制定详细的数据库备份与灾难恢复策略,并通过模拟故障对每种可能的情况进行严格测试,只有这样才能保证数据的高可用性。数据库的备份是一个长期的过程,而恢复只在发生事故后进行,恢复可以看作是备份的逆过程,恢复的程度的好坏很大程度上依赖于备份的情况。此外,数据库管理员在恢复时采取的步骤正确与否也直接影响最终的恢复结果,本文主要针对 Oracle数据库可能遇到的各种故障提供了相应的恢复的方法,仅供大家参考。

 
     要对Oracle数据库备份与恢复有清晰的认识,首先有必要对数据库的几种运行状态有充分的了解。Oracle数据库的运行状态主要分为3种,他们依次为:


l Nomount(非安装)Oracle只是读取ini文件中的配置信息,并初始化SGA区。
l Mount(安装)Oracle除了需要读取ini文件还要读取控制文件,并从中获取有关数据库的物理结构等信息。
l Open(打开)数据库要检查所有文件处于同一时间点,对错误进行恢复对未完成事务回滚,并最终可以允许用户访问。


     数据库的备份主要分为三种类型:冷备份;热备份;逻辑备份;
     数据库的备份不是本文讨论的重点,在这里只作一个概要的介绍,Oracle数据库备份主要有:

 
l Cold Backup(冷备份) 主要指在关闭数据库的状态下进行的数据库完全备份,备份内容包括所有数据文件、控制文件、联机日志文件、ini文件。
l Hot Backup(热备份) 指在数据库处于运行状态下,对数据文件和控制文件进行备份,要使用热备份必须将数据库运行在(Archive Log)归档方式下。
l Export(逻辑备份)这是最简单的备份方法,可按数据库中某个表、某个用户或整个数据库来导出,并且支持全部、累计、增量三种方式。使用这种方法,数据库必须处于打开状态,而且如果数据库不是在restrict状态将不能保证导出数据的一致性。


     数据库的恢复可分为两大类:完全恢复;不完全恢复;


完全恢复指将数据库恢复到发生故障的时间点,不丢失任何数据。

不完全恢复指将数据库恢复到发生故障前的某一个时间点,此时间点以后的所有改动将会丢失。如果没有特殊需求,我们建议应尽量使用完全恢复。


     Oracle 数据库的恢复过程分两步进行,首先将把存放在重做日志文件中的所有重做运用到数据文件,之后对重做中所有未提交的事务进行回滚,这样所有数据就恢复到发生灾难那一时刻了。数据库的恢复只能在发生故障之前的数据文件上运用重做,将其恢复到故障时刻,而不能将数据文件反向回滚到之前的某一个时刻。举个例子,我们有一个2001/1/1的数据库备份,当2001/5/1使我们发现数据库中数据发生混乱,希望将数据库恢复到2001/4/30时的状态,我们只能先恢复2001/1/1的数据库备份然后在其上运用重做记录使其前滚到2001/4/30时的状态,而不能将2001/5/1的数据库向后回滚到2001 /4/30。


     为了系统的设计数据库的恢复方案,我们先对可能遇到的错误进行分类,Oracle数据库错误主要分为5大类:


l SQL语句失败
l 线程失败
l 实例失败
l 用户操作失败
l 存储设备失败


     如果发生前三种失败,不需要我们人为干涉,Oracle系统会自动进行恢复。对于用户操作型的失败(如误删除数据),我们采取的补救措施主要有导入最新的逻辑备份或进行到某一时间点的不完全恢复。从Oracle 8之后的新版本中引入了基于表空间的时间点恢复(TSPITR),可以单独将包含错误操作的表空间恢复到指定时间,而不必对整个数据库进行不完全恢复。当错误操作发现比较及时而且数据量不大的情况下也可以考虑使用logminer生成反向SQL。

 
     针对存储设备的失败的情况比较复杂也是本文讨论的重点,存储设备的失败必然会使放置在其上的文件变为不可用,我们先将Oracle数据库所涉及到的文件进行一个划分,主要可分为:


l Oracle的系统文件,指Oracle的运行文件,各种应用程序
l 数据库控制文件
l 数据库联机重做日志文件
l 数据文件
l 归档日志文件


     避免第一种文件失败主要依赖系统管理员进行操作系统级的备份,当发生事故后只能依靠操作系统备份将其恢复。
     控制文件中记录着整个数据库的结构、每个数据文件的状况、系统SCN、检查点计数器等重要信息,在创建数据库时会让用户指定三个位置来存放控制文件,他们之间互为镜像,当其中任何一个发生故障,只需将其从ini文件中注释掉故障数据文件就可重新将数据启动。当所有控制全部失效时,可以在Nomount模式下执行create controlfile来重新生成控制文件,但必须提供redo log,data file,文件名和地址以及MAXLOGFILES,MAXDATAFILES,MAXINSTANCES等信息。如果失败之前运行过alter database backup controlfile to trace或alter database backup controlfile to ‘xxx’对控制文件作备份,恢复时可使用生成的脚本来重建或用备份文件覆盖,如果使用了旧的控制文件在恢复时要使用recover xxx using backup controlfile选项来进行恢复,并使用resetlogs选项来打开数据库。

 

 


     如果丢失的是联机日志文件,分两种情况处理1、丢失的是非活动的日志文件;2、丢失的是当前激活的日志文件。


     如果是第一种情况,而发生故障的日志文件组又具有多个成员,可以先将数据库shutdown,然后用操作系统命令将损坏日志文件组中好的日志成员文件把损坏的成员文件覆盖(在同一个日志成员组中的所有日志文件的各为镜象的),如果其物理位置不可用可将其拷贝到新的驱动器上,使用alter database rename file ‘xxxx’ to ‘xxxx’改变文件位置,之后启动数据库,如果正常马上进行一个冷备份。如果损坏的日志组中只有一个日志成员,先mount上数据库,将其转换为 noarchivelog模式,执行alter database add logfile member ‘xxx’ to group ‘x’给相关组增加一个成员,再执行alter database drop logfile member ‘bad_file’将损坏的日志文件删除,由于数据库的结构发生变动需要备份控制文件,之后将数据库改回archivelog模式,做一个冷备份。

 


     如果丢失的是当前激活的日志文件,数据库又没有镜像而且当前日志组中所有成员均变为不可用。

     首先将数据库shutdown abort,从最近的一次全备份中恢复所有的数据文件,将数据库启动到mount状态。如果原来的日志文件物理位置不可用,使用alter database rename file ‘xxx’ to ‘xxx’改变文件的存放位置。然后,使用recover database until cancel命令来恢复数据库,直到提示最后一个归档日志运用完之后,输入cancel。之后用alter database open resetlogs打开数据库,如果没有问题,立即进行一个冷备份。注意!所有包含在损坏的redo log中的信息将会丢失,也就是说数据库崩溃前已经提交的数据有可能会丢失。这对于某些要求很高的应用将会损失惨重,因此应尽量使每个日志组具有多个日志成员,并且放置在不同的驱动器上一防止发生介质故障。

 


     数据文件发生故障的情况也分为多种情况,

1、丢失包含在SYSTEM表空间的数据文件;
2、丢失没有回滚段的非SYSTEM数据文件;
3、丢失有回滚段的非SYSTEM数据文件。


     如果损坏的是系统表空间的数据文件。唯一的办法是从上一次备份中恢复受损的数据文件,(如果原位置不可用使用alter database rename命令改变新文件的位置),之后在数据库mount的状态下执行recover database/datafile对数据库进行回复,才能将数据库打开。注意:当SYSTEM表空间或其中的数据文件脱机,数据库是无法被打开的,因此必须在mount状态下将所有的恢复工作完成。


     当丢失的数据文件不属于系统表空间而且也不包含回滚段时,有可选择在数据库的两种状态下进行恢复---在数据库open的状态或者在数据库mount的状态。如果用户急于访问数据库中未受损部分的数据或对损坏的数据文件进行恢复需要很长时间,可以先使受损的数据文件脱机,将数据库打开给用户访问,再恢复受损的数据文件最后将其联机。步骤如下:先在数据库mount时,将相关的数据文件或表空间进行脱机alter database datafile xxx offline,然后将数据库open,这样就能使数据库未受损的部分先供用户访问,之后再进行recover datafile/tablespace,完成后用alter database datafile/tablespace ‘xxx’ online使其恢复联机就可被访问了。 当然用户也可以选择在数据库mount状态下,用recover database/datafile将所有的恢复工作做完,将所有数据文件一起打开供用户访问。


     如果丢失的数据文件是最后一种情况,即包含有回滚段的非系统表空间数据文件。也可以选择是在数据库先open的状态还是在mount状态下恢复。不过与上一种情况不同的是当包含回滚段的数据文件损坏时,如果使其先offline将数据库打开,那么所有数据库崩溃前未提交的事务涉及到的表将无法访问,也就是说在回滚段恢复前其中涉及的对象都不允许被访问。而且当所有包含回滚段的数据文件都在offline状态时,数据库无法进行任何DML操作,因此在数据库open状态恢复包含回滚段的数据文件时,可以先创建几个临时回滚段供数据使用create rollback segment temp1 tablespace system; alter rollback segment temp1 online;,当数据文件恢复后再将他们删除alter rollback segment temp1 offline; drop rollback segment temp1;。注意:当用这种方法使恢复的数据文件online之后,所有的原有回滚段将处于offline状态,必须手工使用alter rollback segment RBSxx online;使他们恢复联机状态,这样才能被数据库正常使用。如果在数据库mount状态下完成所有恢复,则不需要上述步骤。


     如果丢失数据文件后,用户发现没有故障前的数据文件的备份,而且自从丢失的数据文件最早建立之后一直没有使用过resetlogs选项打开过数据库。也就是说用户的控制文件是在损坏的数据文件建立前创建的,归档日志中包括对损坏数据文件的所有重做记录。用户就还有一种恢复方法,用户可以先将损坏的数据文件或表空间脱机 alter database datafile / tablespace xxx offline,之后执行alter database create datafile ‘new/xxx.dbf’ as ‘old/xxx.dbf’,数据库会根据保存在控制文件中的信息重建一个空的数据文件,之后再执行recover tablespace / datafile将所有重做记录运用到数据文件,使其完全恢复到当前状态,之后便可再将其恢复联机。

 


     如果丢失的是最后一种文件---归档文件或归档文件所处的物理位置不可用,首先shutdown数据库,立即作一个冷备份。然后修改ini文件中的归档日志文件目的路径,重新启动数据库。以后再发生灾难只需从最新的备份中将相关文件恢复,数据库作recover时就不需要备份之前丢失的归档文件了。在Oracle 8之后的新版本中提供了log_archive_duplex_dest和log_archive_dest_1...5等参数允许保留多份归档文件到不同位置,甚至到远端服务器从而保证归档文件的可靠性。

 


最后再说几点数据库恢复时的注意事项:


1.本文讨论所有情况的默认前提是数据库运行在归档(ARCHIVELOG)方式下,并只涉及到一般常见的情况和最基本的恢复方法。使用Oracle提供的恢复管理器RMAN也能完成上述任务,如果运行环境比较复杂建议使用RMAN来做备份和恢复。


2.一旦数据库发生灾难,最好在进行恢复之前做一次完全的冷备份,以便在进行恢复时产生差错还可以进行补救。很大一部分数据丢失是由于不正确的恢复操作所引起的。


3. 当数据库完成恢复之后,尤其是使用resetlogs选项打开数据库之后,要马上关闭数据库进行一次完全的冷备份。因为,为防止放弃的重做日志被下次恢复时再次运用,resetlogs选项会重新创建redo log文件并将其的计数清零,这将使之前做的所有备份将变为不可用(一般情况下)。


4.要特别注意当进行数据库完全恢复,从发生故障的时间点前的备份中恢复损坏文件时,一定不要使备份中的redo log文件覆盖了当前的redo log文件,否则就只能进行不完全恢复并且要丢失一部分数据了。


原作者:吴悦

7月30日

Squid配置(转)

     在此,我们要配置一个只对内部网络提供代理服务的Proxy Server。它将用户分为高级用户和普通用户两种,对高级用户采用网卡物理地址识别的方法,普通用户则需要输入用户名和口令才能正常使用。高级用户没有 访问时间和文件类型的限制,而普通用户只在上班时可以访问以及一些其它的限制。


安装
  可以从Squid站点www.squid-cache.org获取该软件的源代码,很多linux的发行版,如Red Hat提供的RPM。
squid在debian的安装:
      apt-get install squid
其他linux,RPM方式安装很简单,命令如下:
  $ rpm -ivh Squid-2.x.STALBx.i386.rpm

   不过笔者认为,即便是系统中已经默认安装了Squid,也应当先删掉然后安装最新的源代码包。因为开源软件会不断修正问题、提供更新的功能,使用最新版 本可以保证最高的性能及安全,而且源代码方式可以完全定制系统。不过STABLE稳定版、DEVEL版通常是提供给开发人员测试程序的,假定下载了最新的 稳定版squid-2.5.STABLE2.tar.gz,

debian下不需要删除原来的旧包,直接升级到最新版即刻   apt-get install squid,会安装最新版的squid软件包。

用以下命令解开压缩包:
$ tar xvfz squid-2.5.STABLE.tar.gz
  用bz2方式压缩的包可能体积更小,相应的命令是:
$ tar xvfj squid-2.5.STABLE.tar.bz2
  然后,进入相应目录对源代码进行配置和编译,命令如下:
$ cd squid-2.5.STABLE2

  配置命令configure有很多选项,如果不清楚可先用“-help”查看。通常情况下,用到的选项有以下几个:


--prefix=/web/squid
#指定Squid的安装位置,如果只指定这一选项,那么该目录下会有bin、sbin、man、conf等目录,而主要的配置文件此时在conf子目录中。为便于管理,最好用参数--sysconfdir=/etc把这个文件位置配置为/etc。


--enable-storeio=ufs,null
#使用的文件系统通常是默认的ufs,不过如果想要做一个不缓存任何文件的代理服
务器,就需要加上null文件系统。


--enable-arp-acl
#这样可以在规则设置中直接通过客户端的MAC地址进行管理,防止客户使用IP欺骗。


--enable-err-languages="Simplify_Chinese"
--enable-default-err-languages="Simplify_Chinese"
#上面两个选项告诉Squid编入并使用简体中文错误信息。


--enable-linux-netfilter
#允许使用Linux的透明代理功能。


--enable-underscore
#允许解析的URL中出现下划线,因为默认情况下Squid会认为带下划线的URL是
非法的,并拒绝访问该地址。

整个配置编译过程如下:

./configure --prefix=/var/squid
--sysconfdir=/etc
--enable-arp-acl
--enable-linux-netfilter
--enable-pthreads
--enable-err-language="Simplify_Chinese"
--enable-storeio=ufs,null
--enable-default-err-language="Simplify_Chinese"
--enable-auth="basic"
--enable-baisc-auth-helpers="NCSA"
--enable-underscore


  其中一些选项有特殊作用,将在下面介绍它们。
  最后执行make和make install两条命令,将源代码编译为可执行文件,并拷贝到指定位置。

 

基本配置
  安装完成后,接下来要对Squid的运行进行配置(不是前面安装时的配置)。所有项目都在squid.conf中完成。Squid自带的squid.conf包括非常详尽的说明,相当于一篇用户手册,对配置有任何疑问都可以参照解决。
  在这个例子中,代理服务器同时也是网关,内部网络接口eth0的IP地址为192.168.0.1,外部网络接口eth1的IP地址为202.103.x.x。

 

下面是一个基本的代理所需要配置选项:

  http_port 192.168.0.1:3128
  默认端口是3128,当然也可以是任何其它端口,只要不与其它服务发生冲突即可。为了安全起见,在前面加上IP地址,Squid就不会监听外部的网络接口。


  下面的配置选项是服务器管理者的电子邮件,当错误发生时,该地址会显示在错误页面上,便于用户联系:

cache_mgr start@soocol.com


  以下这些参数告诉Squid缓存的文件系统、位置和缓存策略:

cache_dir ufs /var/squid
cache_mem 32MB
cache_swap_low 90
cache_swap_high 95


   在这里,Squid会将/var/squid目录作为保存缓存数据的目录,每次处理的缓存大小是32兆字节,当缓存空间使用达到95%时,新的内容将取 代旧的而不直接添加到目录中,直到空间又下降到90%才停止这一活动。如果不想Squid缓存任何文件,如某些存储空间有限的专有系统,可以使用 null文件系统(这样不需要那些缓存策略):

cache_dir null /tmp


  下面的几个关于缓存的策略配置中,较主要的是第一行,即用户的访问记录,可以通过分析它来了解所有用户访问的详尽地址:

cache_access_log /var/squid/access.log
cache_log /var/squid/cache.log
cache_store_log /var/squid/store.log


  下面这行配置是在较新版本中出现的参数,告诉Squid在错误页面中显示的服务器名称:

visible_hostname No1.proxy


  以下配置告诉Squid如何处理用户,对每个请求的IP地址作为单独地址处理:

client_mask 255.255.255.255

 


  如果是普通代理服务器,以上的配置已经足够。但是很多Squid都被用来做透明代理。所谓透明代理,就是客户端不知道有代理服务器的存在,当然也不需要进行任何与代理有关的设置,从而大大方便了系统管理员。相关的选项有以下几个:

httpd_accel_host virtual
httpd_accel_port 80
httpd_accel_with_proxy on
httpd_accel_user_host_header on


  在Linux上,可以用iptables/ipchains直接将对Web端口80的请求直接转发到Squid端口3128,由Squid接手,而用户浏览器仍然认为它访问的是对方的80端口。例如以下这条命令:

iptables -t nat -A PREROUTING -s 192.168.0.200/32 -p tcp --dport 80 -j REDIRECT 3128
  就是将192.168.0.200的所有针对80端口的访问重定向到3128端口。


   所有设置完成后,关键且重要的任务是访问控制。Squid支持的管理方式很多,使用起来也非常简单(这也是有人宁愿使用不做任何缓存的Squid,也不 愿意单独使用iptables的原因)。Squid可以通过IP地址、主机名、MAC地址、用户/密码认证等识别用户,也可以通过域名、域后缀、文件类 型、IP地址、端口、URL匹配等控制用户的访问,还可以使用时间区间对用户进行管理,所以访问控制是Squid配置中的重点。Squid用ACL (Access Control List,访问控制列表)对访问类型进行划分,用http_access deny 或allow进行控制。根据需求首先定义两组用户advance和normal,还有代表所有未指明的用户组all及不允许上网的baduser,配置代 码如下:


acl advance 192.168.0.2-192.168.0.10/32
acl normal src 192.168.0.11-192.168.0.200/32
acl baduser src 192.168.0.100/32
acl baddst dst www.soocol.com
acl all src 0.0.0.0/0
http_access deny baduser
http_access allow advance
http_access allow normal

 

可以看出,ACL的基本格式如下:
  acl 列表名称 控制方式 控制目标
  比如acl all src 0.0.0.0/0,其名称是all,控制方式是src源IP地址,控制目标是0.0.0.0/0的IP地址,即所有未定义的用户。出于安全考虑,总是在最后禁止这个列表。

  下面这个列表代表高级用户,包括IP地址从192.168.0.2到192.168.0.10的所有计算机:
acl advance 192.168.0.2-192.168.0.20/32

  下面这个baduser列表只包含一台计算机,其IP地址是192.168.0.100:
acl baduser 192.168.0.100/32


  ACL写完后,接下来要对它们分别进行管理,代码如下:

http_access deny baduser
http_access allow advance
http_access allow normal

   上面几行代码告诉Squid不允许baduser组访问Internet,但advance、normal组允许(此时还没有指定详细的权限)。由于 Squid是按照顺序读取规则,会首先禁止baduser,然后允许normal。如果将两条规则顺序颠倒,由于baduser在normal范围中, Squid先允许了所有的normal,那么再禁止baduser就不会起作用。

  特别要注意的是,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”。

 

  高级控制

  前面说过,Squid的控制功能非常强大,只要理解Squid的行为方式,基本上就能够满足所有的控制要求。下面就一步一步来了解Squid是如何进行控制管理的。
  通过IP地址来识别用户很不可靠,比IP地址更好的是网卡的MAC物理地址。要在Squid中使用MAC地址识别,必须在编译时加上“--enable-arp-acl”选项,然后可以通过以下的语句来识别用户:

acl advance arp 00:01:02:1f:2c:3e 00:01:02:3c:1a:8b ...


  它直接使用用户的MAC地址,而MAC地址一般是不易修改的,即使有普通用户将自己的IP地址改为高级用户也无法通过,所以这种方式比IP地址可靠得多。
  假如不想让用户访问某个网站应该怎么做呢?可以分为两种情况:一种是不允许访问某个站点的某个主机,比如ok的主机是ok.sina.com.cn,而其它的新浪资源却是允许访问的,那么ACL可以这样写:


acl sinapage dstdomain ok.sina.com.cn
... ...
http_access deny ok
... ...


  由此可以看到,除了ok,其它如www.sina.com.cn、news.sina.com.cn都可以正常访问。


  另一种情况是整个网站都不许访问,那么只需要写出这个网站共有的域名即可,配置如下:

acl qq dstdomain .tcccent.com.cn

  注意tcccent前面的“.”,正是它指出以此域名结尾的所有主机都不可访问,否则就只有tcccent.com.cn这一台主机不能访问。


  如果想禁止对某个IP地址的访问,如202.118.2.182,可以用dst来控制,代码如下:

acl badaddr dst 202.118.2.182

 当然,这个dst也可以是域名,由Squid查询DNS服务器将其转换为IP。


  还有一种比较广泛的控制是文件类型。如果不希望普通用户通过代理服务器下载MP3、AVI等文件,完全可以对他们进行限制,代码如下:

acl mmxfile urlpath_regex \.mp3 \.avi \.exe
http_access deny mmxfile

  看到regex,很多读者应该心领神会,因为这条语句使用了标准的规则表达式(又叫正则表达式)。它将匹配所有以.mp3、.avi等结尾的URL请求,还可以用-i参数忽略大小写,例如以下代码:

acl mmxfile urlpath_regex -i \.mp3

  这样,无论是.mp3还是.MP3都会被拒绝。当然,-i参数适用于任何可能需要区分大小写的地方,如前面的域名控制。


  如果想让普通用户只在上班时间可以上网,而且是每周的工作日,用Squid应当如何处理呢?看看下面的ACL定义:

acl worktime time MTWHF 8:30-12:00 14:00-18:00
http_access deny !worktime

  首先定义允许上网的时间是每周工作日(星期一至星期五)的上午和下午的固定时段,然后用http_access 定义所有不在这个时间段内的请求都是不允许的。
  或者为了保证高级用户的带宽,希望每个用户的并发连接不能太多,以免影响他人,也可以通过Squid控制,代码如下:

acl conncount maxconn 3
http_access deny conncount normal
http_access allow normal

  这样,普通用户在某个固定时刻只能同时发起三个连接,从第四个开始,连接将被拒绝。
  总之,Squid的ACL配置非常灵活、强大,更多的控制方式可以参考squid.conf.default。


  认证
  用户/密码认证为Squid管理提供了更多便利,最常用的认证方式是NCSA。从Squid 2.5版本开始,NCSA认证包含在了basic中,而非以前单独的认证模块。下面来看看实现认证的具体操作。


  首先在编译时配置选项应包括以下配置:

--enable-auth="basic" --enable-basic-auth-helpers="NCSA"


   “make install”以后,需要将“helpers/basic_auth/NCSA/ncsa_auth”拷贝到用户可执行目录中,如/usr/bin(如 果在该目录中找不到这个执行文件,在编译时请使用make all而不是make,或者直接在该目录中执行make),然后需要借助Apache的密码管理程序htpasswd来生成用户名/密码对应的文件,就像 下面这行代码:

htpasswd -c /var/squid/etc/password guest

  在输入两遍guest用户的密码后,一个guest用户就生成了。如果以后需要添加用户,把上面的命令去掉-c参数再运行即可。
  Squid 2.5在认证处理上有了较大的改变,这里就只讨论2.5版本的处理方法,2.4及以下版本请参考squid.conf.default。在2.5版的squid.conf中,包括以下几个相关选项:

#该选项指出了认证方式(basic)、需要的程序(ncsa_auth)和
对应的密码文件(password)
auth_param basic program /usr/bin/ncsa_auth /var/squid/etc/password
# 指定认证程序的进程数
auth_param basic children 5
# 浏览器显示输入用户/密码对话框时的领域内容
auth_param basic realm My Proxy Caching Domain
# 基本的认证有效时间
auth_param basic credentialsttl 2 hours
# 普通用户需要通过认证才能访问Internet
acl normal proxy_auth REQUIRED
http_access allow normal


   通过以上的配置即可完成认证工作。有的读者可能要问:认证只针对普通用户,而高级用户是直接上网的,该怎么处理呢?其实,这两种用户是可以共存的。如前 所述,Squid是顺序处理http_access的,所以在http_access处理过程中,如果先处理normal用户,那么当前用户无论是否属于 高级用户,都会被要求进行认证;相反如果先处理高级用户,剩下的就只有需要认证的普通用户了。例如以下配置代码:

...
http_access allow normal (需要认证)
http_access allow advance (不需要认证)
...
  不管是否为noauth用户,都要求进行用户名/密码验证。正确的方法是将二者位置交换,代码如下:
...
http_access allow advance
http_access allow normal
...
  这时,高级用户不会受到任何影响。

  总结
  下面把整个squid.conf总结一下:


# 服务器配置
http_port 192.168.0.1:3128
cache_mgr start@soocol.com
cache_dir null /tmp
cache_access_log /var/squid/access.log
cache_log /var/squid/cache.log
cache_store_log /var/squid/store.log
visible_hostname No1.proxy
client_mask 255.255.255.255
httpd_accel_host virtual
httpd_accel_port 80
httpd_accel_with_proxy on
httpd_accel_user_host_header on


# 用户分类
acl advance arp 00:01:02:1f:2c:3e 00:01:02:3c:1a:8b ...
acl normal proxy_auth REQUIED
acl all src 0.0.0.0


# 行为分类
acl mmxfile urlpath_regex \.mp3 $ \.avi $ \.exe $
acl conncount maxconn 3
acl worktime time MTWHF 8:30-12:00 14:00-18:00
acl sinapage dstdomain ok.sina.com.cn
acl qq dstdomain .tcccent.com.cn


# 处理
http_access allow advance
http_access deny conncount normal
http_access deny !worktime
http_access deny mmxfile
http_access deny sinapage
http_access deny qq
http_access allow normal


  配置后的状况是,advance组可以不受任何限制地访问Internet,而normal组则只能在工作时间上网,而且不能下载多媒体文件,不能访问某些特定的站点,而且发送请求不能超过3个。
  通过本文的介绍,它可以了解Squid的基本能力。当然,它的能力远不止此,可以建立强大的代理服务器阵列,可以帮助本地的Web服务器提高性能,可以提高本地网络的安全性等。要想发挥它的功效,还需要进一步控制。

4月27日

Apache+SSL+SVN+SSPI

用到的程序:

apache_2.0.59-win32-x86-no_ssl.msi

Apache_2.0.59-Openssl_0.9.8b-Win32.zip

Openssl-0.9.8b-Win32.zip

Setup-Subversion-1.5.3.msi

 

参考了网络上大量的文章 实际操作了一遍,其实openssl的命令有很多种方式可以生成crt文件以及pem文件 我采用的只是一种最直观比较完整的一个方案。当然也算比较繁琐的一种。

 

 

======安装apache========

 

一、安装 apache_2.0.59-win32-x86-no_ssl.msi

 

 

 

======设置SSL模组=======

 

 

二、解压 Apache_2.0.59-Openssl_0.9.8b-Win32.zip  完整覆盖原Apache

三、生成证书文件

解压Openssl-0.9.8b-Win32.zip,假设至目录E:\OpenSSL。
拷贝openssl.cnf至目录E:\OpenSSL,并修改CA_Default部分如下:


                dir = ssl
                certs = $dir\\certs
                crl_dir = $dir\\crl
                database = $dir\\index.txt
                new_certs_dir = $dir
                certificate = $dir\\cacert.pem
                serial = $dir\\serial
                crl = $dir\\crl.pem
                private_key = $dir\\privkey.pem
                RANDFILE = $dir\\privkey.rnd (MS单反斜杠也可以)


在E:\OpenSSL目录下新建文件夹ssl,在其中分别建立index.txt文件(内容任意)和serial文件(内容01)

       )))Error:
                I am unable to access the ./xxx/certs directory

               Solution
               创建上述文件。


              

 

在命令行下切换至E:\OpenSSL依次运行下边的命令:

 


        openssl genrsa -des3 -out ssl/ca.key 1024
                           产生 CA private key
        openssl req -config openssl.cnf -new -key ssl/ca.key -out ssl/ca.csr    
                           产生CA require cert,照说明填入相关资料
        openssl x509 -days 3650 -req -signkey ssl/ca.key -in ssl/ca.csr -out ssl/ca.crt
                           产生CA public cert

 


        openSSL genrsa -out ssl/server.key 1024
                           产生Server private key
        openssl req -config openssl.cnf -new -key ssl/server.key -out ssl/server.csr
                           产生Server require cert,资料据说最好要和上边相同
        openssl ca -config openssl.cnf -days 3650 -cert ssl/ca.crt -keyfile ssl/ca.key -in ssl/server.csr –out ssl/server.crt

                   产生Server public key

 

openSSL genrsa -out ssl/client.key 1024

openssl req -config openssl.cnf -new -key ssl/client.key -out ssl/client.csr

openssl ca -config openssl.cnf -days 3650 -cert ssl/ca.crt -keyfile ssl/ca.key -in ssl/client.csr -out  ssl/client.crt 

openssl pkcs12 -export -clcerts -inkey ssl/client.key -in ssl/client.crt -out ssl/client.p12
                    产生客户证书

 

以上命令在ssl文件夹下生成ca.crt、server.crt、server.key、client.key、client.csr、client.crt、client.p12文件   
    ca和server文档 复制到Apache安装目录下conf目录下建立的ssl文件夹中。
    client.p12复制给客户。

 


        注意:在上边两步填写资料时,

        )))Error: 
                 在Apache的错误日志中发现错误为“ 证书和服务器名称不匹配”
                 SA server certificate CommonName (CN) `127.0.0.1' does NOT match server name!?

         Solution
         Common Name (eg, your websites domain name) []要填的和httpd.conf中的一样,否则会出错,
                          可以考虑使用本地IP地址

)))Error:
         SSLPassPhraseDialog built-in is not supported on Win32

           Solution
          
When generating a Secure Socket Layer (SSL) key file, do not enter a challenge password.

 

 

四、修改ssl.conf 配置文档:

DocumentRoot "c:/apache/htdocs"                      #修改路径
ServerName www.example.com:443                   #可以改成 本机地址:443 尽量保持与Common Name一致
ServerAdmin you@example.com                            
ErrorLog logs/error_log
TransferLog logs/access_log                                 #可以根据需要修改
SSLCertificateFile conf/ssl.crt/server.crt                 #注意证书路径
SSLCertificateKeyFile conf/ssl.key/server.key        #注意证书路径
SSLMutex  file:logs/ssl_mutex为SSLMutex  default
SSLCertificateChainFile conf/ssl.crt/ca.crt                #注意证书路径
注释掉<IfDefine SSL>和</IfDefine>开启SSL功能


五、修改httpd.conf:

      去掉

         #LoadModule ssl_module modules/mod_ssl.so  

           的注释。

      如果域名无法使用的话,可能需要把httpd.conf中的ServerName改为:127.0.0.1:端口。

六、测试:https://127.0.0.1/

 

 

=====安装SVN模组========

 

七、安装Subversion

八、修改httpd.conf:

去掉

   #LoadModule dav_fs_module modules/mod_dav_fs.so
   #LoadModule dav_module modules/mod_dav.so

     的注释

 

添加

LoadModule dav_svn_module "C:/Program Files/Subversion/bin/mod_dav_svn.so"
LoadModule authz_svn_module "C:/Program Files/Subversion/bin/mod_authz_svn.so"

 

添加

<Location /svn>
DAV svn
SVNParentPath c:/svn
AuthType Basic
AuthName "Subversion repository"
AuthUserFile c:/auth/auth
#AuthzSVNAccessFile c:/auth/access
SSLRequireSSL
Require valid-user
</Location>

 

九、创建认证文档

 

        htpasswd –c c:\auth\auth zzz

 

 

文件/home/svn/access内容示例

[groups]
admin = aaa
team = bbb,ccc
LAI = ddd
AIP = eee

[test:/]
aaa = rw
@LAI = r
@AIP = r

[test:/01Source]
@team = rw
@LAI = rw
* =

[test:/02Public]
@team = rw
* =

 

==========安装SSPI模组==============

 

十、SSPI

拷贝mod_auth_sspi.so文件

 

httpd.conf下添加

LoadModule sspi_auth_module modules/mod_auth_sspi.so

 

<Location /svn>
DAV svn
SVNParentPath c:/svn
AuthType SSPI
AuthName "Subversion repository"
#AuthUserFile c:/auth/auth
AuthzSVNAccessFile c:/auth/accessfilesspi
Require valid-user
SSLRequireSSL
SSPIAuth On
SSPIAuthoritative On
SSPIDomain eocsh
SSPIOfferBasic On
</Location>

 

另一边复制过来的注释 还蛮详细的。转自:http://www.sunky.net/archives/2008/163.html

在httpd.conf文件最后加上 (蓝色部分为注释,可以删除)

#这里设置成”/svn/”访问版本库的网址就是http://localhost/svn/,
#如果设置成”/”访问网址就是http://localhost
<Location /svn/>
DAV svn
#列出根目录下的所有项目
SVNListParentPath on
#版本库目录,请参照修改。
SVNParentPath E:/svnroot
#目录访问权限控制文件,现指向与httpd.conf同目录
AuthzSVNAccessFile conf/access.conf
#认证对话框提示信息。最好使用英文
AuthName “ZyXEL VOIP”
#SSPI表示使用域验证
AuthType SSPI
SSPIAuth On
SSPIAuthoritative On
#指定Windows域。ZYCN是我们公司Windows域,请对照修改
SSPIDomain ZYCN
#省略用户id前的域名部分,需要注意的是如果这个选项打开,
#那么access.conf里面的用户id也不能带域名,
#如果这个选项关闭,那么用户id就需要带域名。此外,这个选项影响到Apache的log。
#这里有一个技巧就是如果你不能确定你所处的域,你可以将此选项置为off,
#然后尝试从Web登陆,查看Apache的error.log,可以发现log会自动给用户id加上现处的域,
#这样就可以确定自己所处的域SSPIDomain.

SSPIOmitDomain on
# 是否允许非IE客户端(必须打开)
SSPIOfferBasic On
# 关闭几本验证方式,如果需要多重验证可以打开。
SSPIBasicPreferred Off
# 用户名大小写,由于目录访问权限控制文件AuthzSVNAccessFile,
#也就是access.conf里的用户id用大小写敏感,而在Windows的世界里大小写是一致的。
#所以我们有必要统一大小写规范。当这个选项设置为lower时,
#你必须把access.conf里的用户id也统一设置为小写,否则验证将会失败。

SSPIUsernameCase lower
# 用户必须通过认证,就是要求所有用户必须通过验证才能登陆SVN.
#至于Require group “ZYCN\wx-sw1″组验证问题稍候再谈。

Require valid-user
#Require group “ZYCN\wx-sw1″
</Location>

然后需要配置D:\Program Files\Apache Software Foundation\Apache2.2\conf\access.conf

access.conf默认是不存在的,需要自行创建。下面给出access.conf文件内容

[groups]
admins = w00666, w00777

[/]
@admins = rw

上面的w00768就是用户id, 注意全部小写,并且当SSPIOmitDomain on时用户id前不要加域名. 更精确的目录权限控制你可以参考其他文档。

 

 

 

==================================

########################

==================================

 

OK,finished.

以上。

12月31日

Vsftpd 530 Login incorrect


vi /etc/vsftpd/vsftpd.conf

anonymous_enable=NO
userlist_enable=YES
userlist_deny=NO
userlist_file=/etc/vsftpd.user_list
local_enable=YES
write_enable=YES
pam_service_name=vsftpd

 

Also check:

/etc/vsftpd.user_list 
/etc/vsftpd.chroot_list
/etc/ftpusers
/etc/pam.d/vsftpd

配置整合Win+Apache+PHP+CGI+MySQL+Tcomcat(或Resin)完全手册(转)(擅自添加了CGI部分~呵呵)

前期准备:

所需软件列表:(本配置以下列软件版本完成)
1、 APACHE_2.0.47-win32-x86-no_ssl       (Apache web服务器)
2、 PHP-4.3.3-Win32                              (PHP语言解析器)
3、 ActivePerl-5.10.0.1004-MSWin32-x86   (ActivePerl编译器)
4、 MySQL-4.0.12-win                            (MySQL数据库)
5、 j2sdk-1_4_2-windows-i586                 (JAVA 语言环境)
6、 Jakarta-Tomcat-5.0.9                        (Tomcat JSP解析服务器)
7、 Resin-3.0.3                                      (Resin JSP解析服务器)
8、 mod_jk_1.2.5_2.0.47.dll                     (整合Apache+Tomcat的plus)
9、 mm.mysql-2.0.4-bin.jar                      (JSP访问连接MySQL文件)

  

开始安装:


一、 Apahce+PHP+CGI+MySQL安装配置

1. 安装APACHE_2.0.47-win32-x86-no_ssl ,程序默认安装路径为:C:\apache2\program files\apache Group\ ,需要将其安装路径修改为:C:\
(也可以不做修改,主要为了修改配置方便做修改的)。

     #寻找到ServerName。这里定义你的域名。这样,当Apache Server运行时,你可以在浏览器中访问自己的站点。如果前面有#,记得删除它,这是conf的注释标记。
  #寻找到ServerAdmin。这里输入你的E-Mail地址。如果你仅仅是单机使用,改不改没什么关系。
  #寻找到Directory。向下有一句Options,去掉后面所有的参数,加一个All(注意区分大小写!下同。);接着还有一句Allow Override,也同样去掉后面所有的参数,加一个All。
  #寻找到DocumentRoot。这个语句指定你的网站路径,也就是你主页放置的目录。你可以使用默认的,也可以自己指定一个,但记住,这句末尾不要""。此外注意,目录的""在Apache Server里写成"/"。
  #寻找到DirectoryIndex。这就是你站点第一个显示的主页。

2. 安装完成之后,apache服务自动加载,这时打开浏览器,浏览:http://localhost,出现apache欢迎页面(这步需要将C:\apache2\htdocs目录中的文件“index.html.en”改为“index.html”,方能显示);如果这步出现异常,请检查安装源文件,重新安装。

3. 安装PHP-4.3.3-Win32,一般下载的PHP文件为一个免安装的压缩包,解压到C:\PHP就可以。

4. 配置PHP和Apache,使之能解析php程序。
    PHP配置:将C:\PHP\目录中的“php.ini-dist”改名“php.ini”并复制到C:\windows\system32
    Apache配置:C:\apahce2\conf\httpd.conf

httpd.conf
在此配置文件最后添加以下语句,用以支持php程序:
    ScriptAlias /php/ "C:/PHP/"
    AddType application/x-httpd-php .php3
    AddType application/x-httpd-php .php
    AddType application/x-httpd-php .phtml
    Action application/x-httpd-php "/php/php.exe"

5.重新启动Apache服务器,用编辑器编写如下语句:           
    <?
       phpinfo();
    ?>
    保存文件名为“test.php”到C:\apache2\htdocs目录,然后打开浏览器,浏览:http://localhost/test.php,

    出现PHP基本信息就说明配置成功。严格按以上说明安装配置,都会一次成功。

6. 安装ActivePerl

  httpd.conf

     寻找到ScriptAlias /cgi-bin/ "C:/Apache/cgi-bin/"。删除前面的#,将""中的路径指向你存放CGI脚本的目录,也就是,这个目录中的CGI脚本可以被执行。
  寻找到Directory。将""中的路径指向你存放CGI脚本的目录,要与上面的相同。更改Options、Allow Override的参数为All。
  寻找到AddHandler cgi-script .cgi。删除前面的#,在后面加上 .pl。
     注意: CGI脚本中的Perl解释路径改为:#!C:perlbinperl。否则,会出现500错误。

6. 安装MySQL-4.0.12-win,一直按”next”就安装成功了,然后在C:\mysql\bin目录执行” winmysqladmin.exe”,出现mysql的初始信息面,表示安装成功。

7. PHP连MySQL此处略过,一般没有什么问题。

到此可以休息一下,准备下面的漫长过程……

二、安装JDK和Tomcat

1. 安装j2sdk-1_4_2-windows-i586,JDK一定要在Tomcat和Resin之前安装,默认安装路径就可以。

2. 安装Jakarta-Tomcat-5.0.9,默认安装路径就可以。

3. 复制mm.mysql-2.0.4-bin.jar文件分别到C:\j2sdk1.4.2\lib 和 C:\Tomcat 5.0\common\lib

4.设置环境变量(桌面->我的电脑->右键点击->选择“属性”->高级->环境变量),所有设置均在系统变量栏进行。
新建->变量名:JAVA_HOME
    ->变量值:C:\j2sdk1.4.2
新建->变量名:TOMCAT_HOME
    ->变量值:C:\Tomcat 5.0
新建->变量名: PATH
    ->变量值:.;C:\j2sdk1.4.2\bin;  (前面的“.;”一定要有)
修改增加环境变量 CLASSPATH (如果没有此变量名,则新建)
    ->增加变量值:.;C:\j2sdk1.4.2\lib\dt.jar;C:\j2sdk1.4.2\lib\tool.jar;
C:\j2sdk1.4.2\lib\NetComponents.jar;
C:\j2sdk1.4.2\lib\mm.mysql-2.0.4-bin.jar;
C:\Tomcat 5.0\common\classes;
C:\Tomcat 5.0\common\lib;
C:\Tomcat 5.0\common\lib\servlet-api.jar;
(前面的“.;”一定要有)

5. 启动Tomcat服务器,打开浏览器,浏览:http://localhost:8080/ ,出现Tomcat欢迎页面;

    如果这步出现异常,请检查安装源文件,重新安装。

 

三、整合Apache+Tomcat服务器

1. 复制mod_jk_1.2.5_2.0.47.dll文件到C:\Apache2\modules目录。

2. Apache配置:C:\apahce2\conf\httpd.conf

    httpd.conf
      在此配置文件最后添加以下语句,用以支持jsp程序:
        LoadModule jk_module modules/mod_jk_1.2.5_2.0.47.dll
        JkWorkersFile "C:/Tomcat 5.0/conf/workers.properties"
        JkMount /servlet/* ajp13
        JkMount /*.jsp ajp13

3. 查看C:\Tomcat 5.0\conf\server.xml文件中有关端口“8009”是否被注释,
    如果是和我这的版本一致的话,不用修改。

4. 在C:\Tomcat 5.0\conf\目录下,新建文件名为“workers.properties”的文件,将如下内容复制到新建文件workers.properties中。

workers.properties
  # 只复制以下内容即可:

  # 这现行根据安装目录做修改
  workers.tomcat_home=C:\Tomcat 5.0
  workers.java_home=C:\j2sdk1.4.1_01
  ps=\
  # worker.list=ajp13
  worker.list=ajp12,ajp13 

  worker.ajp12.port=8007
  worker.ajp12.host=localhost
  worker.ajp12.type=ajp12
  worker.ajp12.lbfactor=1
  worker.ajp13.port=8009        
  worker.ajp13.host=localhost     
  worker.ajp13.type=ajp13
  worker.ajp13.lbfactor=1

  worker.loadbalancer.type=lb
  worker.loadbalancer.balanced_workers=ajp12, ajp13
  worker.inprocess.type=jni
  worker.inprocess.class_path=$(workers.tomcat_home)$(ps)classes
  worker.inprocess.class_path=$(workers.tomcat_home)$(ps)lib$(ps)jaxp.jar
  worker.inprocess.class_path=$(workers.tomcat_home)$(ps)lib$(ps)parser.jar
  worker.inprocess.class_path=$(workers.tomcat_home)$(ps)common$(ps)lib$(ps)jasper.jar
  worker.inprocess.class_path=$(workers.tomcat_home)$(ps)common$(ps)lib$(ps)servlet.jar
  worker.inprocess.class_path=$(workers.tomcat_home)$(ps)common$(ps)lib$(ps)webserver.jar
  worker.inprocess.class_path=$(workers.java_home)$(ps)lib$(ps)tools.jar
  worker.inprocess.cmd_line=-config
  worker.inprocess.cmd_line=$(workers.tomcat_home)/conf/jni_server.xml
  worker.inprocess.cmd_line=-home
  worker.inprocess.cmd_line=$(workers.tomcat_home)
  worker.inprocess.jvm_lib=$(workers.java_home)$(ps)jre$(ps)bin$(ps)classic$(ps)jvm.dll
  worker.inprocess.stdout=$(workers.tomcat_home)$(ps)inprocess.stdout
  worker.inprocess.stderr=$(workers.tomcat_home)$(ps)inprocess.stderr
  worker.inprocess.sysprops=tomcat.home=$(workers.tomcat_home)

5. 到此Apache 和 Tomcat整合完成,重启Apache和Tomcat服务器,

用编辑器编写如下内容:

<%@ page contentType="text/html;charset=gb2312"%>

<html>
<head>
<title>HI-JSP实验</title>
</head>
<body>
<%
  String Msg = "This is JSP test! 看到这段话,恭喜你,成功了!"; 
  out.print("Hello World!");
%>
<h3><%=Msg%></h3>
The current date and time is <%=new java.util.Date() %>
<br>
<%
  String str = "Using trim() and substring() can be very useful";
  out.println(str);
%>
</body>
</html>

保存文件名为“test.jsp”到C:\Tomcat 5.0\webapps\ROOT目录,然后打开浏览器,浏览:http://localhost:8080/test.jsp,如果显示正常,然后将地址改为:http://localhost/test.jsp  显示正常说明配置成功。严格按以上说明安装配置,都会一次成功。

 

四、整合Apache+Tomcat+MySQL

      这步相对简单许多,但也是最不容易成功的部分,前面已经将JSP的MySQL驱动放到相应的目录中,环境变量也设置,所以只是测试JSP是否可以连接MySQL数据库。

      1. 测试1,用编辑器编写如下内容:

<%@ page contentType="text/html;charset=gb2312" %>
<%
java.sql.Connection conn;
java.lang.String strConn;
Class.forName("org.gjt.mm.mysql.Driver").newInstance();
conn= java.sql.DriverManager.getConnection("jdbc:mysql://localhost/test","root","");
%>

注:数据库此处为:test 连接数据库存的用户名为:root  密码为空。根据自己数据库作相应修改。

保存文件名为“test-mysql.jsp”到C:\Tomcat 5.0\webapps\ROOT目录,然后打开浏览器,浏览:http://localhost:8080/test-mysql.jsphttp://localhost/test-mysql.jsp ,运行后,如果显示为空白页面,说明连接数据库成功,否则说明没有连接成功,请往回逐步仔细配置。

      2. 测试2,用编辑器编写如下内容:

<%@ page contentType="text/html;charset=GBK" %>
<%@ page language="java" import="java.sql.*"%>
<%
Connection conn = null;
Class.forName("org.gjt.mm.mysql.Driver").newInstance();
conn = java.sql.DriverManager.getConnection("jdbc:mysql://localhost/test","root","");
if(conn==null){
System.out.println("get Conn Error");
}
Statement stmt=conn.createStatement();
ResultSet RS_result=null;
%>
<html>
<head>
<title>测试</title></head>
<body>
<%
RS_result=stmt.executeQuery("select * from guestbook");
String Name;
while(RS_result.next())
{
Name=RS_result.getString("name");
%>
<%=Name%>
<%
}
RS_result.close();
stmt.close();
conn.close();
%>
</body>
</html>

保存文件名为“test-mysql2.jsp”到C:\Tomcat 5.0\webapps\ROOT目录,然后打开浏览器,浏览:http://localhost:8080/test-mysql2.jsphttp://localhost/test-mysql2.jsp ,运行后。

 

五、安装Resin,整合Apache+Resin

1. 假定机子上现在没有启动别的JSP解析服务器,如果启动请关闭该服务。

2. 直接解压Resin-3.0.3.zip到C:\

3. 在字符模式下用命令:C:\resin-3.0.3\bin\httpd –install
将Resin安装为系统的一个服务,然后在服务中启动Resin.
删除服务命令:C:\resin-3.0.3\bin\httpd –remove

4. 打开浏览器,浏览:http://localhost:8080 ,如果显示有Resin信息,则Resin服务已经启动 。

5. Apache配置:C:\apahce2\conf\httpd.conf

httpd.conf
在此配置文件最后添加以下语句:

    LoadModule caucho_module C:/resin-3.0.3/libexec/apache-2.0/mod_caucho.dll

    <IfModule mod_caucho.c>
      ResinConfigServer localhost 6802
      <Location /caucho-status>
      SetHandler caucho-status
      </Location>
    </IfModule>

    AddHandler caucho-request jsp
    <Location /servlet/*>
     SetHandler caucho-request
    </Location>

      保存,重启apache.

      6. Resin配置:
        C:\resin-3.0.3\conf\resin.conf

resin.conf
修改默认目录,红色部分为修改内容:
<server>
  <host id="">
    <document-directory>C:\Apache2\htdocs</document-directory>
    ...
  </host>
</server>

      完成后保存,重启Resin服务,把编辑好的JSP文件存放到C:\Apache2\htdocs目录,然后打开浏览器浏览,就可以在PHP和JSP之间自由窜越了。

12月29日

登录中文搜索引擎入口(转)

转贴地址http://guxqcn.spaces.live.com/blog/cns!CA0B3E9C258483D0!1517.entry

 

登录搜索引擎是推广网站很重要的一步。为了方便大家,整理了主要搜索引擎,希望对大家有帮助。以下地址都经过了测试,可以使用,若您在使用时发现死链接,请通知我们,以便更好的为大家服务。同时也欢迎大家推荐好的搜索引擎,在留言本中给我留言就可以了。另外要指出的是,贡献流量的主要是几个著名的搜索引擎,其它的对流量贡献微乎其微。如果您时间不多,大可不必全部登录。当然,如果时间充足,又没有很多推广经费,登录一下也大有好处。

 

百度免费登录入口 http://www.baidu.com/search/url_submit.htm

Google免费登录入口 http://www.google.com/intl/zh-CN/add_url.html

雅虎免费登录入口 http://search.help.cn.yahoo.com/h4_4.html

Live Search登录入口:http://search.msn.com.cn/docs/submit.aspx

新浪免费登录入口 http://bizsite.sina.com.cn/newbizsite/docc/index-2jifu-09.htm

搜狐免费登录入口 http://db.sohu.com/regurl/regform.asp?Step=REGFORM&class=

天网免费登录入口 http://bingle.pku.edu.cn/submit.htm

慧聪行业免费登录入口 http://202.108.33.161/web/frontward/free/free_speedlogin.asp

搜豹免费登录入口 http://search.sobao.com/Computers_and_Internet/Personal/

焦点网免费登录入口 http://search.focus.com.cn/search/search_newurl_register.ecgi

协通免费登录入口 http://www.net2asp.com.cn/search/regform.htm

银河免费登录入口 http://search.inhe.net/navigate.asp

中国假日免费登录入口 http://www.china-holiday.com/newterms/hall/it/sort.asp?sortid=259

山西互连网免费登录入口 http://www.shanxi.net.cn/sxhulian/addcate.asp

网络奇兵登陆入口http://www.net7b.com/net7b_site/denglu/index.asp

6128搜索引擎免费登陆入口http://www.6128.cn/add.htm

深圳网狐登陆入口 http://www.szfox.com/search/

中国搜索同盟免费登录入口 http://service.chinasearch.com.cn/w ... ree/free_protocol.htm

北极星免费登录入口 http://www.beijixing.com.cn/bjx01/search/regi_1.asp

亦凡信息娱乐网络-亦凡搜索 http://www.gotofind.com/opendir/

法律网免费登录入口 http://www.law-lib.com/lawseek/wzdl.asp

银河免费登录入口 http://search.inhe.net/navigate.asp

温州信息港免费登录入口 http://www.wzonline.com.cn/

建设免费登录入口http://www.cnjjl.com/other/

孙悟空免费登录入口 http://www.sunwukong.cn/add.php

猫头鹰 http://www.owlchina.com/publish.asp?l=pub

凯希 http://www2d.biglobe.ne.jp/~kinryou/cgi/url.html

ebsee http://www.ebsee.com/cgi-bin/find/find.cgi?menu=add

focus http://search.focus.com.cn/search/search_newurl_register.ecgi

zhao5.com登陆入口 http://www.zhao5.com/deng_9.htm

三百六十行在线登陆入口 http://www.360hang.com/

中国168免费登录入口 http://www.china168.com/chaoshi/it/regsta1.asp?sortid=242

中国车网免费登录入口 http://www.cncar.net/search/addsite.asp

绿界免费登录入口 http://ep.sunup.net/add.php

天上人间中文搜索引擎 http://www.6mj.com/search/

企业搜索引擎 http://www.shengdarealestate.com.cn/search/sort.asp?sortid=37

好东西网址登陆 http://dir.haodx.com/computer/internet/search/search_egines/

中国搜索登陆入口 http://service.chinasearch.com.cn/zhongsou/wzdl/free_protocol.htm

网讯快车 http://www.ne163.com/

广东阳江在线 http://www.gdyj.com/

泰达搜索引擎 http://www.tedanet.com/search/index.asp

Y28 Search http://www.y28.com/cgi-bin/link/join.pl  Guxqcn 10/15/06, 11:30am

12月22日

Apache下的SVN自定义日志

 

svn log配置

最近经济不景气,老板真是越抓越严 现在连svn的登录日志也要记录检查~

   原本svn自带的那个access.log基本不太能够阅读 所以打算再自制一个log文档

   svn在apache下运行要用到mod_dav mod_dav_svn mod_authz_svn几个模块

   日志模块是mod_log_config

 

~~~~~~~

 

svn在1.4之后的版本都支持内建的svn类log 公司用的是1.2~所以要先svn升级 找个安装包直接覆盖安装就可以了

 

然后在httpd.conf文档里增加

CustomLog logs\svn_log "%t %a %u \"%{SVN-ACTION}e\" " env=SVN-ACTION

 

前面几个参数都没问题 就是%e这个就是通过设置环境变量env 为SVN-ACTION 来使得日志变得更可读,ok了

   记录出来的样子如下

[22/Dec/2008:11:53:57 +0800] 172.17.3.193 EOCSH\\xh "update / r2302 send-copyfrom-args"
develop\\wangyihua "commit r2303" [22/Dec/2008:11:54:04 +0800]

 

~~~~~~~~~~~~~~~~~~

附录1

 

Apache模块 mod_log_config

现有的语种:  en 说明:    将对服务器发起的请求记录到日志
状态:    Base
模块名:    log_config_module
源文件:    mod_log_config.c

概要

      本模块提供了灵活的方法将客户请求记录到日志。日志可以以自定义的格式直接写入文件,或者传送到一个外部程序中继续处理。条件日志功能可以实现根据请求的特征来决定一个日志信息是否被包含在最终的日志记录里面。

      本模块提供了三个指令:TransferLog 指令用来生成一个日志文件,LogFormat 指令用来设定自定义的日志格式,最后你还可以通过CustomLog 指令来同时完成日志文件和格式的设定。TransferLog 指令和CustomLog 指令在每个服务器上都可以被多次使用,以便将一个请求记录到多个文件中。
指令索引
CookieLog
CustomLog
LogFormat
TransferLog

 


自定义日志格式

      LogFormat 指令和CustomLog 指令的格式化参数是一个字符串。这个字符串会在每次请求发生的时候,被记录到日志中去。它可以包含将被原样写入日志的文本字符串以及C语言式样的控制字符"\n"和"\t"以实现回车与换行。文本中的引号和反斜杠应通过\来转义。

      请求本身的情况将通过在格式字串中放置各种"%"转义符的方法来记录,它们在写入日志文件时,根据下表的定义进行转换:

 

格 式                 描述
%%                   百分号(Apache 2.0.44 或更高的版本)
%...a                 远端IP地址
%...A                 本地IP地址
%...B                 除HTTP报头外传送的字节数
%...b                以CLF格式显示的除HTTP报头外的传送字节数,例如:当没有字节传送时显示'-'而不是0。
%...{Foobar}C     在请求中传送给服务端的cookie Foobar的内容。
%...D                 服务器完成本请求的时间,以毫秒为单位。
%...{FOOBAR}e    环境变量FOOBAR的值
%...f                  文件名
%...h                 远端主机
%...H                 请求协议
%...{Foobar}i      发送到服务器的请求报头Foobar的内容。
%...l                  远端登录名(由identd而来,如果支持的话)
%...m                请求的方法
%...{Foobar}n     从另一个模块来的注解Foobar:。
%...{Foobar}o     返回时报头的内容Foobar:。
%...p                 服务器提供本请求对应服务的标准端口。
%...P                 为本请求提供服务的子进程的进程ID。
%...q                 查询字串(如果存在由一个?引导,否则返回空串)
%...r                 请求的第一行
%...s                 状态。对于内部重定向的请求,这个状态指的是原始请求的状态,--- %...>s则指的是最后请求的状态。
%...t                 时间,用普通日志时间格式(标准英语格式)
%...{format}t     时间,用strftime(3)指定的格式表示的时间。(默认情况下按本地化格式)
%...T                完成请求服务的时间,以秒为单位。
%...u                 远程用户名(根据验证信息而来;如果返回status (%s)为401,可能是假的)
%...U                请求的URL路径,不包含查询串。
%...v                进行服务的服务器的标准名字ServerName。
%...V                根据UseCanonicalName指令设定的服务器名称。
%...X                请求完成时的连接状态:     X =    连接在应答完成前中断。
+ =                   应答传送完后继续保持连接。
- =                    应答传送完后关闭连接。

(在Apache 1.3后来的版本中,这个指令是%...c,但这样就和过去的SSL语法:%...{var}c有冲突了。
%...I    接收的字节数,包括请求头的数据,并且不能为零。要使用这个指令你必须启用mod_logio模块。
%...O    发送的字节数,包括请求头的数据,并且不能为零。要使用这个指令你必须启用mod_logio模块。

      上表中的"..."在实际中可以什么也没有(例如:"%h %u %r %s %b"),也可以用来指定条目被包含的条件(如果条件不满足,它会被"-"来替换)。条件是由一个HTTP状态代码的列表来组成的,状态代码前还可以加上"!"前缀。 这样,格式串"%400,501{User-agent}i" 只记录400错误(错误的请求)和501错误(没实现的功能)到User-agent:; "%!200,304,302{Referer}i"记录任何没有正常返回的请求到Referer:。

      注意在处理由%...r、%...i和%...o组成的字串时,不会进行ESC序列的转义。这主要是为了符合通用日志格式(Common Log Format)的要求。这样就使用户能在日志中插入控制字符,因此,在处理原始的日志文件的时候,要特别注意这一点。

 

一些常见的格式串如下所示:
能用日志格式(CLF)
"%h %l %u %t \"%r\" %>s %b"
带虚拟主机的通用日志格式
"%v %h %l %u %t \"%r\" %>s %b"
NCSA扩展/组合日志格式
"%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""
Referer日志格式
"%{Referer}i -> %U"
Agent (Browser)日志格式
"%{User-agent}i"

      注意对请求提供服务的服务器的正式主机名(ServerName)和侦听端口(Listen)分别由%v和%p来得到。 这一点将忽略UseCanonicalName 指令的设置,因为否则日志分析程序会需要成倍地进行整个虚拟主机算法的运算以决定实际上是哪个服务器在响应请求。

 

 

CustomLog 指令说明: 

设定日志的文件名和格式
语法:     CustomLog file|pipe format|nickname [env=[!]environment-variable]
上下文:   服务器配置, 虚拟主机
状态:     Base
模块:     mod_log_config

 

    CustomLog 指令用来对服务器的请求进行日志记录。可以指定日志的格式,也可以使用环境变量根据请求的特征来随意地组织日志。

第一个参数指定了日志记录的位置,可以使用以下两种方式来设定:
file
日志文件名,相对于ServerRoot 目录。
pipe
管道符"|"后面紧跟着一个程序的路径,这个程序把日志从标准输入设备中读入并处理。


安全性警告:

如果这里用到了程序,那个这个程序是以启动httpd的用户来执行的。因此如果启动httpd的用户是root,那这个程序也是以root用户身份来启动的;确认这个程序是安全的。


注意

     当在非UNIX平台上输入文件路径的时候,要特别注意即使平台本身是使用反斜杠来分隔路径的,在这里也只能使用斜杠。通常在配置文件里只用斜杠来分隔路径总是不会错的。

     第二个参数指定了写入日志文件的内容。它既可以是由前面的LogFormat 指令定义的别名,也可以是直接按日志格式一节所描述的规则定义的格式字符串。

例如:以下两组指令的结果是完全一样的:

# CustomLog with format nickname
LogFormat "%h %l %u %t \"%r\" %>s %b" common
CustomLog logs/access_log common

# CustomLog with explicit format string
CustomLog logs/access_log "%h %l %u %t \"%r\" %>s %b"

     第三个参数是可选的,它根据服务器上特定的环境变量是否被设置来决定是否对某一特定的请求进行日志记录。如果这个特定的环境变量被设置(在'env=!name'的情况下,没被设置),那么这个请求就被日志所记录。

     可以使用mod_setenvif 和 / 或mod_rewrite 模块来为每一类请求设置环境变量。例如:如果你想在你的服务器上将所有对GIF图片的请求记录在不同于主日志文件的另一个日志文件中,你可以使用下面的指令:

SetEnvIf Request_URI \.gif$ gif-image
CustomLog gif-requests.log common env=gif-image
CustomLog nongif-requests.log common env=!gif-image

 

~~~~~~~~~~~~

 

其他的附属命令

 

LogFormat 指令说明: 

定义日志文件里的记录格式
语法:       LogFormat format|nickname [nickname]
默认值:    LogFormat "%h %l %u %t \"%r\" %>s %b"
上下文:    服务器配置, 虚拟主机
状态:       Base
模块:       mod_log_config

    本指令定义访问日志的记录格式。

     LogFormat 指令可以使用两种方式中的一种。在第一种定义方式中,指令只带一个参数,以定义后续的TransferLog 指令中指定的日志内容的日志格式。这唯一的参数可以按上述自定义日志格式所描述的格式来定义。另外它也可以通过下述的方法使用别名来参照预先定义的日志格式。

     在LogFormat 指令的第二种定义方式中,将一个直接的格式和一个别名联系起来。这样在后续的LogFormat 或CustomLog 指令中,就不用一再重复整个冗长的格式串。定义别名的LogFormat 指令仅仅用来一个别名,它不做其它任何事情 -- 也就是说,它只是定义了这个别名,它既没有实际应用这个别名,也不是把它设为缺省的格式。因此,它不会影响后续的TransferLog 指令。另外,LogFormat 不能用一个别名来定义另一个别名。注意,别名不能包含百分号(%)。


示例

LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_common

 

TransferLog 指令说明:  

指定日志文件的位置
语法:     TransferLog file|pipe
上下文:   服务器配置, 虚拟主机
状态:     Base
模块:     mod_log_config

     本指令除不允许直接定义日志格式或根据条件进行日志记录外,与CustomLog 指令有完全相同的参数和功能。实际应用中,日志的格式是由最近的非别名定义的LogFormat 指令指定。如果没有定义任何日志格式,则使用通用日志格式。


示例

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""
TransferLog logs/access_log

 

 

CookieLog 指令说明: 

设定针对cookies的日志文件名


语法:                        CookieLog filename
上下文:                     服务器配置, 虚拟主机
状态:                        Base
模块:                        mod_log_config
兼容性:                     本指令有争议

     CookieLog 指令设置针对cookies所作的日志记录的文件名。文件是相对ServerRoot目录的。 包含本指令仅仅是为了保持与mod_cookies模块的兼容,并且不推荐使用。

 

需要考虑的安全性问题

     如果日志文件放置的目录对除了启动Apache服务以外的用户可写的话,可能会对系统的安全性造成威胁,具体的讨论请参见安全方面的提示一章。

 

~~~~~

附录2

 

在Apache下的日志简介

    Apache提供了广泛记录运行时各方面信息的工具。比如有条件性的记录日志,日志循环,确定IP地址等时普遍会遇到的问题。还讲解很多用于检测您的Apache服务器状态以及分析其日志的捆绑的第三方模块和工具。

 

 

默认的Apache日志文件

    Apache提供很多检测和日志工具来追踪服务器的正确运行。默认的Apache配置提供两个日志文件,放置在安装目录下的日志目录里面。

    access_log 这个文件(在windows下对应access.log文件)包含了服务器已经处理过的请求的信息,比如说请求的URL,客户端的IP地址,请求是否被成功完成等。error_log 这个文件(在windows下对应error.log文件)包含了与错误情况相关的信息,以及服务器生命周期中不同的大事件。

创建日志格式
LogFormat "%h %l %u %t \"%r\" %>s %b" common
LogFormat "%h %l %u %t \"%r\" %>s %b" \"%{Referer}i\" \"%{User-agent}i\"" combined

    LogFormat 指令允许你告诉Apache你想要记录请求的哪些方面。而你仍需附加的指令来告诉Apache在哪里记录那些信息,这在下一章中将会介绍。下面的例子显示了两种最受欢迎的格式的配置:普通日志格式和整合日志格式。当Apache收到一个请求,他将会用相应的请求属性来替代以%为前缀的每一个域。如果您正在使用普通日志格式,您的日志文件里的每一项输入看起来都将是这样的:

        192.168.200.4 - someuser [12/Jun/2005:08:33:34+0500] "GET /example.png HTTP/1.0" 200 1234

   如果您正在使用整合日志格式,您的日志文件里的每一项输入看起来则都将是这样的:

192.168.200.4 - someuser [12/Jun/2005:08:33:34+0500] "GET /example.png HTTP/1.0" 200 1234 http://www.example.com/index.html "Mozilla/5.0    (Windows; U; Windows NT 5.1; en-US; rv:1.7.7)"

   尽管有附件提供日志格式的详尽索引,下表描述了一些最为重要的域:

# %h: 客户端(例如,浏览器)向服务器发出连接请求时自己的当时的IP地址或域名(需开启HostNameLookups)。
# %u: 使用HTTP方式认证用户时,记录下的用户的编号。
# %t: 服务器接受到连接请求的时间。
# %r: 客户端发出的原始连接请求中的文本信息,包含所使用的HTTP方法。
# %>s: 服务器应答浏览器后的返回状态代码,200表示请求成功。.
# %b: 服务器应答浏览器发出的单个请求的回传对象的内容大小(字节为单位),不统计数据包头部字节。

    整合日志格式在普通日志格式的基础上扩展出了两个附加的域。定义为:

# %{Referer}i: 连接请求数据包包头,包含指向当前页面的文档关联信息。
# %{User-agent}i: 用户代理连接请求数据包包头,包含客户浏览器的信息。

 

 

    创建一个自定义日志文件

CustomLog logs/access_log common
TransferLog logs/sample.log

    您可能会想创建Apache自带以外的新的日志文件。下面的例子将运用CustomLog来创建一个新的日志文件,并保存由一个之前定义好的日志格式,即前一章提到的common,所定义的信息。您还可以用格式本身的定义来替换昵称。一个附加的,更为简单的指令是Transferlog,它只接受最后一个 LogFormat指令提供的定义。

 

    重导向日志到一个外部的程序

TransferLog "|bin/rotatelogs /var/logs/apachelog 86400"

    你也可以用CustomLog或TransferLog将日志的输出重导向(输出)到一个外部的程序,而不是一个文件。要做到这一点,首先您需要以输出字符 "|"开头,跟着是接收日志标准输入信息的程序之路经。本例运用Apache自带的rotatelogs程序,在稍后的章节中会对其有所介绍。

    当有一个外部程序被使用,它将作为启动httpd的用户被运行。如果服务器是被超级管理员所启动,它就会是超级管理员,完全确保这个程序是安全的。并且,当进入一个非Unix平台上的一个文件路径时,需要小心确保只有正斜杠被使用,即使这个平台可能是允许使用反斜杠的。总的来说,在整个配置文件中总是使用正斜杠是个好主意。

    有条件的日志请求

SetEnvIf Request_URI "(\.gif|\.jpg)$" image
CustomLog logs/access_log common env=!image
SetEnvIf Remote_Addr 192\.168\.200\.5 specialmachine
CustomLog logs/special_access_log common env=specialmachine

    你可以根据可变的环境决定是否记录一个请求。这种可变可以根据许多参数,比如客户端的IP地址或请求中某个头部的存在,事先设置好。正如本例中所显示, CustomLog指令可以将可变的环境作为第三个参数来接受。如果存在可变的环境,它就将被记录,否则就不会。如果这个可变的环境被一个"!"开头否定,那么不存在可变的环境将会被记录。本例将告诉您如何避免在日志里以GIF和JPEG的格式记录图像,及如何从一个特定的IP地址记录请求道一个单独的日志文件。另一个例子请参加下一节。

    谁在连接你的网站

SetEnvIfNoCase Referer www\.example\.com internalreferral
LogFormat "%{Referer}i -> %U" referer
CustomLog logs/referer.log referer env=!internalreferral

    可以通过记录Referer的值来检测哪些人连接了你的网站,Referer变量位于用户发送连接请求数据包的头部,数据包头中还包含了用户访问的目的网站的URL地址。通过这种方法可以记录下绝大部分网站访问者。也可以把来自特定网站(www\.example\.com)地址段的来访者排除出日志记录文件。


    利用模块参数(mod_status)来监视Apache服务器

<location /server-status>
  SetHandler server-status
  Order Deny,Allow
  Deny from all
  Allow from 192.168.0
</location>

    Apache 服务器中可以使用的功能模块很多,有服务器内置的也有外挂的,这些模块工作的状态和性能就是通过mod_status参数来记录的,记录的内容有“哪些模块参与了网站应答服务、哪些模块处于空闲状态、服务器的开启/关闭时间。正在处理的连接请求数和访问者数量(需要指定ExtendedStatus记号) -该模块记录对高负荷网站服务器性能有很大影响”。例子中记录的模块状态统计结果可以用浏览器访问http://www.example.com/server-status页面来查看。

 

    通过SNMP协议来监视Apache服务器

    SNMP 是简单网管协议,支持SNMP的服务器或网络设备可以被OpenView、Tivoli等网管软件统一管理,目前有很多开源的SNMP模块可以加装到 Apache网站服务器之上,对于Apache 1.3版来讲,mod_snmp模块可以支持第1版和2版的SNMP协议;对于Apache 2版来讲,mod_apache_snmp模块可以编译成Apache的DSO直接支持第1版、第2版和第3版的SNMP协议。有了SNMP模块,外部网管软件就可以对Apache网站服务器的各种实时性能参数进行查看了,这些参数包含“服务器连续在线时间、平均负载、一段时间内的错误数、提供网站服务的字节数和连接请求数”。SNMP模块遇到突然激增的并发连接请求数时会向控制台报警。管理SNMP资源的开源工具软件有:“net-snmp, OpenNMS,Najios等”。

    用开源工具分析日志

    有很多开源和商业版的工具软件可以对产生的Apache日志文件做分析和处理,通常的步骤是:

1.选取一个日志文件。
2.分析日志文件内容。
3.生成包含不同类别内容的统计信息网页输出。

    Webalizer(http://www.mrunix.net/webalizer/)和AWStats(http://awstats.sf.net)是较为流行的日志文件分析工具;还有一些工具可以记录来访者具体访问路线,比如Vistors和Pathalizer工具,可以分别从http://www.hping.org/visitors/和http://pathalizer.bzzt.net/下载。

    实时监视日志

    使用apachetop命令行工具来显示apache服务器当前的运行状态,类似于Unix等系统下的top命令工具。对流量比较低的Unix- Apache网站也可以使用tail命令来记录实时日志信息,tail -f /logfile/。通过扫描错误日志文件中的记录,分析出恶意连接请求,常用的错误日志文件扫描工具有Logscan和ScanErrLog,可以分别从http://www.garand.net/security.php和http://www.librelogiciel.com/software/去下载这些工具。

    将连接请求日志记录到数据库

    Apache 本身没有将记录转发到数据库的功能,必须要第三方脚本和模块来支持。这里列举几个:mod_log_sql模块允许将连接请求直接记入MySQL数据库,然后用Apache LogView SQL工具来参看库中的记录;pglogd工具可以记录日志到PostgreSQL数据库中。

    将日志文件转存和归档

CustomLog "|bin/rotatelogs /var/logs/apachelog 86400" common

    如果网站流量较高,日志文件很容易就会变得很大,需要进行转存和归档处理。转存日志文件时需要压缩和保存,在线进行这项工作可以使用Apache提供的rotatelogs来完成,类似工具还可以在http://cronolog.org/上找到。例子中用rotatelogs工具将每天的日志做了转存和归档处理,一天共有86400秒。查看Apache帮助文件可以了解更多的rotatelogs工具参数。注意如果rotatelogs工具所在的目录名含有空格,则需要用跳转符号\来指定。

    IP地址和域名之间对应处理

    将HostNameLookups 设置成on,那么日志记录中将显示来访者所在的域名,设置成on可降低服务器性能。为了解决这一问题,Apache提供了一个事后分析IP地址域名信息的工具logresolve,例如$ logresolve < access_log > resolved_log

    如果用代理服务器或网关设备来完成的网站访问,Apache服务器将只能记录到代理服务器和网关的IP地址和域名。

     如何自动启动Apache服务器

#!/bin/bash
if [ 'ps -waux | grep -v grep | grep -c httpd' -lt 1];
then apachectl restart; fi

    在windows 平台下以服务方式启动的Aapche遇到意外退出后可以由服务管理器自动自动,Unix平台下需要借助watchdog脚本来实现自动启动功能, watchdog程序专门用来监视其他程序的运行状态,发现被监视的程序退出或停止后可以重新将他们启动。例子中简单的linux脚本将监视系统的进程表,如果网站服务器httpd进程消失,则负责将它重新启动,使用该脚本的条件有2个,首先保证该脚本文件具备可执行权限,第二必须将该文件设置到 cron文件中,使之可以在预定的时间间隔内运行,如果使用Solaris系统,需要将例子中的ps -waux改成ps -ef。用户可以访问http://perl.apache.org/docs/general/control/control.html网页发现更多高级的watchdog类脚本工具,大多数linux发行版自带一些用于Apache的脚本工具。

    日志文件的分割和合并

    如果用户的网站环境是用服务器集群来搭建的,通常需要将所有服务器上的日志做合并成单个文件后,才可以进行分析和处理。相似的道理,如果在单台服务器上运行多个虚拟网站,则需要将单个日志文件分割成多个部分供不同的虚拟网站用户去分析。在Apache服务器源码的support/文件夹下可以找到相应的脚本工具split-logfile等。在http://www.coker.com.au/logtools/网页可以找到一些其他的日志工具。比如vlogger工具就可以替代cronologs来对单个服务器上的虚拟网站日志进行分别处理,该工具在http://n0rp.chemlab.org/vlogger/下载。

    为虚拟网站保存独立的日志文件

<virtualhost>
  ServerName vhost1.example.com
  CustomLog logs/vhost1.example.com_log combined
  ErrorLog logs/vhost2.example.com_log
  .......
</virtual host>

    使用CustomLog标志段在Apache配置文件的区块内实现虚拟网站日志文件的独立处理。

LogFormat "%v %h %l %u %t \"%r\" %>s %b" common_virtualhost
CustomLog logs/access_log common_virtualhost

    在Apache全局配置中配置方法,其中的v%负责把提供服务的虚拟网站记录下来,对于配置了很多虚拟网站的单台服务器来说,这种配置不错。如果不想记录虚拟服务器的日志只需要在配置文件中加入"CustomLog /dev/null"就可以了。

日志文件中常见的条目

缺少favicon.ico文件,该文件可在浏览器的标题栏显示网站的个性图案;
缺少robots.txt文件,利于站点复制工具和搜索引擎使用;
覆写httpd.pid文件,网站服务器不正常退出后遗留的PID记录文件;
陌生的长记录条,"SEARCH /\x90\x02\xb1\x02\xb1\x02\xb1\x02 ..."
"GET /scripts/..%252f../winnt/system32/cmd.exe?/
  c+dir HTTP/1.0..."
"GET /default.ida?NNNNNNN NNNNNNNNNNNNNNNNNN ..."

    类似的记录条表示访问者请求了网站上根本没有的cmd.exe,root.exe或dir等文件。
    日志文件中的一些条目经常反映了那些自动探测网站服务器漏洞的动作,多数来源于针对IIS网站服务器的蠕虫和恶意程序。有时候也会发现一些针对Apache的漏洞,所以为了保证Apache的正常运行,用户应保持经常更新Apache软件。

11月12日

如何查看linux版本(转)


查看linux的版本主要有三种方法:

1) 登录到服务器执行 lsb_release -a ,即可列出所有版本信息,例如:

[root@3.5.5Biz-46 ~]# lsb_release -a
LSB Version: 1.3
Distributor ID: RedHatEnterpriseAS
Description: Red Hat Enterprise Linux AS release 4 (Nahant Update 1)
Release: 4
Codename: NahantUpdate1
[root@3.5.5Biz-46 ~]#

这个命令适用于所有的linux,包括Redhat、SuSE、Debian等发行版。

2) 登录到linux执行cat /etc/redhat-release ,例如如下:
[root@3.5.5Biz-46 ~]# cat /etc/redhat-release
Red Hat Enterprise Linux AS release 4 (Nahant Update 1)
[root@3.5.5Biz-46 ~]#

这种方式下可以直接看到具体的版本号,比如 AS4 Update 1

3)登录到linux执行rpm -q redhat-release ,例如如下

[root@3.5.5Biz-46 ~]# rpm -q redhat-release
redhat-release-4AS-2.4
[root@3.5.5Biz-46 ~]#

这种方式下可看到一个所谓的release号,比如上边的例子是2.4
这个release号和实际的版本之间存在一定的对应关系,如下:

redhat-release-3AS-1 -> Redhat Enterprise Linux AS 3
redhat-release-3AS-7.4 -> Redhat Enterprise Linux AS 3 Update 4
redhat-release-4AS-2 -> Redhat Enterprise Linux AS 4
redhat-release-4AS-2.4 -> Redhat Enterprise Linux AS 4 Update 1
redhat-release-4AS-3 -> Redhat Enterprise Linux AS 4 Update 2
redhat-release-4AS-4.1 -> Redhat Enterprise Linux AS 4 Update 3
redhat-release-4AS-5.5 -> Redhat Enterprise Linux AS 4 Update 4

注意:第(2)(3)两种方法只对Redhat Linux有效

原文地址 http://bbs.eb2000.cn/redirect.php?tid=1928&goto=lastpost

11月7日

linux运行&开发环境建立(远程访问+postgresql+eclipse+tomcat)

 

由于redhat在每次打开文件夹时都新增一个窗口,特麻烦,我们安装文件管理器Nautilus。由于在安装redhat as4时选择了最小安装,所以在安装Nautilus前还得先安装gcc编译器。

1.1 安装gcc

操作系统是在Redhat AS4 U4,安装的时候选择的最小安装,现在使用rpm来安装gcc:

rpm的包依赖确实很麻烦,过程我就不重复了,直接说怎么装(下面这些RPM包在redhat as4安装光盘中):

rpm -Uvh cpp-3.4.6-3.i386.rpm

rpm -Uvh glibc-kernheaders-2.4-9.1.98.EL.i386.rpm

rpm -Uvh glibc-headers-2.3.4-2.25.i386.rpm

rpm -Uvh glibc-devel-2.3.4-2.25.i386.rpm

rpm -Uvh gcc-3.4.6-3.i386.rpm

相关的rpm包在redhat的iso镜像里都能找到。

安装好后,使用 rpm -qa | grep gcc 会发现gcc已经成功安装了,我们还可以使用 rpm -qR gcc-xxx 查询一下gcc都依赖于哪些文件。

1.2 安装nautilus

下载地址:http://www.icewalkers.com/download/Nautilus/1191/dls/

2 远程控制

为了在windows上控制linux,不想老跑来跑去,建立远程控制。

在linux上要做三件事情:

1) 打开远程控制。在“应用程序”—“首选项”---“远程桌面”里设置,将“允许其他用户控制您的桌面”等打勾。

2) 打开XDMCP服务,打开177端口。在“应用程序”---“系统设置”----“登录屏幕”里设置,将“启用XDMCP”前打勾。可用netstat –nul 命令查看177端口是否已经打开。另外,将“安全”选项卡中的“允许root通过GDM远程登录”前也打勾。

3) 打开防火墙相应的端口。这里是测试,我们用 iptables –F 命令取消所有的防火墙策略。

在windows上做一件事情,就是安装Xmanager软件(也可用VNC Viewer)。安装上,直接在地址栏上输入linux机器所在的IP地址即可远程控制了。

3 使用SSH

在便于从windows上向linux机器上传文件,我们使用SSH。

在linux上打开相应的端口即可。默认是安装了SSH的。

在Windows中做一件事,安装ssh客户端。可用Xshell这个小软件。很简单,装了你自己看一看自然就会用了,略。

4 linux与windows交换数据

可有三种方式,共享文件、SSH、FTP

通过比较,我们最后选择了winscp方式。

4.1 通过samba共享文件

Samba(SMB是其缩写) 是一个网络服务器,用于Linux和Windows共享文件之用;Samba 即可以用于Windows和Linux之间的共享文件,也一样用于Linux和Linux之间的共享文件;不过对于Linux和Linux之间共享文件有更好的网络文件系统NFS,NFS也是需要架设服务器的;

下载地址:http://download.chinaunix.net/download.php?id=24685&ResourceID=30

mkdir temp

cp -r gnsSpider/* temp //拷贝gnsSpider下的所有文件到temp

rm -rf jdk5 //删除一个目录下的所有文件及文件夹

4.2 通过SSH的SCP命令上传

在两个linux之间使用ssh自带的scp上传文件,在windows下可用WinSCP

iptables-save //查看SSH使用的远程端口22是否被封

/etc/rc.d/init.d/iptables stop //关掉fc防火墙

/etc/rc.d/init.d/iptables start //开启fc防火墙

chkconfig --level 35 iptables off //永久关闭防火墙

iptable -t filter -I RH-Firewall-1-INPUT -p tcp -m tcp --dport 22 -j ACCEPT //开启22端口

ssh zhanghua@172.17.1.122 //运行ssh user@ip 远程登录

scp -P 22 gnsSpider.tar zhanghua@172.17.1.122:/home/zhanghua/gsnSpider

WinSCP的下载地址:http://sourceforge.net/projects/winscp/ 。下载完无须安装,直接就可以用。

4.3 通过ftp上传

http://forum.ubuntu.org.cn/viewtopic.php?t=85074&sid=27a22c693d20107369cd5e4e291784f4

ftp 172.17.1.122

anonymous //FTP用户名

ls //查看FTP上有哪些文件

lcd /home/zhanghua/gnsSpider //下载的存放路径

binary //这种模式传输速度快

prompt //关掉询问用户是否下载的提示

cd gnsSpider //进入FTP上的gnsSpider目录

mget * //将FTP上的gsnSpider目录下的文件全下载(注意它好像不能下载文件夹)

put i001.jpg //上传

bye //退出

5 安装postgresql数据库

首先要声明的是,在linux上安装的实际上是postgresql server. 那样在windows里直接用pgAdmin客户端便能操作。

Postgresql的下载地址:http://www.enterprisedb.com/products/pgdownload.do#linux

chmod 777 postgresql-8.3.3-2-linux.bin //给执行权限

./postgresql-8.3.3-2-linux.bin //显示图形化安装界面,按下一步开始安装

passwd postgres //给postgres用户改密码,不用以root用户安装

//在.bash_profile中追加环境变量

vi ~postgres/.bash_profile

initdb //初始化数据库

./postmaster -i -D ../data & //在bin目录下打这个命令启动

如果postgresql已经占了端口,可强行杀掉

ps –aux |grep postgresql

kill -9 6229

如果需要其他IP能够访问,必须改变两个文件:

1) 修改/opt/PostgreSQL/8.3/data/postgresql.conf

将listen_addresses = 'localhost' 改成 listen_addresses = '*'

2) 修改/opt/PostgreSQL/8.3/data/pg_hbd.conf。如下图第2、3两行是我们加的。

6 安装eclipse

为调试程序,我们需要安装eclipse。下载地址:

http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/ganymede/R/eclipse-cpp-ganymede-linux-gtk.tar.gz

先安装JDK1.6,步骤如下:

chmod 777 jdk-6u6-linux-i586.bin

./jdk-6u6-linux-i586.bin //解压JDK6

ls

mv jdk1.6.0_06 jre //给JDK6改个新名字

修改环境变量:

vi /etc/profile

JAVA_HOME="/opt/j2sdk1.4.2_01"

MYSQL_HOME="/var/mysql"

CLASSPATH=.:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar

PATH=$PATH:$JAVA_HOME/bin:$MYSQL_HOME/bin:

export JAVA_HOME CLASSPATH PATH

安装eclipse。解压即可,无须安装。

安装tomcat插件,与windows下的安装方法同,略。

7 安装tomcat

解压即可,无须安装。