表头文件
#include<stdio.h>
定义函数
void perror(const char *s);
函数说明
perror ( )用 来 将 上 一 个 函 数 发 生 错 误 的 原 因 输 出 到 标 准 错误
(stderr) 。参数 s 所指的字符串会先打印出,后面再加上错误原因
字符串。此错误原因依照全局变量 errno 的值来决定要输出的字符串。
范例:
#include <stdio.h>
int main(void)
{
FILE *fp ;
fp = fopen( ”/root/noexitfile”, ”r+” );
if ( NULL == fp )
{
perror(“/root/noexitfile”);
}
return 0;
}
运行结果:
[root@localhost io]# gcc perror.c
[root@localhost io]# ./a.out
/root/noexitfile: No such file or directory
六月 15, 2009
标准库函数perror用法(打印出错误原因信息字符串)
六月 14, 2009
文件I/O函数(fcntl)
fcntl函数:int
fcntl(int filedes, int cmd, …/*int arg */);
返回:若成功则依赖于cmd,若出错为-1。
作用:可以改变已打开的文件的性质
下列三个命令有特定的返回值:F_DUPFD,F_GETFD以及F_GETOWN。第一个返回新的文件描述符,第二个返回相应标志,最后一个返回一个正的进程ID或负的进程组ID。
第三个参数总是一个整数,当然在作为记录锁用时,第三个参数则是指向一个结构的指针。
fcntl函数有五种功能:
(1)复制一个现存的描述符(cmd=F_DUPFD)
(2)获得/设置文件描述符标志(cmd=F_GETFD或F_SETFD)
(3)获得/设置文件状态标志(cmd=F_GETFL或F_SETFL)
(4)获得/设置异步I/O有权(cmd=F_GETOWN或F_SETOWN)
(5)获得/设置记录锁(cmd=F_GETLK,F_SETLK或F_SETLKW)
F_DUPFD:复制文件描述符filedes,新文件描述符作为函数值返回。它是尚未打开的各描述符中大于或等于第三个参数值中各值的最小值。新描述符与filedes共享同一文件表项。但是新描述符有它自己的一套文件描述符标志,其FD_CLOEXEC文件描述符标志被清除。
F_GETFD:对应于filedes的文件描述符标志作为函数值返回。当前只定义了一个文件描述符标志FD_CLOEXEC。
F_SETFD:对于filedes设置文件描述符标志。新标志值按第三个参数设置。
F_GETFL:对应于filedes的文件状态标志作为函数返回。在说明open函数时,已说明了文件状态标志。
F_SETFL:将文件状态标志设置为第三个参数的值(取整数值),可以更改的几个标志:O_APPEND,O_NONBLOCK,O_SYNC和O_ASYNC。
F_GETOWN:取当前接受SIGIO和SIGURG信号的进程ID或进程组ID。
F_SETOWN:设置接受SIGIO和SIGURG信号的进程ID或进程组ID。正的arg指定一个进程ID,负的arg表示等于arg绝对值的一个进程组ID。
范例:
#include
#include
#include
#include
int
main(int argc, char **argv)
{
int
fd;
int
var;
if(argc!=2)
{
printf(“please
input filename and one arg!\n”);
exit(1);
}
if((var=fcntl(atoi(argv[1]),F_GETFL,0))==-1)
{
printf(“fcntl
file error!\n”);
exit(1);
}
printf(“%d\n”,var);
switch(var
& O_ACCMODE)
{
case
O_RDONLY:printf(“Read only.\n”);
break;
case
O_WRONLY:printf(“Write only.\n”);
break;
case
O_RDWR: printf(“Read Write.\n”);
break;
default:break;
}
exit(0);
}
Linux下的管道编程技术-dup函数和dup2函数
dup和dup2也是两个非常有用的调用,它们的作用都是用来复制一个文件的描述符。它们经常用来重定向进程的stdin、stdout和stderr。这两个函数的原型如下所示:
#include
int dup( int oldfd );
int dup2( int oldfd, int targetfd )
利用函数dup,我们可以复制一个描述符。传给该函数一个既有的描述符,它就会返回一个新的描述符,这个新的描述符是传给它的描述符的拷贝。这意味着,这两个描述符共享同一个
数据结构
。例如,如果我们对一个文件描述符执行lseek操作,得到的第一个文件的位置和第二个是一样的。下面是用来说明dup函数使用方法的代码片段:
int fd1, fd2;
…
fd2 = dup( fd1 );
需要注意的是,我们可以在调用fork之前建立一个描述符,这与调用dup建立描述符的效果是一样的,子进程也同样会收到一个复制出来的描述符。
dup2函数跟dup函数相似,但dup2函数允许调用者规定一个有效描述符和目标描述符的id。dup2函数成功返回时,目标描述符(dup2函数的第
二个参数)将变成源描述符(dup2函数的第一个参数)的复制品,换句话说,两个文件描述符现在都指向同一个文件,并且是函数第一个参数指向的文件。下面
我们用一段代码加以说明:
int oldfd;
oldfd = open(“app_log”, (O_RDWR | O_CREATE), 0644 );
dup2( oldfd, 1 );
close( oldfd );
本例中,我们打开了一个新文件,称为“app_log”,并收到一个文件描述符,该描述符叫做fd1。我们调用dup2函数,参数为oldfd和1,这会
导致用我们新打开的文件描述符替换掉由1代表的文件描述符(即stdout,因为标准输出文件的id为1)。任何写到stdout的东西,现在都将改为写
入名为“app_log”的文件中。需要注意的是,dup2函数在复制了oldfd之后,会立即将其关闭,但不会关掉新近打开的文件描述符,因为文件描述
符1现在也指向它。
下面我们介绍一个更加深入的示例代码。回忆一下本文前面讲的命令行管道,在那里,我们将ls –1命令的标准输出作为标准输入连接到wc –l命令。接下来,我们就用一个C程序来加以说明这个过程的实现。代码如下面的示例代码3所示。
在示例代码3中,首先在第9行代码中建立一个管道,然后将应用程序分成两个进程:一个子进程(第13–16行)和一个父进程(第20–23行)。接下来,
在子进程中首先关闭stdout描述符(第13行),然后提供了ls
–1命令功能,不过它不是写到stdout(第13行),而是写到我们建立的管道的输入端,这是通过dup函数来完成重定向的。在第14行,使用dup2
函数把stdout重定向到管道(pfds[1])。之后,马上关掉管道的输入端。然后,使用execlp函数把子进程的映像替换为命令ls
–1的进程映像,一旦该命令执行,它的任何输出都将发给管道的输入端。
现在来研究一下管道的接收端。从代码中可以看出,管道的接收端是由父进程来担当的。首先关闭stdin描述符(第20行),因为我们不会从机器的键盘等标
准设备文件来接收数据的输入,而是从其它程序的输出中接收数据。然后,再一次用到dup2函数(第21行),让stdin变成管道的输出端,这是通过让文
件描述符0(即常规的stdin)等于pfds[0]来实现的。关闭管道的stdout端(pfds[1]),因为在这里用不到它。最后,使用
execlp函数把父进程的映像替换为命令wc -1的进程映像,命令wc -1把管道的内容作为它的输入(第23行)。
示例代码3:利用C实现命令的流水线操作的代码
1: #include
2: #include
3: #include
4:
5: int main()
6: …{
7: int pfds[2];
8:
9: if ( pipe(pfds) == 0 ) …{
10:
11: if ( fork() == 0 ) …{
12:
13: close(1);
14: dup2( pfds[1], 1 );
15: close( pfds[0] );
16: execlp( “ls”, “ls”, “-1″, NULL );
17:
18: } else …{
19:
20: close(0);
21: dup2( pfds[0], 0 );
22: close( pfds[1] );
23: execlp( “wc”, “wc”, “-l”, NULL );
24:
25: }
26:
27: }
28:
29: return 0;
30: }
在该程序中,需要格外关注的是,我们的子进程把它的输出重定向的管道的输入,然后,父进程将它的输入重定向到管道的输出。这在实际的应用程序开发中是非常有用的一种技术。
1. 文件描述符在内核中数据结构
在具体说dup/dup2之前, 我认为有必要先了解一下文件描述符在内核中的形态。
一个进程在此存在期间,会有一些文件被打开,从而会返回一些文件描述符,从shell
中运行一个进程,默认会有3个文件描述符存在(0、1、2), 0与进程的标准输入相关联,
1与进程的标准输出相关联,2与进程的标准错误输出相关联,一个进程当前有哪些打开
的文件描述符可以通过/proc/进程ID/fd目录查看。 下图可以清楚的说明问题:
进程表项
————————————————
fd标志 文件指针
_____________________
fd 0:|________|____________|————> 文件表
fd 1:|________|____________|
fd 2:|________|____________|
fd 3:|________|____________|
| ……. |
|_____________________|
图1
文件表中包含:文件状态标志、当前文件偏移量、v节点指针,这些不是本文讨论的
重点,我们只需要知道每个打开的文件描述符(fd标志)在进程表中都有自己的文件表
项,由文件指针指向。
2. dup/dup2函数
APUE和man文档都用一句话简明的说出了这两个函数的作用:复制一个现存的文件描述符。
#include
int dup(int oldfd);
int dup2(int oldfd, int newfd);
从图1来分析这个过程,当调用dup函数时,内核在进程中创建一个新的文件描述符,此
描述符是当前可用文件描述符的最小数值,这个文件描述符指向oldfd所拥有的文件表项。
进程表项
————————————————
fd标志 文件指针
_____________________
fd 0:|________|____________| ______
fd 1:|________|____________|—————-> | |
fd 2:|________|____________| |文件表|
fd 3:|________|____________|—————-> |______|
| ……. |
|_____________________|
图2:调用dup后的示意图
如图2 所示,假如oldfd的值为1, 当前文件描述符的最小值为3, 那么新描述符3指向
描述符1所拥有的文件表项。
dup2和dup的区别就是可以用newfd参数指定新描述符的数值,如果newfd已经打开,则
先将其关闭。如果newfd等于oldfd,则dup2返回newfd, 而不关闭它。dup2函数返回的新
文件描述符同样与参数oldfd共享同一文件表项。
APUE用另外一个种方法说明了这个问题:
实际上,调用dup(oldfd);
等效与
fcntl(oldfd, F_DUPFD, 0)
而调用dup2(oldfd, newfd);
等效与
close(oldfd);
fcntl(oldfd, F_DUPFD, newfd);
3. CGI中dup2
写过CGI程序的人都清楚,当浏览器使用post方法提交表单数据时,CGI读数据是从标准
输入stdin, 写数据是写到标准输出stdout(c语言利用printf函数)。按照我们正常的理
解,printf的输出应该在终端显示,原来CGI程序使用dup2函数将STDOUT_FINLENO(这个
宏在unitstd.h定义,为1)这个文件描述符重定向到了连接套接字。
dup2(connfd, STDOUT_FILENO); /*实际情况还涉及到了管道,不是本文的重点*/
如第一节所说, 一个进程默认的文件描述符1(STDOUT_FILENO)是和标准输出stdout相
关联的,对于内核而言,所有打开的文件都通过文件描述符引用,而内核并不知道流的
存在(比如stdin、stdout),所以printf函数输出到stdout的数据最后都写到了文件描述
符1里面。至于文件描述符0、1、2与标准输入、标准输出、标准错误输出相关联,这
只是shell以及很多应用程序的惯例,而与内核无关。
用下面的流图可以说明问题:(ps: 虽然不是流图关系,但是还是有助于理解)
printf -> stdout -> STDOUT_FILENO(1) -> 终端(tty)
printf最后的输出到了终端设备,文件描述符1指向当前的终端可以这么理解:
STDOUT_FILENO = open(“/dev/tty”, O_RDWR);
使用dup2之后STDOUT_FILENO不再指向终端设备, 而是指向connfd, 所以printf的
输出最后写到了connfd。是不是很优美?:)
4. 如何在CGI程序的fork子进程中还原STDOUT_FILENO
如果你能看到这里,感谢你的耐心, 我知道很多人可能感觉有点复杂, 其实
复杂的问题就是一个个小问题的集合。所以弄清楚每个小问题就OK了,第三节中
说道,STDOUT_FILENO被重定向到了connfd套接字, 有时候我们可能想在CGI程序
中调用后台脚本执行,而这些脚本中难免会有一些输入输出, 我们知道fork之后,
子进程继承了父进程的所有文件描述符,所以这些脚本的输入输出并不会如我们愿
输出到终端设备,而是和connfd想关联了,这个显然会扰乱网页的输出。那么如何
恢复STDOUT_FILENO和终端关联呢?
方法1:在dup2之前保存原有的文件描述符,然后恢复。
代码实现如下:
savefd = dup(STDOUT_FILENO); /*savefd此时指向终端*/
dup2(connfd, STDOUT_FILENO); /*STDOUT_FILENO(1) 被重新指向connfd*/
….. /*处理一些事情*/
dup2(savefd, STDOUT_FILENO); /*STDOUT_FILENO(1) 恢复指向savefd*/
很遗憾CGI程序无法使用这种方法, 因为dup2这些不是在CGI程序中完成的,而是在
web server中实现的,修改web server并不是个好主意。
方法2: 追本溯源,打开当前终端恢复STDOUT_FILENO。
分析第三节的流图, STDOUT_FILENO是如何和终端关联的? 我们重头做一遍不就行
了, 代码实现如下:
ttyfd = open(“/dev/tty”, O_RDWR);
dup2(ttyfd, STDOUT_FILENO);
close(ttyfd);
/dev/tty是程序运行所在的终端, 这个应该通过一种方法获得。实践证明这种方法
是可行的,但是我总感觉有些不妥,不知道为什么,可能一些潜在的问题还没出现。
目前我就想到这两种方法, 不知道你有什么好的想法? 有的话希望告诉我:)
六月 12, 2009
apache+tomcat
安装步骤:
jdk-6u3-linux-i586.bin
#chmod u+x jdk-6u3-linux-i586.bin
#./jdk-6u3-linux-i586.bin
ln -s /usr/local/jdk1.6.0_03 /usr/local/jdk
ln -s /usr/local/jdk1.6.0_03 /jre /usr/local/jre
#vi /etc/profile
加入以下几行
export JAVA_HOME=/usr/local/jdk
export CLASSPATH=$JAVA_HOME/lib
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
export CATALINA_HOME=/usr/local/tomcat
保存退出。
#source /etc/profile
java –version 查看jdk是否安装成功
httpd-2.2.6.tar.gz
#cp httpd-2.2.6.tar.gz /usr/local
#cd /usr/local
#tar zxvf httpd-2.2.6.tar.gz
#cd httpd-2.2.6
#./configure –prefix=/usr/local/apache –enable-module=so
#make
#make install
启动Apache,并测试。
# cd /usr/local/apache/bin
# ./apachectl start
打开浏览器,并在地址栏中输入主机的IP地址
apache-tomcat-6.0.14.tar.gz
#tar zxvf apache-tomcat-6.0.14.tar.gz
#cp –r apache-tomcat-6.0.14 /usr/local/tomcat
#/usr/local/tomcat/bin/startup.sh
打开
http://localhost:8080
验证tomcat可以启动
整和apache和tomcat
tomcat-connectors-1.2.25-src.tar.gz
#tar zxvf tomcat-connectors-1.2.25-src.tar.gz
进行编译配置。大家一定要注意这几个参数中前三个是很重要的,必要时可以去相应的目录看看相关的文件是否存在。
#cd tomcat-connectors-1.2.25-src/native
# ./ buildconf.sh
#./configure –with-apxs=/usr/local/apache/bin/apxs –with-tomcat=/usr/local/tomcat –with-java-home=/usr/java/jdk –with-jni
# make
# make install
#ll /usr/local/apache/modules/mod_jk.so
-rwxr-xr-x 1 root root 487769 8月 14 20:40 /usr/local/apache/modules/mod_jk.so
mod_jk.so生成成功了。
编辑apache的配置文件:
#vi /usr/local/apache/conf/httpd.conf
在末尾添加以下几行
# Load mod_jk module
LoadModule jk_module modules/mod_jk.so
# Where to find workers.properties
JkWorkersFile /usr/local/apache/conf/workers.properties
# Where to put jk logs
JkLogFile /usr/local/apache/logs/mod_jk.log
# Set the jk log level [debug/error/info]
JkLogLevel info
# Select the timestamp log format
JkLogStampFormat “[%a %b %d %H:%M:%S %Y] ”
# JkRequestLogFormat set the request format
JkRequestLogFormat “%w %V %T”
# JkOptions indicate to send SSL KEY SIZE,
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
# Send servlet for context /examples to worker named worker1
#JkMount /examples/*.jsp worker1
JkMount /servlet/* worker1
# Send JSPs for context /examples to worker named worker1
JkMount /*.jsp worker1
创建文件workers.proferties
#vi /usr/local/apache/conf/workers.porperties
添加如下内容:
workers.tomcat_home=/usr/local/tomcat
workers.java_home=/usr/local/jdk
ps=/
worker.list=worker1
worker.worker1.port=8009
worker.worker1.host=localhost
worker.worker1.type=ajp13
worker.worker1.connection_pool_timeout=600
worker.worker1.socket_keepalive=1
worker.worker1.lbfactor=1
worker.inprocess.stdout=$(workers.tomcat_home)$(ps)logs$(ps)inprocess.stdout
worker.inprocess.stderr=$(workers.tomcat_home)$(ps)logs$(ps)inprocess.stderr
5) 配置apache和tomcat的虚拟主机
首先APACHE的虚拟主机设置如下:
修改 conf/httpd.conf找到
# Virtual hosts
#Include conf/extra/httpd-vhosts.conf
修改为
# Virtual hosts
Include conf/extra/httpd-vhosts.conf
然后编辑
conf/extra/httpd-vhosts.conf
加入下面的代码
ServerAdmin oasis.yan@intermobiz.com
DocumentRoot /data/www/test1
ServerName test1.ydjxc.com
DirectoryIndex index.jsp
ErrorLog logs/web_error_log
CustomLog logs/web_access_log common
Options -Indexes FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
ServerAdmin oasis.yan@intermobiz.com
DocumentRoot /data/www/test2
ServerName test2.ydjxc.com
ServerAlias localhost
DirectoryIndex index.jsp
ErrorLog logs/wap_error_log
CustomLog logs/wap_access_log common
Options -Indexes FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
备注:test1/index.jsp的内容如下:
同理为test2/index.jsp
注意:丢掉下面这段代码会提示403错误
Options -Indexes FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
其次Tomcat设置虚拟主机
编辑tomcat的配置文件server.xml
在后面添加如下代码
备注:其中这是两段虚拟主机的代码,红色部分为虚拟目录的配置,这样就可以访问
http://test1.ydjxc.com:8080/test2
http://test2.ydjxc.com:8080/test1
特别注意的地方:
在配置文件中找到:
讲其改为:
如果不改的话,输入:
http://ip:8080
就可以直接进入tomcat的管理界面了。
最后重新启动tomcat和apache,我们的安装就完成了
#/usr/local/tomcat/bin/shutdown.sh //关闭tomcat
#/usr/local/tomcat/bin/startup.sh //启动tomcat
#/usr/local/apache/bin/apachectl restart //重启apache
参考地址
六月 11, 2009
五月 21, 2009
C 指针和数组地址笔记
#include<stdio.h>
int main()
{
int a[5]={1,2,3,4,5];
int *ptr=(int *)(&a+1)
printf(“%d,%d\n”,*(a+1),*(prt-1);
}
~
一定很绕吧,我也糊涂了 琢磨了一早上
C语言里面规定a是数组的首地址是代表整个数组 但&a+1不等价于&a[0]+1, &a是首地址 &a+1就是取a 的地址在加1直接指向下一个内存区域 也就是指向到了ptr[0]的地址是地址上面 然后在把&a+1 的地址复制给ptr指针 这时候ptr变指向了a[5] ,ptr-1=a[4] 最后结果2,5
四月 29, 2009
DNS正向区域
TTL 86400
@ IN SOA dns1.wonxun.com root.wonxun.com (
42 ; serial (d. adams)
3H ; refresh
15M ; retry
1W ; expiry
1D ) ; minimum
IN NS dns1
www IN A 123.123.123.
mail IN A 123.123.123.
dns1 IN A 123.123.123.12
~
四月 28, 2009
SOA资源记录
SOA资源记录 |
| 发布时间:2007.03.29 17:50 来源:赛迪网技术社区 作者:metal |
|
SOA资源记录是一个常常让大家困惑的问题,现在我来详细对它进行说明。
SOA(start of authority)记录定义了DNS授权区域的起始点。
下面先给出一个具体的例子:
@ IN SOA server.lpicn.org. admin.lpicn.org. ( 2003062201 ; Serial 28800 ; Refresh 7200 ; Retry 604800 ; Expire 86400) ; Minimum TTL
例子第一行的“@”表示当前起始点。起始点的含义是,数据文件是为哪个区域创建的,该区域就是当前的起始点。这样的话,这个数据文件中的所有记录都遵从这里的SOA规定,除非它们另有说明(比如ttl说明)。对于其他类型的记录,这里的@也可换成一个主机名如aa,但SOA记录只能用@。因为SOA记录中定义了区传送的时间参数,这必须对应于整个数据文件而不是某条记录。
第一行中的“IN SOA”说明这是一条SOA记录。
第一行中的“server.lpicn.org.”表示该数据文件记录在哪一台主机中,如果这台主机是本区域的,那么必须在该区域文件中定义这台主机。注意这里的最后一个“.”是有意义的,假设这个数据文件是为”lpicn.org.”区域创建的话,那么,如果不写点,而写成”server.lpicn.org”,则相当于写成”server.lpicn.org.lpicn.org.”,这里的内容可参考dns数据文件的语法规定。
第一行中的“admin.lpicn.org.”给出了负责维护域名服务器的管理员的邮件地址,它相当于“admin@lpicn.org”,这里把“@”换成了“.”;
我们可以注意到,在第2至5行的数字外面还套了一对括号。其实是这样的,本来这里所有的数字都是应该写在同一行的,然而,为了看上去方便,我们将之分为5行。使用括号,可以将跨越多行的数据定义在一起,视为一个整行数据处理。
5行数据的前四行都是针对主辅服务器间的区传送而言的。
数据的第一行是序列号,进行区传送时,检查主服务器上的序列号有无变大(比较的方法是辅服务器利用上次从主服务器获得的数据和这次的进行比较),如果变大了,就进行传送,否则不传送。这个序列号可以是小数,如果是小数,也必须按一定的规则转变为整数进行比较。规则是这样的:小数点右边的乘以1000,然后直接把小数点右边的连接到前面乘法运算后的结果之后,如200.1相当于2000001,100.01相当于10000001,这样200.1倒反而比100.01来得小了,所以这种方法很不直观,不推荐使用,但要看的懂,有时还是有用的,因为它可以缩短数字的长度。一种我们推荐的方法是使用如下形式:“年月日第几次”,如2003年6月22日第1次修改用“2003062201”,第二次修改用2003062202,…。当序列号变得很大,需要重新变小时,为了能让区传送继续,一种方法是删除所有辅服务器上的对应区域文件并重启服务,这样来强制执行区传送。
数据的第二行是辅服务器检查主服务器是否同步的间隔时间。
数据的第三行是辅服务器在区传送失败后,等待再次进行区传送的时间间隔。
数据的第四行规定,如果不能保证辅服务器与主服务器同步,最长可以使用辅服务器数据的时间,时间到了之后,仍不能进行传送的话,辅服务器将丢弃对应的数据。
数据的第五行是最小TTL(time-to-live)时间,这是针对缓存而言的,与区传送没有关系。 生存期(TTL)为所容许的名字服务器对数据缓存的时间长度,一旦生存期到了,名字服务器必须丢弃缓存数据并从授权的名字服务器中重新获取新的数据。这样可以确保域数据在整个网络上的一致性。
缓存不仅保存成功查询信息,也保存失败查询信息。我们常有体验,在访问一个叫abcd.efg.com的站点时,如果查询失败,那么,在短时间内重新访问这个站点,会立刻返回这个主机不存在的信息,就是这个道理。在BIND8.2以前的版本中,两种缓存的生存期使用同一个值,而新版本中分别设定值。对于老版本,名字服务器的数据库文件的SOA最后一项就是TTL;而新版本(Bind8.2及以后版本)数据库文件的SOA最后一项是失败信息缓存的生存期,文件的第一行则多了个$TTL,为成功信息的缓存生存期。
最后一点说明,上面的时间在较老的版本都是以秒为单位,新版本中默认以秒为单位,也可根据需要自己指定单位,具体请查阅相关文档。但需注意,对于区传送的时间参数,如果设定为很短时间,比如两秒,则不一定能按照该时间进行,一般会比设定的长一点。
希望上面的内容能够对大家有所帮助。
|
四月 23, 2009
apahe+tomcat 301
- 用Apache的.htaccess来做301域名转向,很牛!
- 由于本人在国外注册的域名在国内访问有点慢,所以需要用国内的免费dns服务器(有免费的,为什么不用?呵…暂时没必要去组一个DNS服务器出来),但这些DNS服务器不支持域名转向,于是只能用别的方法了——这方法很牛:连后面了具体网址,甚至跟了rewrite都可以转向!
- 把代码分享给大家
- 1、开启apache支持.htaccess,方法:
- 在Apache的配置文件httpd.conf中,找到
- <Directory />
- Options FollowSymLinks
- AllowOverride None
- 把其中的AllowOverride None改为AllowOverride All,然后重启apache。
- 2、在网站的根目录下新建一个.htaccess的文件,并把.htaccess文件的权限改成644
- 3、把下面的三行内容复制到这个文件中
- RewriteEngine on
- RewriteCond %{HTTP_HOST} ^aidong.org [NC]
- RewriteRule ^(.*)$ http://www.aidong.org/$1 [L,R=301]
- 记得把域名改成你自己的…
四月 21, 2009
整理一下杂七杂八的postfix+extmail的mail服务器架设维护笔记
前提: 做好DNS的A记录,MX(Mail Exchange mail交换记录)
如:upkiller.com 192.168.1.123
mx=mail.upkiller.com
mail.upkiller.com=192.168.1.123
检查:
nslookup upkiller.com
nslookup -type=MX upkiller.com
输出结果:
upkiller.com MX preference = 1, mail exchanger = mail.upkiller.com
mail.upkiller.com internet address = 192.168.1.123
mail server的备份:可以设置多个邮件交换记录,设置MX优先级,安装多台的主机实现
如:
;Host Address (A记录)
mail1.upkiller.com
mail2.upkiller.com
;Mail Exchanges (MX记录)
upkiller.com IN MX 1 mail1.upkiller.com
upkiller.com IN MX 2 mail2.upkiller.com
邮件传递顺序,优先MX记录,如没有MX记录,尝试将邮件传给该域的A记录ip地址。
—————————————————————————-
SMTP状态码:
2xx 答应要求
4xx 遇到暂时性的错误
5xx 发生永久性问题
——————————————————————————
一 ,安装cyrus-sasl-2.1.22(Simple Authentication and Security Layer)
简单的验证和安全层,smtp发信认证。
ftp://ftp.andrew.cmu.edu/pub/cyrus-mail/cyrus-sasl-2.1.22.tar.gz
tar -zxvf cyrus-sasl-2.1.22.tar.gz
./configure –prefix=/usr/local/sasl2
–disable-gssapi
–disable-anon
–disable-sample
–disable-digest
–enable-plain
–enable-login
–enable-sql
–with-mysql=/usr/local/mysql
–with-mysql-includes=/usr/local/mysql/include/mysql
–with-mysql-libs=/usr/local/mysql/lib/mysql
–with-authdaemond=/usr/local/courier-authlib/var/spool/authdaemon/socket
make
make install
rm /usr/lib/libsasl
关闭原有的sasl链接新的(重要):
mv /usr/lib/libsasl2.a /usr/lib/libsasl2.a.OFF
mv /usr/lib/libsasl2.la /usr/lib/libsasl2.la.OFF
mv /usr/lib/libsasl2.so.2.0.19 /usr/lib/libsasl2.so.2.0.19.OFF
mv /usr/lib/sasl2 /usr/lib/sasl2.OFF
rm /usr/lib/libsasl2.so
rm /usr/lib/libsasl2.so.2
ln -sv /usr/local/sasl2/lib/* /usr/lib
postfix 2.3以后的版本会分别在/usr/local/lib和/usr/local/include中
搜索sasl库文件及头文件,故还须将其链接至此目录中:
ln -sv /usr/local/sasl2/lib/* /usr/local/lib
ln -sv /usr/local/sasl2/include/sasl/* /usr/local/include
创建运行时需要的目录并调试启动
mkdir -pv /var/state/saslauthd
/usr/local/sasl2/sbin/saslauthd -v //看看版本是不是2.1.22
/usr/local/sasl2/sbin/saslauthd -a shadow pam -d //正常不会报错
启动并测试
/usr/local/sasl2/sbin/saslauthd -a shadow pam
/usr/local/sasl2/sbin/testsaslauthd -u root -p password //正常显示0: OK “Success”成功
配置库文件搜索路径,让postfix能找到sasl:
echo “/usr/local/sasl2/lib” >> /etc/ld.so.conf
echo “/usr/local/sasl2/lib/sasl2″ >> /etc/ld.so.conf
ldconfig -v
ldconfig -v | grep sasl2 //看看有没有什么错误
加入开机自启动:
echo “/usr/local/sasl2/sbin/saslauthd -a shadow pam” >> /etc/rc.local
错误FAQ:
1,authentication mechanisms: getpwent pam rimap shadow
echo “/usr/local/sasl2/lib” >> /etc/ld.so.conf
echo “/usr/local/sasl2/lib/sasl2″ >> /etc/ld.so.conf
ldconfig -v
———————————————————————–
二,安装postfix-2.4.5:(Mail Transport agent(MTA)邮件传输代理)
http://www.postfix.org
ftp://ftp.cuhk.edu.hk/pub/packages/mail-server/postfix/index.html
下载:postfix-2.4.5.tar.gz源码包
rpm -e sendmail –nodeps //删除sendmail
//添加postfix用户组和帐号
groupadd -g 2525 postfix
useradd -u 2525 -g postfix -s /sbin/nologin -d /dev/null postfix
groupadd -g 2526 postdrop
useradd -g postdrop -u 2526 -s /bin/false postdrop
tar -zxvf postfix-2.4.5.tar.gz
配置postfix编译参数支持sasl,mysql验证:
make -f Makefile.init Makefiles \
‘CCARGS=-DHAS_MYSQL -I/usr/local/mysql/include/mysql -DUSE_SASL_AUTH -DUSE_CYRUS_SASL -I/usr/local/sasl2/include/sasl’ \
‘AUXLIBS=-L/usr/local/mysql/lib/mysql -lmysqlclient -lz -lm -L/usr/local/sasl2/lib -lsasl2′
(这里要注”这间要有一个空格)
make
make install
安装最后的选项:
install_root:[/] (默认)
tempdir:[/home/postfix-2.4.5] /tmp
config_directory: [/etc/postfix] (默认)
daemon_directory:[/usr/libexec/postfix] /usr/local/postfix/libexec
command_directory:[/usr/sbin] /usr/local/postfix/sbin
queue_directory:[/var/spool/postfix] (默认)
sendmail_path: [/usr/sbin/sendmail] (默认)
newaliases_path: [/usr/bin/newaliases] (默认)
mailq_path: [/usr/bin/mailq] (默认)
mail_owner: [postfix] (默认)
setgid_group: [postdrop] (默认)
html_directory: [no] (默认)
manpages: [/usr/local/man] /usr/local/postfix/man (默认)
readme_directory: [no]
编译postfix错误FAQ:
cannot find -lmysqlclient
严格检查输入是否有误:),’AUXLIBS前面要有空格,或是把mysql库加入搜索路径:
echo /usr/local/mysql/lib/mysql >> /etc/ld.so.conf
ldconfig
最后:
生成别名二进制文件,这个步骤如果忽略,会造成postfix效率极低:
/usr/bin/newaliases
检验postfix是否支持sasl认证,如果输出为以下结果,则支持:
/usr/local/postfix/sbin/postconf -a
cyrus
dovecot
/usr/local/postfix/sbin/postconf -m | grep mysql
mysql
没有的话需重新编译postfix。
————————————————————
启动错误FAQ:
1,postsuper: fatal: scan_dir_push: open directory defer:Permission denied
postfix/postfix-script: fatal: Postfix integrity check failed!
进入postfix-2.4.5源码目录重新make install一遍即可
———————————————————————-
三,配置基本postfix:
修改main.cf配置文件:
vi /etc/postfix/main.cf
myhostname = mail.upkiller.com //主机名称
mydomain = upkiller.com //域名
myorigin = $mydomain //组织名称,邮件标头上面的 mail from 的那个地址
inet_interface = all //监听的网卡接口
mydestination = $myhostname,localhost.$mydomain,localhost,$mydomain //指定postfix系统要接收到哪个域名的邮件
mynetworks = 127.0.0.0/8 //允许不使用smtp发信认证的网段
配置main.cf说明:
1,参数行和注释行是不能处在同一行中,参数不要加引号,=号两边的空格可有可无
2,被引用的参数并不一定要先定义,即顺序颠倒也无所谓。
3,如果参数同时拥有一个以上的值,参数之间可以用逗号,空格|tab,或换行字符隔开。
4,如果参数太多无法放同一行,可以将它们放在不同的行中,只需要在每行前多置一个
tab|空格即可;postfix会把第一个字符为(空格|tab)的行视为前一行的延续。
5,修改后立即生效,重载配置postfix reload,最好可以postfix stop;postfix start
启动postfix测试:
/usr/local/postfix/sbin/postfix check //检查postfix的完整性(没有消息就是good)
/usr/local/postfix/sbin/postfix start
netstat -tnl | grep :25
建立收信测试帐号:
adduser upkiller
passwd upkiller
发信测试:
nc localhost 25
ehlo mail.upkiller.com
250-mail.upkiller.com
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
mail from:root@upkiller.com
rcpt to:upkiller@upkiller.com
data
subject:Postfix mail test!
postfix test!
.
quit
开启另一tty用upkiller登陆:
mail
“/var/spool/mail/upkiller”: 1 message 1new
>N 1 root@upkiller.com Thu Seq 20 05:12 15/547 “Postfix mail test!”
cat /var/spool/mail/upkiller //储存upkiller用户的mail文件
测试成功。
———————————————————————
四,开启cyrus-sasl认证功能:
vi main.cf
#====================SASL========================
broken_sasl_auth_clients = yes
smtpd_recipient_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_invalid_hostname,
reject_non_fqdn_hostname,
reject_unknown_sender_domain,
reject_non_fqdn_sender,
reject_non_fqdn_recipient,
reject_unknown_recipient_domain,
reject_unauth_pipelining,
reject_unauth_destination,
permit
smtpd_sasl_auth_enable = yes
smtpd_sasl_local_domain = $domain
smtpd_sasl_security_options = noanonymous
smtpd_sasl_application_name = smtpd
smtpd_banner = $myhostname ESMTP $mail_name ($mail_version)
#编辑smtpd.conf
vi /usr/local/lib/sasl2/smtpd.conf
内容:
pwcheck_method: saslauthd
mech_list: PLAIN LOGIN
重新启动postfix:
/usr/local/postfix/sbin/postfix stop
/usr/local/postfix/sbin/postfix start
测试:
adduser upkiller
passwd upkiller
//取base64编码
perl -MMIME::Base64 -e ‘print encode_base64(“upkiller”)’
dxBraWxsZXI=
nc localhost 25
220 mail.upkiller.com ESMTP Postfix (2.4.5)
ehlo mail.upkiller.com
250-mail.upkiller.com
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-AUTH PLAIN LOGIN (看见这二行即成功)
250-AUTH=PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
auth login
334 VXNlcm5hbWU6
dXBraWxsZXI=
334 VXNlcm5hbWU6
dXBraWxsZXI=
235 2.0.0 Authentication successful
mail from:root@upkiller.com
rcpt to:upkiller@upkiller.com
data
subject:smtp authentication test!
test ok
.
quit
错误FAQ:
tail -f /var/log/maillog
1,fatal: SASL per-connection initialization failed
warning: /usr/local/libexec/postfix/smtpd: bad command startup
解决方法:
sasl2没装好,和旧的冲突,重新安装sasl2把sasl2装在/usr/local/sasl2下再关闭旧的
文件,连接新的,确保系统能找到的include和lib文件都是新编的,
再重编译postfix即可
2,NIS domain name not set NIS lookups disabled
提示没有启动NIS
alias_maps = $alias_database
强制postfix只使用本地的aliases资料库。
————————————————————-
五,让postfix支持mysql的虚拟域和虚拟用户:
1、编辑/etc/postfix/main.cf,添加如下内容:
vi /etc/postfix/main.cf
#================ Virtual Mailbox Settings =====================#
# 指定用户邮箱所在的根目录
virtual_mailbox_base = /var/mailbox
#指定postfix如何去检索邮箱,这里是采用mysql
virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf
#指定postfix如何去检索虚拟域
virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_domains_maps.cf
virtual_alias_domains =
#指定postfix如何去检索虚拟别名
virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf
#邮件账号uid, 即postfix组id号(即/var/mailbox目录所有者的帐号)
virtual_uid_maps = static:2525
virtual_gid_maps = static:2525
#如果没有安装maildrop,则此处为virtual
virtual_transport = virtual
maildrop_destination_recipient_limit = 1
maildrop_destination_concurrency_limit = 1
#================ QUOTA Settings =============================#(邮箱限额)
#每封信的最大(10M),postfix的默认值是10M, 但这指的是邮件正文和编码后附件的总和
#, 经过#base64编码,附件的大小会增加35%左右, 因此这里设定可接受邮件的大小为14M
message_size_limit = 14336000
virtual_mailbox_limit = 20971520
virtual_create_maildirsize = yes
virtual_mailbox_extended = yes
#指定postfix如何获得用户的quota信息(每个用户的邮箱大小)
virtual_mailbox_limit_maps =
mysql:/etc/postfix/mysql_virtual_mailbox_limit_maps.cf
# 是否允许覆盖默认邮箱的大小
virtual_mailbox_limit_override = yes
virtual_maildir_limit_message = Sorry, the user’s maildir has overdrawn his diskspace quota, please Tidy your mailbox and try again later.
virtual_overquota_bounce = yes
2、添加为支持虚拟域和虚拟用户所用到的配置文件:
vi /etc/postfix/mysql_virtual_alias_maps.cf //虚拟别名:
user = extmail
password = extmail
hosts = localhost
dbname = extmail
table = alias
select_field = goto
where_field = address
additional_conditions = AND active = ‘1′
vi /etc/postfix/mysql_virtual_domains_maps.cf //虚拟域
user = extmail
password = extmail
hosts = localhost
dbname = extmail
table = domain
select_field = domain
where_field = domain
additional_conditions = AND active = ‘1′
vi /etc/postfix/mysql_virtual_mailbox_limit_maps.cf //虚拟邮箱容量
user = extmail
password = extmail
hosts = localhost
dbname = extmail
table = mailbox
select_field = quota
where_field = username
additional_conditions = AND active = ‘1′
vi /etc/postfix/mysql_virtual_mailbox_maps.cf //虚拟邮箱
user = extmail
password = extmail
hosts = localhost
dbname = extmail
table = mailbox
select_field = maildir
where_field = username
additional_conditions = AND active = ‘1′
//新建虚拟用户邮箱所在目录,postfix用户所有:
mkdir -pv /var/mailbox
chown -R postfix:postfix /var/mailbox
//开启smtp也从mysql中验证帐号:
vi /usr/local/lib/sasl2/smtpd.conf (/usr/lib/sasl2连接到该目录)
pwcheck_method: auxprop
auxprop_plugin: sql
mech_list: PLAIN LOGIN
sql_engine: mysql
sql_hostname: localhost
sql_user: extmail
sql_passwd: extmail
sql_database: extmail
sql_select: SELECT password FROM mailbox WHERE username=’%u@%r’ and
domain=’%r’ and active=’1′
(%u表示登录的用户名,%r表示smtpd_sasl_local_domain = $myhostname 的值)
重启postfix
//打开mysql的查询日志功能
vi /etc/my.cnf
[mysqld]
log=/var/log/mysqld/log.log
创建日志文件并设置权限
mkdir /var/log/mysqld
touch /var/log/mysqld/log.log
chown -R mysql:mysql /var/log/mysqld
//重启mysql
service mysqld stop
service mysqld start
//测试postfix连接mysql数据库查询认证
//取base64编码
perl -MMIME::Base64 -e ‘print encode_base64(“upkiller”)’
dxBraWxsZXI=
nc localhost 25
220 mail.upkiller.com ESMTP Postfix (2.4.5)
ehlo mail.upkiller.com
250-mail.upkiller.com
250-PIPELINING
250-SIZE 10240000
250-VRFY
250-ETRN
250-AUTH PLAIN LOGIN (看见这二行即成功)
250-AUTH=PLAIN LOGIN
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 DSN
auth login
334 VXNlcm5hbWU6
dXBraWxsZXI=
334 VXNlcm5hbWU6
dXBraWxsZXI=
235 2.0.0 Authentication successful
tail -f /var/log/mysqld/log.log
提示如下日志:
connect postfix@localhost on postfix
SELECT password FROM mailbox WHERE username=’upkiller@upkiller.com’ and
domain=’upkiller.com’ and active=’1′
tail -f /var/log/maillog
验证错误提示:
SASL login authentication failed: authentication failure
成功:connect from localhost.localdomain
把原先系统的cyruss-sasl删除,再重新编译cyrus-sasl和postfix:
rpm -e `rpm -qa | grep cyrus-sasl` –nodeps
一般都是没有安装和配置好courier authentication.
再做其它各种查询测试:
//邮箱
postmap -q ‘maps’ mysql:/etc/postfix/mysql_virtual_mailbox_maps.cf
SELECT maildir FROM mailbox WHERE username=’maps’
//别名
postalias -q ‘alias’ mysql:/etc/postfix/mysql_virtual_alias_maps.cf
SELECT goto FROM alias WHERE address=’alias’
——————————————————————————–
六,安装Courier authentication library:
新版本的imap不再包含authentication library,必须先安装 Courier authentication library
http://kent.dl.sourceforge.net/sourceforge/courier/
下载:
http://www.mirrorservice.org/sites/download.sourceforge.net/pub/sourceforge/c/co/courier/courier-authlib-0.59.3.tar.bz2
解压编译安装:
tar jxvf courier-authlib-0.59.3.tar.bz2
cd courier-authlib-0.59.3
./configure –prefix=/usr/local/courier-authlib \
–sysconfdir=/etc \
–without-authpam \
–without-authldap \
–without-authpwd \
–without-authshadow \
–without-authvchkpw \
–without-authpgsql \
–with-authmysql \
–with-mysql-libs=/usr/local/mysql/lib/mysql \
–with-mysql-includes=/usr/local/mysql/inculde/mysql \
–with-redhat \
–with-authmysqlrc=/etc/authmysqlrc \
–with-authdaemonrc=/etc/authdaemonrc \
#优化
CFLAGS=”-march=i686 -O2 -fexpensive-optimizations”
CXXFLAGS=”-march=i686 -O2 -fexpensive-optimizations”
make
make install
chmod 755 /usr/local/courier-authlib/var/spool/authdaemon
cp /etc/authdaemonrc.dist /etc/authdaemonrc
cp /etc/authmysqlrc.dist /etc/authmysqlrc
编辑authdaemonrc(确保只使用mysql认证):
vi authdaemonrc
authmodulelist=”authmysql”
authmodulelistorig=”authmysql”
daemons=10
DEBUG_LOGIN=2 (打开日志方便调试,调试成功之后再关闭)
编辑/etc/authmysqlrc 为以下内容,其中2525,2525 为postfix 用户的UID和GID:
MYSQL_SERVER localhost
MYSQL_PORT 3306 (指定你的mysql监听的端口3306)
MYSQL_USERNAME extmail (extmail数据库的所有者的用户名)
MYSQL_PASSWORD extmail (数据库帐户密码)
MYSQL_SOCKET /tmp/mysql.sock
MYSQL_DATABASE extmail
MYSQL_USER_TABLE mailbox
MYSQL_CRYPT_PWFIELD password
MYSQL_UID_FIELD ‘2525′
MYSQL_GID_FIELD ‘2525′
MYSQL_LOGIN_FIELD username
MYSQL_HOME_FIELD concat(‘/var/mailbox/’,homedir)
MYSQL_NAME_FIELD name
MYSQL_MAILDIR_FIELD concat(‘/var/mailbox/’,maildir)
注意:确认在这个文件中不能用空格键,只能用tab键。
确认只使用单引号,比如:’/var/mailbox/’,'UID’,'GID’
localhost不能用单引号
确认你的/etc/hosts文件中有localhost
编译时如果支持Ipv6可能导致错误
MYSQL_GID_FIELD 和MYSQL_UID_FIELD是maildrop的UID和GID,而不是MySQL的。
如果想使用md5密码,把MYSQL_CLEAR_PWFIELD password改成MYSQL_CRYPT_PWFIELD password
加入库搜索路径:
echo “/usr/local/courier-authlib/lib/courier-authlib” >> /etc/ld.so.conf
ldconfig -v
加入开机启动:
cp courier-authlib.sysvinit /etc/init.d/courier-authlib
chmod 755 /etc/init.d/courier-authlib
chkconfig –add courier-authlib
chkconfig –level 35 courier-authlib on
手动启动:
/usr/local/courier-authlibn/sbin/authdaemond start
检测是否启动成功:
pstree | grep authdaemond
——————————————–
错误FAQ:
1,MYSQL_SERVER: command not found等一大堆参数错误
原来是
cp /etc/authmysqlrc.dist /etc/authdaemonrc
时复制文件名错误:(
2,configure: error: –with-authmysql specified but no mysqlclient.so
checking for mysql_config… /usr/bin/mysql_config
checking for mysql_connect… no
checking for mysql_real_connect… no
rm /usr/bin/mysql_config
ln -s /usr/local/mysql/bin/mysql_config /usr/bin/mysql_config
再不行:
ln -s libmysqlclient.so.15 libmysqlclient.so.12
ln -s libmysqlclient.so.15 mysqlclient.so
——————————————————————————–
七,安装Courier-IMAP(提供POP3/IMAP服务):
下载:
http://surfnet.dl.sourceforge.net/sourceforge/courier/courier-imap-4.1.3.tar.bz2
tar jxvf courier-imap-4.1.3.tar.bz2
cd courier-imap-4.1.3
./configure –prefix=/usr/local/courier-imap \
–with-redhat \
–enable-unicode=utf-8,iso-8859-1,gb2312,gbk,gb18030 \
–disable-root-check \
–with-trashquota \
–without-ipv6 \
CPPFLAGS=’-I/usr/local/courier-authlib/include’ \LDFLAGS=’-L/usr/local/courier-authlib/lib/courier-authlib’ \
COURIERAUTHCONFIG=’/usr/local/courier-authlib/bin/courierauthconfig’
make
make install
//建立配置文件
cd /usr/local/courier-imap/etc
ls *.dist | awk -F”.” ‘{print “cp “$0″ “$1″”}’ | sh
//打开pop3,imapd支持,修改MAILPATH
vi /usr/local/courier-imap/etc/pop3d
POP3DSTART=YES
MAILDIRPATH=/var/mailbox
vi /usr/local/courier-imap/etc/imapd
IMAPDSTART=YES
MAILPATH=/var/mailbox
//加入开机启动
cp courier-imap.sysvinit /etc/rc.d/init.d/courier-imapd
chmod 755 /etc/rc.d/init.d/courier-imapd
chkconfig –add courier-imapd
chkconfig –level 2345 courier-imapd on
service courier-imapd start
检测:
netstat -tnl |egrep “110|143″
新建虚拟用户邮箱所在的目录,并将其权限赋予postfix用户:
#mkdir –pv /var/mailbox
#chown –R postfix /var/mailbox
接下来重新配置SMTP 认证,编辑 /usr/local/lib/sasl2/smtpd.conf ,确保其为以下内容:
pwcheck_method: authdaemond
log_level: 3
mech_list: PLAIN LOGIN
authdaemond_path:/usr/local/courier-authlib/var/spool/authdaemon/socket
验证:
nc localhost 25 (重复上面的)
tail -f /var/log/mysqld/log.log
如果有下面:
SELECT username,password, “”, ‘2525′, ‘2525′,concat(‘/var/mailbox/’,homedir)..
表示重新配置的smtp验证成功了。
———————————————-
调试:pop3
编辑authdaemonrc:
DEBUG_LOGIN=2 (打开日志方便调试,调试成功之后再关闭)
tail -f /var/log/maillog
nc localhost 110
user user1@extmail.org
user user
list
retr 1
quit
——————————————————————–
———————————————————————
安装extman:
tar -zxvf extman-0.2.2.tar.gz
mv extman-0.2.2 /var/www/extsuite/extman
cd /var/www/extsuite/extman
vi webman.cf
SYS_MAILDIR_BASE = /home/domains
此处即为您在前文所设置的用户邮件的存放目录,可改作:
SYS_MAILDIR_BASE = /var/mailbox
SYS_MYSQL_SOCKET = /var/lib/mysql/mysql.sock
此处修改为:
SYS_MYSQL_SOCKET = /tmp/mysql.sock
SYS_DEFAULT_GID = 2525 //即postfix组gid
更改目录的权限:
chown -R postfix.postfix /var/www/extsuite/extmail/cgi/
chown -R postfix.postfix /var/www/extsuite/extman/cgi/
mkdir /tmp/extman
chown -R postfix:postfix /tmp/extman
配置apache:
<VirtualHost *>
ServerAdmin admin@upkiller.com //管理员邮件
ServerName upkiller.com //域名
ServerAlias www.upkiller.com //别名
DocumentRoot /var/www/extsuite/extmail/html //网站目录
ScriptAlias /extmail/cgi /var/www/extsuite/extmail/cgi //脚本执行别名
Alias /extmail /var/www/extsuite/extmail/html //别名
ScriptAlias /extman/cgi /var/www/extsuite/extman/cgi
Alias /extman /var/www/extsuite/extman/html
SuexecUserGroup postfix postfix //切换到postfix帐户运行
<Directory /var/www/extsuite> //目录权限
Options Indexes FollowSymLinks //允许符号链接,访问不在本目录下的文件
AllowOverride None //禁止读取.htaccess
Order allow,deny //指定先执行Allow访问规则,再执行Deny访问规则
Allow from all //允许访问所有
</Directory>
</VirtualHost>
——————————————————————————
安装extman的图形日志:
1,在首先在http://search.cpan.org
搜索:Time::HiRes和File::Tail:并下载
http://oss.oetiker.ch/rrdtool/pub/?M=D 下载rrdtool-1.2.23.tar.gz
安装Time::HiRes
tar zxvf Time-HiRes-1.9707.tar.gz
cd Time-HiRes-1.9707
perl Makefile.PL
make
make test
make install
安装File::Tail
tar zxvf File-Tail-0.99.3.tar.gz
cd File-Tail-0.99.3
perl Makefile.PL
make
make test
make install
安装rrdtool-1.2.23
tar zxvf rrdtool-1.2.23.tar.gz
cd rrdtool-1.2.23
(需要libart_lgpl-devel,libpng-devel,tcl-devel,freetype,libpng)
./configure –prefix=/usr/local/rrdtool
make
make install
(如果出現 make[3]: *** [tclrrd.o] 错误 1
make[3]: Leaving directory `/home/cacti/rrdtool-1.2.10/bindings/tcl’
make[2]: *** [all-recursive] 错误 1
make[2]: Leaving directory `/home/cacti/rrdtool-1.2.10/bindings’
make[1]: *** [all-recursive] 错误 1
make[1]: Leaving directory `/home/cacti/rrdtool-1.2.10′
make: *** [all] 错误 2
可以./configure –prefix=/usr/local/rrdtool \
–disable-tcl
也可以
rrdtool-1.2.10 的安裝
# declare
export BUILD_DIR=/tmp/rrdtool
# Install cgilib
cd cgilib-0.5
make CC=gcc CFLAGS=”-O3 -fPIC -I.”
mkdir -p $BUILD_DIR/lb/include
cp *.h $BUILD_DIR/lb/include
mkdir -p $BUILD_DIR/lb/lib
cp libcgi* $BUILD_DIR/lb/lib
# Install zlib
cd zlib-1.2.2
env CFLAGS=”-O3 -fPIC” ./configure –prefix=$BUILD_DIR/lb
make
make install
# Install libpng
cd libpng-1.2.8-config
env CPPFLAGS=”-I$BUILD_DIR/lb/include” LDFLAGS=”-L$BUILD_DIR/lb/lib” CFLAGS=”-O3 -fPIC” ./configure –disable-shared –prefix=$BUILD_DIR/lb
make
make install
# Install freetype
cd freetype-2.1.9
env CPPFLAGS=”-I$BUILD_DIR/lb/include” LDFLAGS=”-L$BUILD_DIR/lb/lib” CFLAGS=”-O3 -fPIC” ./configure –disable-shared –prefix=$BUILD_DIR/lb
make
make install
## Install libart_lgpl
cd libart_lgpl-2.3.17
env CFLAGS=”-O3 -fPIC” ./configure –disable-shared –prefix=$BUILD_DIR/lb
make
make install
# Install rrdtool
cd rrdtool-1.2.10
IR=-I$BUILD_DIR/lb/include
CPPFLAGS=”$IR $IR/libart-2.0 $IR/freetype2 $IR/libpng”
LDFLAGS=”-L$BUILD_DIR/lb/lib”
CFLAGS=-O3
export CPPFLAGS LDFLAGS CFLAGS
./configure prefix=/usr/local/rrdtool –disable-tcl
make
make install)
错误:I found a copy of pkgconfig, but there is no freetype2.pc
cd /usr/src/freetype-2.2.1
find . -name “*.pc
cp builds/unix/freetype2.pc /usr/lib/pkgconfig/
复制mailgraph_ext到/usr/local,并启动之
cp -r /var/www/extsuite/extman/addon/mailgraph_ext /usr/local
/usr/local/mailgraph_ext/mailgraph-init start
启动报错:
Can’t locate RRDs.pm in @INC…..
解决方法:
find /usr -name “RRDs.pm”
ln -sv /usr/local/rrdtool/lib/perl/5.8.5/i386-linux-thread-multi/RRDs.pm /usr/lib/perl5/5.8.5
再启动:
Can’t locate loadable ojbect for module RRDs
解决:
ln -sv /usr/local/rrdtool/lib/perl/5.8.5/i386-linux-thread-multi/auto/RRDs/RRDs.so /usr/lib/perl5/5.8.5/i386-linux-thread-multi/
再启动ok
(如果碰到少别的模块都可以用查找链接这种方法解决,找不到就是没安装咯,一个是pm模块,一个是so库)
/usr/local/mailgraph_ext/qmonitor-init start //启动ok
打开extman后台管理,打开图形日志,没报错就ok啦。
再加入开机启动:
echo “/usr/local/mailgraph_ext/mailgraph-init start” >> /etc/rc.local
———————————————————————–
Extman FAQ:
1,extman默认登录密码:
默认管理帐号为:root@extmail.org 密码为:extmail*123*
2,第一次配置好extmail打开浏览器提示:
Unix::Syslog not found, please install it first! (in cleanup) Undefined subroutine &Ext::Logger::do_closelog called at /var/www/extsuite/extmail/libs/Ext/Logger.pm line 87.
没装perl-Unix-Syslog包,
安装perl-Unix-Syslog-0.100-1hzq.i386.rpm搞定
或是到http://search.cpan.org搜索Syslog下载一个Unix-Syslog-0.100.tar.gz
tar zxvf Unix-Syslog-0.100.tar.gz
cd Unix-Syslog-0.100
perl Makefile.PL
make
make install
3,install_driver(mysql) failed: Can’t locate DBD/mysql.pm in
搜索DBD-mysql-4.005.tar.gz下载,安装,结果提示如下
4,之后提示Internal Server Error:
tail -f error_log
/usr/bin/perl: symbol lookup error: /usr/lib/perl5/site_perl/5.8.5/i386-linux-thread-multi/auto/DBD/mysql.so: undefined symbol: DBIc_TRACE_LEVEL
//肯定是DBD-MYSQL版本不兼容问题:
find /usr/lib -name “mysql.so” -exec rm {} \;
http://search.cpan.org/dist/DBD-mysql/下载:DBD-mysql-3.0002_4.tar.gz
perl Makefile.PL
make
make install
(再打开ok)
如果还是显示内部服务器错误,apache的error_log还提示:
suexec policy violation: see suexec log for more details
Premature end of script headers: index.cgi
提示查看su日志:
———————————-
关于suexec的FAQ
1.出现以下错误 command not in docroot
编译的时候加入–with-suexec-docroot 以后虚拟主机运行suexec的目录必须包含指定的目录里,通过suexec -V 可以察看docroot目录是哪儿
2.出现以下错误 user mismatch (daemon instead of www)
编译的时候加入–with-suexec-caller=daemon 默认是www,但一般apache的运行用户是nobody或者daemon,这里我们是httpd2.2.2,用户是daemon,所以指定这个参数,否则suexec不能被运行。
3.出现以下错误 cannot run as forbidden uid (1001/index.cgi)
在虚拟主机配置SuexecUserGroup时,指定的用户和组,必须高于–with-suexec-uidmin –with-suexec-gidmin 指定的用户uid和gid,否则被限制使用。
————————————————
编译Apache的时候要加上:
–enable-suexec \
–with-suexec-caller=daemon \
–with-suexec-docroot=/var/www/extsuite/
临时用postfix,再去su:
5,又提示:DBI connect(‘database=extmail;host=localhost;mysql_socket=/var/lib/mysql/mysql.sock’,
‘extmail’,…)failed: Can’t connect to local MySQL server
vi /var/www/extsuite/extmail/webmail.cf
改:SYS_MYSQL_SOCKET = /tmp/mysql.sock
vi /var/www/extsuite/extman/webman.cf (同上)
(再打开ok)
6,Can’t open /tmp/extman//sid_8519f707216994462c48dcd98b655843, No such file or directory
mkdir /tmp/extman
chown -R postfix:postfix /tmp/extman
7,进入extman无法显示校验码图片:
tail -f error_log
BEGIN failed–compilation aborted at /var/www/extsuite/extman/libs/Ext/GD.pm line 14
http://search.cpan.org/~lds/GD-2.35/
perl Makefile.PL
提示gd装在哪/usr/local/gd2/lib
(选图片支持)
Where is libgd installed? [/usr/lib] /usr/local/gd2
Build JPEG support? [y] y
Build PNG support? [y] y
Build FreeType support? [y] y
Build GIF support? [y] y
Build support for animated GIFs? [y] y
Build XPM support? [y] n
make
make install
错误:cannot find -lpng
ln -vs /usr/local/libpng2/lib/* /usr/lib
错误:cannot find -lfreetype
ln -vs /usr/local/freetype2/lib/* /usr/lib
错误:cannot find -ljpeg
ln -vs /usr/local/jpeg6/lib/* /usr/lib
再重新make clean
perl Makefile.PL (成功)
或是:
extman登录不要校验码:
在 webman.cf 将 SYS_CAPTCHA_ON=0 即可,要重启 Apache
8,新建两个域,各建帐号测试发信:
测试帐号和密码是否正常:
/usr/local/courier-authlib/sbin/authtest user1@rohto.com.cn user1
变更密码;
./authtest -s localhost user1@rohto.com.cn user user1
错误FAQ:Can’t chdir to /var/mailbox/rohto.com.cn/user1/Maildir/, No such file or directory
查看extman的:
SYS_MAILDIR_BASE = /var/mailbox
配置是否正确,删除域名再重建,在新建用户的时候会自动在/var/mailbox/下创建该用户的域名和邮件目录
登入extmail进行各种发信测试:
发给自己
发给同域帐号
发给不同域帐号
发给163收信
用163收信给自己
再使用outlook/foxmail进行如上测试:
———————————-
通过日志分析发信过程:
tail -f /var/log/maillog
成功的日志如下:
postfix/pickup[2215]: 5705EA885D: uid=255 from=<user1@upkiller.com>
postfix/cleanup[3267]: 5705EA885D: message-id=<20070922224616.5705EA885D@mail.upkiller.com>
postfix/qmgr: 5705EA885D: from=<user1@upkiller.org>, size=515,nrcpt=1 (queue active)
postfix/virtual[3271]: 5705EA885D: to=<upkiller@163.org>, relay=mx.mail.163.split.netease.com ,delay=0.13,delays=
0.1/0.02/0.0.01,dsn=2.0.0,status=send (delivered to maildir)
postfix/qmgr[2214]: 5705EA885D: removed
发信错误FAQ:
1,不能发送邮件:
warning: do not list domain upkiller.com in BOTH mydestination and virtual_mailbox_domains
明显是指这个域名不在mydestination许可的列表
解决方法:
在有多域的服务器上直接把mydestination选项在/etc/postfix/main.cf注释掉:
2,虚拟域不能发送邮件给自己:
Sep 28 14:01:10 rohto postfix/local[2377]: 07AC332E69: to=<user2@xxxx.com.cn>, relay=local, delay=0.71, delays=0.41/0.16/0/0.14, dsn=5.1.1, status=bounced (unknown user: “user2″)
1)首先确定:
extman/webman.cf文件中:
SYS_DEFAULT_GID = 2525
修改后进入/var/mailbox/domain.com.cn中rm -rf *
2)原来是在main.cf文件中myhostname与mydomain不能一样,要不然
虚拟域和main.cf中设的域名一样就会出现问题:(kao)
myhostname = xxx.com.cn
mydomain = xxxx.com.cn
修改如下:
myhostname = mail.xxx.com.cn
mydomain = xxxx.com.cn
3,两台extmail互发邮件拒绝:
Recipient address rejected: Try again, see http://bl.extmail.org/cgi/why?greylist (in
reply to RCPT TO command)
//接收地址拒绝,再次尝试,查看http://bl.extmail.org/cgi/why?greylist
上面的解释:
您的主机将被greylist临时封锁 (300 秒
这是您第一次发信给收件人,请隔一段时间重试
前后两次发信间隔小于阀值 (300秒)
等待300秒再发送,没有问题。
解决办法:
修改:/usr/local/slockd/config/whitelist
4,无法向其它服务器发送邮件提示:
Host or domain name not found. Name service error for name=163.com type=MX: Host not found, try again
mail服务器resolv.conf未设好
5,向163发信提示:
http://mail.163.com/help/help_spam_16.htm (in reply to end of DATA command)
反病毒
反垃圾
————————————
小技巧:
1,反解不存在的机器将被拦截:
smtpd_client_restrictions = reject_unknown_client ( 如果是postfix 2.3或以上,则是reject_unknown_client_hostname)
2,日志分析技巧:
1)postfix日志成功接收到邮件:(交货到邮件目录)
cat /var/log/maillog |grep “delivered to maildir”
cat /var/log/maillog |grep “delivered to maildir” | egrep -o “(\w+)([@]{1}\w+[.]{1,})(\w+)”
2)取当天日志:
cat /var/log/maillog | egrep “`data | awk “`’{print “”$2″ “$3″”}’`”
3)取指定日期的错误日志:
cat /var/log/maill | grep “^Sep\ 25″ | egrep “reject|warning|error|fatal|panic” | more