通过tcpserver实现对同一IP的最大连接数和连接频率的限制
2004-08-171. 同一IP最大连接数的限制
使用Balazs Nagy的 periplimit patch 实现同一IP的最大连接数的限制。
相关地址: http://js.hu/package/ucspi-tcp/
实现: ucspi-tcp-0.88-periplimit.6.patch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
diff -ru ucspi-tcp-0.88-orig/Makefile ucspi-tcp-0.88/Makefile --- ucspi-tcp-0.88-orig/Makefile Sat Mar 18 16:18:42 2000 +++ ucspi-tcp-0.88/Makefile Fri May 28 06:48:15 2004 @@ -753,7 +753,7 @@ alloc.h buffer.h error.h strerr.h sgetopt.h subgetopt.h pathexec.h socket.h uint16.h ndelay.h remoteinfo.h stralloc.h uint16.h rules.h stralloc.h sig.h dns.h stralloc.h iopause.h taia.h tai.h uint64.h -taia.h +taia.h uint32.h ./compile tcpserver.c time.a: diff -ru ucspi-tcp-0.88-orig/tcpserver.c ucspi-tcp-0.88/tcpserver.c --- ucspi-tcp-0.88-orig/tcpserver.c Sat Mar 18 16:18:42 2000 +++ ucspi-tcp-0.88/tcpserver.c Thu Jul 1 08:37:03 2004 @@ -2,6 +2,7 @@ #include <sys/param.h> #include <netdb.h> #include "uint16.h" +#include "uint32.h" #include "str.h" #include "byte.h" #include "fmt.h" @@ -242,6 +243,7 @@ tcpserver: usage: tcpserver [ -1UXpPhHrRoOdDqQv ] [ -c limit ] +[ -s perip limit ] [ -x rules.cdb ] [ -B banner ] [ -g gid ] @@ -254,8 +256,24 @@ } unsigned long limit = 40; +unsigned long periplimit = 0; unsigned long numchildren = 0; +typedef struct +{ + pid_t pid; + int offset; +} connections; + +typedef struct +{ + uint32 ipaddr; + unsigned long num; +} ipchildren; + +connections *children; +ipchildren *numipchildren; + int flag1 = 0; unsigned long backlog = 20; unsigned long uid = 0; @@ -278,6 +296,7 @@ { int wstat; int pid; + int i; while ((pid = wait_nohang(&wstat)) > 0) { if (verbosity >= 2) { @@ -286,6 +305,12 @@ strerr_warn4("tcpserver: end ",strnum," status ",strnum2,0); } if (numchildren) --numchildren; printstatus(); + for (i=0;i<limit;++i) + if (children[i].pid == pid) { + children[i].pid=0; + numipchildren[children[i].offset].num--; + break; + } } } @@ -300,10 +325,11 @@ int s; int t; - while ((opt = getopt(argc,argv,"dDvqQhHrR1UXx:t:u:g:l:b:B:c:pPoO")) != opteof) + while ((opt = getopt(argc,argv,"dDvqQhHrR1UXx:t:u:g:l:b:B:c:s:pPoO")) != opteof) switch(opt) { case 'b': scan_ulong(optarg,&backlog); break; case 'c': scan_ulong(optarg,&limit); break; + case 's': scan_ulong(optarg,&periplimit); break; case 'X': flagallownorules = 1; break; case 'x': fnrules = optarg; break; case 'B': banner = optarg; break; @@ -334,6 +360,11 @@ if (!verbosity) buffer_2->fd = -1; + + if (!periplimit) + periplimit = limit; + if (limit<periplimit) + strerr_die2x(111,FATAL,"periplimit must be smaller than or equal to connection limit"); hostname = *argv++; if (!hostname) usage(); @@ -358,6 +389,11 @@ sig_catch(sig_term,sigterm); sig_ignore(sig_pipe); + if (!(numipchildren = (ipchildren*)malloc(sizeof(ipchildren)*limit))) + strerr_die2x(111,FATAL,"out of memory"); + byte_zero(numipchildren,sizeof(ipchildren)*limit); + if (!(children = (connections*)malloc(sizeof(connections)*limit))) + strerr_die2x(111,FATAL,"out of memory"); if (!stralloc_copys(&tmp,hostname)) strerr_die2x(111,FATAL,"out of memory"); if (dns_ip4_qualify(&addresses,&fqdn,&tmp) == -1) @@ -396,6 +432,13 @@ printstatus(); for (;;) { + uint32 ipaddr; + pid_t pid; + int i; + int lastempty = 0; + int freechild = 0; + ipchildren *ipcount; + while (numchildren >= limit) sig_pause(); sig_unblock(sig_child); @@ -403,9 +446,43 @@ sig_block(sig_child); if (t == -1) continue; + + for (i=0;i<limit;++i) { + if (children[i].pid == 0) { + freechild = i; + break; + } + } + uint32_unpack(remoteip,&ipaddr); + for (i=0;i<limit;++i) { + ipcount = &numipchildren[i]; + if (!ipcount->ipaddr || !ipcount->num) + lastempty = i; + else if (ipcount->ipaddr == ipaddr) { + ++ipcount->num; + break; + } + } + if (i == limit) { + if (lastempty) { + i = lastempty; + ipcount = &numipchildren[i]; + ipcount->ipaddr = ipaddr; + ipcount->num = 1; + } else + /* never reached */ + strerr_die2x(111,DROP,"internal problem"); + } + if (ipcount->num > periplimit) { + remoteipstr[ip4_fmt(remoteipstr,remoteip)] = 0; + strerr_warn3(DROP, "per ip limit reached for ", remoteipstr, 0); + close(t); + --ipcount->num; + continue; + } ++numchildren; printstatus(); - switch(fork()) { + switch(pid = fork()) { case 0: close(s); doit(t); @@ -420,6 +497,10 @@ case -1: strerr_warn2(DROP,"unable to fork: ",&strerr_sys); --numchildren; printstatus(); + break; + default: + children[freechild].pid = pid; + children[freechild].offset = i; } close(t); } |
2. 修改 periplimit patch, 实现对特定的IP地址不受限制 (实现: myhan)
上面的patch对所有的IP地址都限制了, 但是我们在使用的时候, 往往有部分IP地址, 如 127.0.0.1 或者本机地址, 不希望受此限制.
通过设置控制文件, 可以实现从控制文件中读取不受限制的IP地址.
控制文件的位置: /var/qmail/control/freeip
控制文件的格式: 每一行一个完整的IP地址
3. 实现对同一IP的连接频率的限制 (实现: qftang)
2和3 的实现: ucspi-tcp-0.88-frequencylimit.1.patch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
--- tcpserver.c.1.2 2004-08-13 16:50:41.000000000 +0800 +++ tcpserver.c 2004-08-17 16:11:59.000000000 +0800 @@ -28,6 +28,7 @@ #include "rules.h" #include "sig.h" #include "dns.h" +#include <stdio.h> int verbosity = 1; int flagkillopts = 1; @@ -236,6 +237,7 @@ /* ---------------------------- parent */ #define FATAL "tcpserver: fatal: " +#define MAX_IP_TIME 4096 void usage(void) { @@ -244,6 +246,7 @@ [ -1UXpPhHrRoOdDqQv ] [ -c limit ] [ -s perip limit ] +[ -f max connection per ip in one minite ] [ -x rules.cdb ] [ -B banner ] [ -g gid ] @@ -258,6 +261,7 @@ unsigned long limit = 40; unsigned long periplimit = 0; unsigned long numchildren = 0; +unsigned long max_freq = 20; typedef struct { @@ -271,14 +275,143 @@ unsigned long num; } ipchildren; +typedef struct freeip_t +{ + char ip[4]; + uint32 ipaddr; + unsigned long num; + struct freeip_t *next; +} freeip; + +typedef struct +{ + uint32 ipaddr; + unsigned long time; +} iptime; + + connections *children; ipchildren *numipchildren; +freeip *freeiplist = NULL; +iptime iptimebuf[MAX_IP_TIME]; int flag1 = 0; unsigned long backlog = 20; unsigned long uid = 0; unsigned long gid = 0; +void initfreeip(void) +{ + freeip *head = NULL; + freeip *tail = NULL; + char tempip[4]; + char buf[256] = {0}; + FILE *fp; + + if (!(head = (freeip *)malloc(sizeof(freeip)))) + strerr_die2x(111,FATAL,"out of memory"); + if (!(tail = (freeip *)malloc(sizeof(freeip)))) + strerr_die2x(111,FATAL,"out of memory"); + + uint32_unpack(localip, &head->ipaddr); + head->num = 100; + head->next = NULL; + + if (ip4_scan("127.0.0.1", tempip)) { + uint32_unpack(tempip, &tail->ipaddr); + tail->num = 100; + tail->next = NULL; + head->next = tail; + } + + fp = fopen("/var/qmail/control/freeip", "r"); + if( !fp ) { + freeiplist = head; + return; + } + while(fgets(buf, 256, fp)) { + freeip *new; + if (ip4_scan(buf, tempip)) { + new = (freeip *)malloc(sizeof(freeip)); + uint32_unpack(tempip, &new->ipaddr); + new->num = 100; + new->next = NULL; + tail->next = new; + tail = tail->next; + } else { + continue; + } + } + + freeiplist = head; +} + +void dumpfreeip(void) +{ + freeip *temp = freeiplist; + char tempip[4]; + char ipstr[IP4_FMT]; + char buf[256] = {0}; + do { + uint32_pack(tempip, temp->ipaddr); + ipstr[ip4_fmt(ipstr, tempip)] = 0; + sprintf (buf, "freeip: %s, num: %dn", ipstr, temp->num); + write(2, buf, strlen(buf)); + temp = temp->next; + } while (temp); +} + +int isfreeip(uint32 ipaddr) +{ + freeip *temp = freeiplist; + int isfree = 0; + + do { + if (temp->ipaddr == ipaddr) { + isfree = 1; + break; + } + temp = temp->next; + } while (temp); + return isfree; +} + +void freefreeip(void) +{ +} + +int isoverfrequency(uint32 ipaddr) +{ + iptime *empty_iptime = NULL; + iptime *piptime = NULL; + time_t now = time(0); + int j; + int count = 0; + int emp_pos = 0; + + for(j=0; j<MAX_IP_TIME; j++) { + piptime = &iptimebuf[j]; + if(!empty_iptime) { + if( !piptime->ipaddr || piptime->time < (now - 60)) { + empty_iptime = piptime; + emp_pos = j; + } + } + if(piptime->ipaddr == ipaddr && piptime->time > (now - 60)) { + count ++; + if(empty_iptime && count >= max_freq) + break; + } + } + + if (!empty_iptime) empty_iptime = &iptimebuf[0]; + + empty_iptime->ipaddr = ipaddr; + empty_iptime->time = now; + + return (count >= max_freq) ? 1 : 0; +} + void printstatus(void) { if (verbosity < 2) return; @@ -325,11 +458,12 @@ int s; int t; - while ((opt = getopt(argc,argv,"dDvqQhHrR1UXx:t:u:g:l:b:B:c:s:pPoO")) != opteof) + while ((opt = getopt(argc,argv,"dDvqQhHrR1UXx:t:u:g:l:b:B:c:s:f:pPoO")) != opteof) switch(opt) { case 'b': scan_ulong(optarg,&backlog); break; case 'c': scan_ulong(optarg,&limit); break; case 's': scan_ulong(optarg,&periplimit); break; + case 'f': scan_ulong(optarg,&max_freq);break; case 'X': flagallownorules = 1; break; case 'x': fnrules = optarg; break; case 'B': banner = optarg; break; @@ -394,6 +528,8 @@ byte_zero(numipchildren,sizeof(ipchildren)*limit); if (!(children = (connections*)malloc(sizeof(connections)*limit))) strerr_die2x(111,FATAL,"out of memory"); + byte_zero(children,sizeof(connections)*limit); + byte_zero(iptimebuf,sizeof(iptime)*MAX_IP_TIME); if (!stralloc_copys(&tmp,hostname)) strerr_die2x(111,FATAL,"out of memory"); if (dns_ip4_qualify(&addresses,&fqdn,&tmp) == -1) @@ -426,6 +562,10 @@ buffer_puts(&b,"n"); buffer_flush(&b); } + + initfreeip(); + + dumpfreeip(); close(0); close(1); @@ -473,13 +613,23 @@ /* never reached */ strerr_die2x(111,DROP,"internal problem"); } - if (ipcount->num > periplimit) { + //if (ipcount->num > periplimit) { + if (!isfreeip(ipaddr) && (ipcount->num > periplimit)) { remoteipstr[ip4_fmt(remoteipstr,remoteip)] = 0; strerr_warn3(DROP, "per ip limit reached for ", remoteipstr, 0); close(t); --ipcount->num; continue; } + + if (isoverfrequency(ipaddr)) { + remoteipstr[ip4_fmt(remoteipstr, remoteip)] = 0; + strerr_warn3(DROP, "frequency limit reached for ", remoteipstr, 0); + close(t); + continue; + } + + ++numchildren; printstatus(); switch(pid = fork()) { |
4. 测试工具 🙂
tcpservertester.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
#!/usr/local/bin/php -f <?php error_reporting(0); set_time_limit(6000); $keepconnect = false; for ($i=0; $i<50; $i++) { $fd = "fp_" . $i; //$$fd = fsockopen("localhost", 110, $errno, $errstr, 30); $$fd = fsockopen("172.18.10.37", 110, $errno, $errstr, 30); if ($$fd === false) { printf("No. %2d: [Error] ErrorNo: %d, ErrorInfo: %sn", $i+1, $errno, $errstr); } else { printf("No. %2d: Connect Success!n", $i+1); $buf = fgets($$fd, 1024); if (substr($buf, 0, 3) == '+OK') { printf("tS: %s", $buf); if (!$keepconnect) { fwrite($$fd, "QUITrn"); printf("tC: QUITn"); $reply = fgets($$fd, 1024); printf("tS: %s", $reply); fclose($$fd); printf("tConnection closedn"); } printf("tSleep 10 secondsn"); sleep(10); } else { printf("tService is not available!n"); if (!$keepconnect) { fclose($$fd); printf("tConnection closedn"); } printf("tSleep 15 secondsn"); sleep(15); } } } if ($keepconnect) { sleep(1000); } ?> |
Apache2 + mod_ssl + php5 完全安装实录
2004-08-10很久以前写的一个笔记,放在CSDN上面了。现在弄回来:)
http://blog.csdn.net/myhan/archive/2004/08/10/69941.aspx
环境:
RedHat 9.0
说明:
使用$ 开头的是普通用户身份执行的命令
使用# 开头的是root帐号执行的命令
第一步:安装apache
下载apache2: http://httpd.apache.org/download.cgi
我需要mod_ssl的支持,和apache1不同的是,mod_ssl不在是单独的模块,而是放在apache发行包里面了,默认是不启用的,config的时候选择上就可以了。
我使用DSO方式编译安装apache,同时将全部模块都编译好,以方便后来可能的需要。只要编辑httpd.conf,在里面去掉不想要的模块(注释或者删除对应模块的LoadModule行),就可以定制自己的apache咯。
$ tar zxvf httpd-2.0.50.tar.gz
$ ./configure --prefix=/usr/local/apache2 --enable-so --enable-ssl=shared --enable-mods-shared=all --with-ssl=/usr/local/ssl
$ make
$ su
# make install
Apache有两种使用模块的方法,其一是永久性包含进核心;
如果操作系统支持动态共享对象(DSO),而且能为autoconf所检测,则模块还可以被动态编译。
DSO模块的存储是独立与核心的,可以被核心使用由mod_so模块提供的运行时刻配置指令包含或排除。
如果编译中包含有任何动态模块,则mod_so模块会被自动包含进核心。如果希望核心能够装载DSO,而不实际编译任何动态模块,需要明确指定–enable-so。
(http://kajaa.bbs.us/ApacheManual/install.html)
第一次按照上述方法编译的apache,启动的时候会报错:
# cd /usr/local/apache2
# ./bin/apachectl startssl
Syntax error on line 251 of /usr/local/apache/conf/httpd.conf:
Cannot load /usr/local/apache/modules/mod_ssl.so into server: /usr/local/apache/modules/mod_ssl.so: undefined symbol: X509_free
原因是什么呢?看 http://www.smartframeworks.com/qt-apache-ssl.html
因为按照下面的方法(参看:Apache2 + mod_ssl + php5 完全安装实录(2))安装的openssl默认是没有编译成动态链接库的,因为其文档说openssl的动态链接库还不成熟,可以使用 ./config shared 编译带动态链接库的openssl,但是还处于试验阶段。
解决这个问题的办法是:将mod_ssl静态的编译到apache里面。
请使用下面的方法重新来过:)
$ ./configure --prefix=/usr/local/apache2 --enable-so --enable-ssl=static --with-ssl=/usr/local/ssl --enable-mods-shared=all
$ make
$ su
# make install
这次启动apache的时候又发现一个错误:
# cd /usr/local/apache2
# ./bin/apachectl startssl
Syntax error on line 108 of /usr/local/apache2/conf/ssl.conf:
SSLCertificateFile: file '/usr/local/apache2/conf/ssl.crt/server.crt' does not exist or is empty
这又是什么原因呢?因为我们没有配置ssl,需要生成ssl需要的证书。
以前使用apache1+mod_ssl的时候,make之后有一个这样的步骤
$ make certificate
可以用来生成ssl所用到的证书。
现在没有这个工具了,只能自己动手生成了,对证书不熟悉的人,有一个工具可以使用:http://www.openssl.org/contrib/ssl.ca-0.1.tar.gz
# cd /usr/local/apache2/conf
# tar zxvf ssl.ca-0.1.tar.gz
# cd ssl.ca-0.1
# ./new-root-ca.sh (生成根证书)
No Root CA key round. Generating one
Generating RSA private key, 1024 bit long modulus
...........................++++++
....++++++
e is 65537 (0x10001)
Enter pass phrase for ca.key: (输入一个密码)
Verifying - Enter pass phrase for ca.key: (再输入一次密码)
......
Self-sign the root CA... (签署根证书)
Enter pass phrase for ca.key: (输入刚刚设置的密码)
........
........ (下面开始签署)
Country Name (2 letter code) [MY]:CN
State or Province Name (full name) [Perak]:JiangSu
Locality Name (eg, city) [Sitiawan]:NanJing
Organization Name (eg, company) [My Directory Sdn Bhd]:Wiscom System Co.,Ltd
Organizational Unit Name (eg, section) [Certification Services Division]:ACSTAR
Common Name (eg, MD Root CA) []:WISCOM CA
Email Address []:acmail@wiscom.com.cn
这样就生成了ca.key和ca.crt两个文件,下面还要为我们的服务器生成一个证书:
# ./new-server-cert.sh server (这个证书的名字是server)
......
......
Country Name (2 letter code) [MY]:CN
State or Province Name (full name) [Perak]:JiangSu
Locality Name (eg, city) [Sitiawan]:NanJing
Organization Name (eg, company) [My Directory Sdn Bhd]:Wiscom System Co.,Ltd
Organizational Unit Name (eg, section) [Secure Web Server]:ACSTAR
Common Name (eg, www.domain.com) []:acmail.wiscom.com.cn
Email Address []:acmail@wiscom.com.cn
这样就生成了server.csr和server.key这两个文件。
还需要签署一下才能使用的:
# ./sign-server-cert.sh server
CA signing: server.csr -> server.crt:
Using configuration from ca.config
Enter pass phrase for ./ca.key: (输入上面设置的根证书密码)
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName :PRINTABLE:'CN'
stateOrProvinceName :PRINTABLE:'JiangSu'
localityName :PRINTABLE:'NanJing'
organizationName :PRINTABLE:'Wiscom System Co.,Ltd'
organizationalUnitName:PRINTABLE:'ACSTAR'
commonName :PRINTABLE:'acmail.wiscom.com.cn'
emailAddress :IA5STRING:'acmail@wiscom.com.cn'
Certificate is to be certified until Jul 16 12:55:34 2005 GMT (365 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
CA verifying: server.crt < -> CA cert
server.crt: OK
(如果这里出现错误,最好重新来过,删除ssl.ca-0.1这个目录,从解压缩处重新开始。)
下面要按照ssl.conf里面的设置,将证书放在适当的位置。
# chmod 400 server.key
# cd ..
# mkdir ssl.key
# mv ssl.ca-0.1/server.key ssl.key
# mkdir ssl.crt
# mv ssl.ca-0.1/server.crt ssl.crt
然后就可以启动啦!
# cd /usr/local/apache2
# ./bin/apachectl startssl
对于这个提示:
httpd: Could not determine the server’s fully qualified domain name, using 127.0.0.1 for ServerName
只需要编辑httpd.conf,找到ServerName xxxx这一行,去掉前面的注释即可。
openssl的安装
下载最新版本的openssl: http://www.openssl.org/source/
$ tar zxvf openssl-0.9.7d.tar.gz
$ cd openssl-0.9.7d
$ ./config
$ make
$ su
# make install
默认的安装最后生成的openssl库是静态库,而不是共享库。在编译apache的时候需要注意,需要使用 –enable-ssl=static 将mod_ssl静态的编译进去才可以正常使用,否则apache在启动的时候会提示错误的。
默认的安装是将openssl全部安装在 /usr/local/ssl 目录下面,所以编译apache的时候,需要指定ssl的目录:–with-ssl=/usr/local/ssl ,因为它在编译的时候要用到openssl提供的头文件和库。
所谓LAMP,Apache + PHP 当然还少不了 mysql 的支持啊。下面我就简单的说一下 mysql 的安装配置。
我没有使用源码编译的方式安装,mysql 提供了各种平台下编译好的二进制包,很方便的说,俺也是一个懒人。
首先下载 mysql 的二进制包:
在这里可以找到 mysql4.0 各种平台下的发布:http://dev.mysql.com/downloads/mysql/4.0.html
从这里下载linux下的二进制包:http://dev.mysql.com/get/Downloads/MySQL-4.0/mysql-standard-4.0.20-pc-linux-i686.tar.gz/from/http://mysql.linuxforum.net/
解压缩之后,mysql目录里面有一个 INSTALL-BINARY 文件,里面有很详细的二进制安装说明。下面我仅仅将我安装的步骤列出来,供大家参考。
解压缩
# tar zxvf mysql-standard-4.0.20-pc-linux-i686.tar.gz -C /usr/local
# cd /usr/local
# mv mysql-standard-4.0.20-pc-linux-i686 mysql
添加 mysql 用户组和用户,我将 mysql 这个帐号的主目录指向了 mysql 的安装目录,并且让该帐号不可以登陆
# groupadd mysql
# useradd -g mysql -d /usr/local/mysql -s /sbin/nologin mysql
按照 INSTALL-BINARY 里面的说明,一步一步的配置 mysql :
# scripts/mysql_install_db --user=mysql
# chown -R root .
# chown -R mysql data
# chgrp -R mysql .
OK,就这么简单,启动mysql:
# /usr/local/mysql/support-files/mysql.server start
看看 mysql 是不是已经起来了呢?
# ps -ef
安装目录 /usr/local/mysql 下面的 lib/ 和 include/ 里面的内容就是待会编译 php5 要用到的库和头文件。
下面我就开始安装php5了,过程其实很简单的。
首先PHP官方网站下载PHP5的源码包:
这个是下载页面:http://www.php.net/downloads.php
这个是PHP5的下载连接:http://cn.php.net/get/php-5.0.0.tar.gz/from/this/mirror
解压缩源码包:
$ tar zxvf php-5.0.0.tar.gz
$ cd php-5.0.0
开始安装:
$ ./configure --with-apxs2=/usr/local/apache2/bin/apxs --with-openssl=/usr/local/ssl --with-mysql=/usr/local/mysql
我是将 php5 编译成apache的DSO方式加载的模块的,这里指定使用的是apache2。如果是apache1,需要将 –with-apxs2 换成 –with-apxs。如果使用 ./configure –help 查看帮助的话,可以看到这样的提示:
EXPERIMENTAL: Build shared Apache 2.0 module. FILE is the optional
pathname to the Apache apxs tool; defaults to apxs.
是说 PHP 在 apache2 下的模块式的安装方式还处于实验阶段。
我使用的是 mysql4.0 版本,如果想使用 php5 提供的 mysqli 模块,还需要安装 mysql4.1 以上的版本。不过 mysql 官方网站上说这还没有正式推出:)
$ make
$ su
# make install
到这里安装就结束了,下面还需要做一些配置。make install 的时候,已经自动将 LoadModule 这一行添加到 Apache 的配置文件 httpd.conf 中了,下面还有一些额外的设置。参考 PHP 的手册可以找到这些内容的:http://www.php.net/manual/zh/installation.php
首先将 PHP 的配置文件从源码目录拷贝到相应的地方,我没有 –prefix 指定 PHP 的安装目录,所以按照默认的设置,prefix是 /usr/local ,php.ini 的位置应该是在:/usr/local/lib下面。如何看 PHP.ini 是否起作用呢?待会告诉呢:)
$ mv php.ini-recommended /usr/local/lib/php.ini
然后,编辑 httpd.conf ,添加上如下的指令告诉 Apache 将特定扩展名的文件解析成 PHP。同时我还添加了 index.php 作为默认页。
#
# Bring in additional module-specific configurations - mod_php5
#
AddType application/x-httpd-php .php
DirectoryIndex index.php
重启 Apache 服务器,一切就OK咯,写一个 phpinfo 来看看吧:
< ?php
phpinfo();
?>