明明白白你的Linux服务器—日志篇

日志对于安全来说,非常重要,它记录了系统每天发生的各种各样的事情,你可以通过他来检查错误发生的原因,或者受到攻击时攻击者留下的痕迹。日志主要的功能有:审计和监测。他还可以实时的监测系统状态,监测和追踪侵入者等等。

  一、配置syslog

  目前,linux依旧使用syslogd作为日志监控进程,对其进行必要的配置能减少很多麻烦,并且可更有效的从系统日志监控到系统的状态。理解并完善一个syslog的配置,对于系统管理员来说显得尤为重要。

  /etc/syslog.conf根据如下的格式定义规则: facility.level action

  设备.优先级 动作facility.level 字段也被称为seletor(选择条件),选择条件和动作之间用空格或tab分割开。

  #号开头的是注释,空白行会自动跳过。

  1、facility

  facility定义日志消息的范围,其可使用的key有: auth -由 pam_pwdb 报告的认证活动。

  authpriv -包括特权信息如用户名在内的认证活动

  cron -与 cron 和 at 有关的计划任务信息。

  daemon -与 inetd 守护进程有关的后台进程信息。

  kern -内核信息,首先通过 klogd 传递。

  lpr -与打印服务有关的信息。

  mail -与电子邮件有关的信息

  mark - syslog内部功能用于生成时间戳

  news -来自新闻服务器的信息

  syslog -由 syslog 生成的信息

  user -由用户程序生成的信息

  uucp -由 uucp 生成的信息

  local0-local7 -与自定义程序使用

  * 通配符代表除了 mark 以外的所有功能除mark为内部使用外,还有security为一个旧的key定义,等同于auth,已经不再建议使用。

  2、level级别

  level定义消息的紧急程度。按严重程度由高到低顺序排列为: emerg -该系统不可用,等同panic

  alert -需要立即被修改的条件

  crit -阻止某些工具或子系统功能实现的错误条件

  err -阻止工具或某些子系统部分功能实现的错误条件,等同error

  warning -预警信息,等同warn

  notice -具有重要性的普通条件

  info -提供信息的消息

  debug -不包含函数条件或问题的其他信息

  none -没有重要级,通常用于排错

  * 所有级别,除了none其中,panic、error、warn均为旧的标识符,不再建议使用。

  在定义level级别的时候,需要注意两点: 1)优先级是由应用程序在编程的时候已经决定的,除非修改源码再编译,否则不能改变消息的优先级;

  低的优先级包含高优先级,例如,为某个应用程序定义info的日志导向,则涵盖notice、warning、err、crit、alert、emerg等消息。(除非使用=号定义)

  3、selector选择条件

  通过小数点符号“.”把facility和level连接在一起则成为selector(选择条件)。

  可以使用分号“;”同时定义多个选择条件。也支持三个修饰符: * - 所有日志信息

  = - 等于,即仅包含本优先级的日志信息

  ! - 不等于,本优先级日志信息除外

  4、action动作

  由前面选择条件定义的日志信息,可执行下面的动作: file-指定日志文件的绝对路径

  terminal 或 print -发送到串行或并行设备标志符,例如/dev/ttyS2

  @host -远程的日志服务器

  username -发送信息本机的指定用户信息窗口中,但该用户必须已经登陆到系统中

  named pipe -发送到预先使用 mkfifo 命令来创建的 FIFO 文件的绝对路径※注意,不能通过“|/var/xxx.sh”方式导向日志到其他脚本中处理。

  5、举例

  例如: *.info;mail.none;news.none;authpriv.none;cron.none /var/log/messages

  #把除邮件、新闻组、授权信息、计划任务等外的所有通知性消息都写入messages文件中。

  mail,news.=info /var/adm/info

  #把邮件、新闻组中仅通知性消息写入info文件,其他信息不写入。

  mail.*;mail.!=info /var/adm/mail

  #把邮件的除通知性消息外都写入mail文件中。

  mail.=info /dev/tty12

  #仅把邮件的通知性消息发送到tty12终端设备

  *.alert root,joey

  #如果root和joey用户已经登陆到系统,则把所有紧急信息通知他们

  *.* @finlandia

  #把所有信息都导向到finlandia主机(通过/etc/hosts或dns解析其IP地址)※注意:每条消息均会经过所有规则的,并不是唯一匹配的。

  也就是说,假设mail.=info信息通过上面范例中定义的规则时,/var/adm/info、/var/adm/mail、/dev/tty12,甚至finalandia主机都会收到相同的信息。这样看上去比较烦琐,但可以带来的好处就是保证了信息的完整性,可供不同地方进行分析。

二、messages日志

  首先说下我们最关注的系统/var/log/messages,这东东不仅是咱们服务器的系统日志,很多时候它也做了许多服务的日志,这也是它被称为杂货铺的原因,值得重点关注,大家一般都喜欢用以下命令看最后十条日志

  tail -n10 /var/log/messages

  其实还可以将一段日志保存成文件,正用练下自己的awk、sed和grep水平;或者直接用vim来查看,这也是算是一种经验之谈吧。我以前配置bind的主从复制,有时因为权限的原因报错;这时可以在一台报错的服务器上用命令tail -f /var/log/messages实时查看服务器的变化情况,从中查找错误的蛛丝马迹;事实证明,效果很好,而且用于lvs+keepalived的排错效也不错,其它事例依此类推。

  三、secure的用法

  /var/log/secure:记录登入系统存取数据的文件,例如 pop3, ssh, telnet, ftp 等都会被记录,我们可以利用此文件找出不安全的登陆IP。

 点击查看原图

  四、记录登陆者的数据

  /var/log/wtmp:记录登入者的讯息数据,由于本文件已经被编码过(为二进制文件),所以必须使用 last指令来取出文件的内容,你用cat等命令直接查看此文件是不行的。

  五、lastlog记录系统时间

  /var/log/lastlog : 记录每个使用者最近签入系统的时间, 因此当使用者签入时, 就会显示其上次签入的时间,您应该注意一下这个时间, 若不是您上次签入的时间, 表示您的帐号可能被人盗用了。 此档可用 /usr/bin/lastlog 指令读取(Freebsd下为/usr/sbin/lastlogin)。

  六、用dmesg查看启动消息

  dmesg提供了一个简单的方法查看系统启动信息。当Linux启动的时候,内核的信息被存入内核ring缓存当中,dmesg可以显示缓存中的内容。默认情况下,dmesg打印内容到屏幕上面,当然你可以重定向输出到一个文件。如果硬件损坏的话,在dmesg日志里是有显示的,可用以下命令来查看dmesg | grep error

  七、服务器的邮件日志

  服务器的邮件为/var/log/messages,如果要用专业的日志分析工具来分析的话,我推荐用Awstats;由于公司的开发对邮件的要求比较低,所以我帮他们配置的就是最简单的sendmail,有时看看邮件日志里的status状态来判断邮件到底有没有正确发送;在配置Nagios服务器,我也习惯用此日志来判断报警邮件到底有没有发送,如果对自己的shell水平足够自信,也可以写脚本来收集邮件服务器的返回状态等,但专业的事情,建议还是由专业的工具来做,特别是邮件负载比较大时,每天几百万条日志或上千万条日志不是开玩笑的。

  八、日志文件的专业工具

  像系统的一些服务,比如Apache、Nginx、Squid、还有mysql,都有自己的特定的日志文件,由于格式比较复杂,也推荐用专业工具,如Awstats、Cacti来分析,现在用cacti用得比较多是用它分析Nginx负载均衡器的一段时间的并发情况。

九、输出Iptables日志到一个指定的文件(logboy同学撰写)

  Iptables的man参考页中提到: 我们可以使用Iptables在Linux内核中建立, 维护和检查IP包过滤规则表。几个不同的表可能已经创建, 每一个表包含了很多内嵌的链, 也可能包含用户自定义的链。Iptables默认把日志信息输出到/var/log/messages文件。不过一些情况下你可能需要修改日志输出的位置。下面向大家介绍如何建立一个新的日志文件/var/log/iptables.log。通过修改或使用新的日志文件, 你可以创建更好的统计信息或者帮助你分析网络攻击信息。

  (1). Iptables默认的日志文件

  例如, 如果你输入下面的命令, 屏幕将显示/var/log/messages文件中的Iptables日志信息:

  # tail -f /var/log/messages

  输出:

  Oct 4 00:44:28 debian gconfd (vivek-4435):Resolved address "xml:readonly:/etc/gconf/gconf.xml.defaults"to a read-only configuration source at position 2Oct 4 01:14:19 debian kernel:IN=ra0 OUT= MAC=00:17:9a:0a:f6:44:00:08:5c:00:00:01:08:00SRC=200.142.84.36 DST=192.168.1.2LEN=60 TOS=0x00 PREC=0x00 TTL=51 ID=18374DF PROTO=TCP SPT=46040 DPT=22 WINDOW=5840 RES=0x00 SYN URGP=0

  (2).输出Iptables日志信息到一个指定文件的方法

  打开你的/etc/syslog.conf文件:

  # vi /etc/syslog.conf

  在文件末尾加入下面一行信息:

  kern.warning /var/log/iptables.log

  保存和关闭文件。

  重新启动Syslogd(如果你使用Debian/Ubuntu Linux):

  # /etc/init.d/sysklogd restart

  另外, 使用下面命令重新启动Syslogd(如果你使用Red Hat/Cent OS/Fedora Core Linux):

  # /etc/init.d/syslog restart现在确认你的Iptables使用了log-level 4参数(前面有一个log-prefix标志)。例如:

  # DROP everything and Log it

  iptables -A INPUT -j LOG –log-level 4

  iptables -A INPUT -j DROP

  举一个例子, 丢弃和记录所有来自IP地址65.55.11.2的连接信息到/var/log/iptables.log文件。

  iptables -A INPUT -s 64.55.11.2 -m limit

  limit 5/m --limit-burst 7 -j LOG

  log-prefix ‘** HACKERS **’ --log-level 4

  iptables -A INPUT -s 64.55.11.2 -j DROP

  命令解释:

  log-level 4: 记录的级别. 级别4为警告(warning)。

  log-prefix ‘*** TEXT ***’: 这里定义了在日志输出信息前加上TEXT前缀。TEXT信息最长可以是29个字符, 这样你就可以在记录文件中方便找到相关的信息。

  现在你可以通过/var/log/iptables.log文件参考Iptables的所有信息:

  # tail -f /var/log/iptables.log

  十、日志轮询

  再说下日志的轮询,Linux的日志轮询机制做得相当好,当然我们也可以通过配置/etc/logrotate.conf来修改它

使用监控宝的snmp监测

默认情况下,监控宝是通过轮询访问网站的80端口,使用http协议来监测网站的可用性,因此功能极为有限。然而监控宝还支持更强大的功能,那就是支持SNMP协议抓取数据,官网Blog有详细说明

下面说一下我的配置过程,因为是vps,而且本人也不喜欢源码安装,原因有二:1是源码安装并不比yum安装效率高多少,2是yum安装非常方便安装与维护

一、安装net-snmp服务端包,net-snmp客户端包(非必须),iptables

[root@unixhater ~]# yum install -y net-snmp
[root@unixhater ~]# yum install -y net-snmp-utils
[root@unixhater ~]# yum install -y iptables #默认vps没有安装,索性安装上去

二、配置net-snmp (使用更为安全的v3c)

yum安装的配置文件为/etc/snmp/snmpd.conf ,里面一大堆东西,一份非常详细的文档,可是我总是有借口没去细看,先移动再说,再自己创建一个snmpd.conf

[root@unixhater ~]#mv /etc/snmp/snmpd.conf /etc/snmp/snmpd.conf.bak
[root@unixhater ~]#vi /etc/snmp/snmpd.conf
输入
rouser jiankongbao auth

再创建/var/net-snmp/snmpd.conf(如果没有运行过snmpd,这个文件是不存在的,所以需要手工创建)
[root@unixhater ~]#vi /var/net-snmp/snmpd.conf
createUser jiankongbao MD5 mypassword

三、把服务启起来,设置成自动运行

[root@unixhater ~]#service snmpd start
[root@unixhater ~]#chkconfig snmpd on
顺便把iptables也重启起来
[root@unixhater ~]#service iptables start
[root@unixhater ~]#chkconfig iptables on

加上一个访问规则(安全性更高了,在网络层再进行一次验证)
[root@unixhater ~]#iptables -A INPUT -i eth0 -p udp -s 125.76.229.215 --dport 161 -j ACCEPT
[root@unixhater ~]#service iptables save #保存这条规则,下次依然生效

四、在监控宝后台加入服务器

要输入的参数是, 服务器名unixhater ip72.249.146.202 安全串unixhater 密码mypassword 加密方式MD5

确定如果状态正常则添加各监控项,如硬盘,CPU,内存,等等

附两张图:不得不说生成的flash很酷

jiankongbao1

memory

TCP状态迁移,CLOSE_WAIT & FIN_WAIT2 的问题

大家对netstat -a命令很熟悉吧,但是,你有没有注意到STATE一栏呢,基本上显示着established,time_wait,close_wait等,这些到底是什么意思呢,在这篇文章,我将会详细的阐述。
大家很明白TCP初始化连接三次握手吧:发SYN包,然后返回SYN/ACK包,再发ACK包,连接正式建立。但是这里有点出入,当请求者收到SYS /ACK包后,就开始建立连接了,而被请求者第三次握手结束后才建立连接。但是大家明白关闭连接的工作原理吗?关闭连接要四次握手:发FIN包,ACK 包,FIN包,ACK包,四次握手!!为什么呢,因为TCP连接是全双工,我关了你的连接,并不等于你关了我的连接。
客户端TCP状态迁移:
CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
服务器TCP状态迁移:
CLOSED->LISTEN->SYN收到->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED
当客户端开始连接时,服务器还处于LISTENING,客户端发一个SYN包后,他就处于SYN_SENT状态,服务器就处于SYS收到状态,然后互相确认进入连接状态ESTABLISHED.

当客户端请求关闭连接时,客户端发送一个FIN包后,客户端就进入FIN_WAIT_1状态,等待对方的确认包,服务器发送一个ACK包给客户,客户端收到ACK包后结束FIN_WAIT_1状态,进入FIN_WAIT_2状态,等待服务器发过来的关闭请求,服务器发一个FIN包后,进入 CLOSE_WAIT状态,当客户端收到服务器的FIN包,FIN_WAIT_2状态就结束,然后给服务器端的FIN包给以一个确认包,客户端这时进入 TIME_WAIT,当服务器收到确认包后,CLOSE_WAIT状态结束了,这时候服务器端真正的关闭了连接.但是客户端还在TIME_WAIT状态下,什么时候结束呢.我在这里再讲到一个新名词:2MSL等待状态,其实TIME_WAIT就是2MSL等待状态,为什么要设置这个状态,原因是有足够的时间让ACK包到达服务器端,如果服务器端没收到ACK包,超时了,然后重新发一个FIN包,直到服务器收到ACK包,TIME_WAIT状态等待时间是在TCP重新启动后不连接任何请求的两倍.
大家有没有发现一个问题:如果对方在第三次握手的时候出问题,如发FIN包的时候,不知道什么原因丢了这个包,然而这边一直处在FIN_WAIT_2状态,而且TCP/IP并没有设置这个状态的过期时间,那他一直会保留这个状态下去,越来越多的FIN_WAIT_2状态会导致系统崩溃.

上面我碰到的这个问题主要因为TCP的结束流程未走完,造成连接未释放。现设客户端主动断开连接,流程如下

如上图所示,

Client 消息 Server

close()
—— FIN ——->
FIN_WAIT1 CLOSE_WAIT
<—– ACK ——-
FIN_WAIT2
close()

CLOSED
CLOSED

由于Server的Socket在客户端已经关闭时而没有调用关闭,
造成服务器端的连接处在“挂起”状态,而客户端则处在等待应答的状态上。
此问题的典型特征是:
一端处于FIN_WAIT2 ,而另一端处于CLOSE_WAIT.

不过,根本问题还是程序写的不好,有待提高

————————————————————————-

CLOSE_WAIT,TCP的癌症,TCP的朋友。

CLOSE_WAIT状态的生成原因
首先我们知道,如果我们的服务器程序APACHE处于CLOSE_WAIT状态的话,说明套接字是被动关闭的!

因为如果是CLIENT端主动断掉当前连接的话,那么双方关闭这个TCP连接共需要四个packet:

Client —> FIN —> Server

Client <— ACK <— Server

这时候Client端处于FIN_WAIT_2状态;而Server 程序处于CLOSE_WAIT状态。

Client <— FIN ACK —> Server

Client回应了ACK,那么Server 的套接字才会真正置为CLOSED状态。

Server 程序处于CLOSE_WAIT状态,而不是LAST_ACK状态,说明还没有发FIN给Client,那么可能是在关闭连接之前还有许多数据要发送或者其他事要做,导致没有发这个FIN packet。

通常来说,一个CLOSE_WAIT会维持至少2个小时的时间。如果有个流氓特地写了个程序,给你造成一堆的CLOSE_WAIT,消耗

你的资源,那么通常是等不到释放那一刻,系统就已经解决崩溃了。

只能通过修改一下TCP/IP的参数,来缩短这个时间:修改tcp_keepalive_*系列参数有助于解决这个问题。

连接进程是通过一系列状态表示的,这些状态有:LISTEN,SYN-SENT,SYN-RECEIVED,ESTABLISHED,FIN-WAIT-
1,FIN-WAIT-2,CLOSE-WAIT,CLOSING,LAST-ACK,TIME-WAIT和
CLOSED。CLOSED表示没有连接,各个状态的意义如下: LISTEN - 侦听来自远方TCP端口的连接请求; SYN-SENT -
在发送连接请求后等待匹配的连接请求; SYN-RECEIVED - 在收到和发送一个连接请求后等待对连接请求的确认; ESTABLISHED
- 代表一个打开的连接,数据可以传送给用户; FIN-WAIT-1 - 等待远程TCP的连接中断请求,或先前的连接中断请求的确认;
FIN-WAIT-2 - 从远程TCP等待连接中断请求; CLOSE-WAIT - 等待从本地用户发来的连接中断请求; CLOSING -
等待远程TCP对连接中断的确认; LAST-ACK - 等待原来发向远程TCP的连接中断请求的确认; TIME-WAIT -
等待足够的时间以确保远程TCP接收到连接中断请求的确认; CLOSED - 没有任何连接状态;
TCP连接过程是状态的转换,促使发生状态转换的是用户调用:OPEN,SEND,RECEIVE,CLOSE,ABORT和STATUS;传送过来的数
据段,特别那些包括以下标记的数据段SYN,ACK,RST和FIN;还有超时,上面所说的都会时TCP状态发生变化。

TCP连接的状态转换图

这 个 图 n 多人都知道, 它 对 排除和定位网 络或系统 故障 时 大有帮助,但是怎 样 牢牢地 将 这张图 刻在 脑 中呢?那 么 你就一定要 对这张图 的 每 一个状 态,及转换的过程有深刻地认识,不能只停留在一知半解之中。下面对这张图的 11 种状态详细解释一下,以便加强记忆!不过在这之前,先回顾一下 TCP 建立连接的三次握手过程,以及关闭连接的四次握手过程。

1 、建立连接协议(三次握手)
( 1 )客户端发送一个带 SYN 标志的 TCP 报文到服务器。这是三次握手过程中的报文 1 。

( 2 ) 服务器端回应客户端的,这是三次握手中的第 2 个报文,这个报文同时带 ACK 标志和 SYN 标志。因此它表示对刚才客户端 SYN 报文的回应;同时又标志 SYN 给客户端,询问客户端是否准备好进行数据通讯。

( 3 ) 客户必须再次回应服务段一个 ACK 报文,这是报文段 3 。

2 、连接终止协议(四次握手)
   由于 TCP 连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个 FIN 来终止这个方向的连接。收到一个 FIN 只意味着这一方向上没有数据流动,一个 TCP 连接在收到一个 FIN 后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

 ( 1 ) TCP 客户端发送一个 FIN ,用来关闭客户到服务器的数据传送(报文段 4 )。
 ( 2 ) 服务器收到这个 FIN ,它发回一个 ACK ,确认序号为收到的序号加 1 (报文段 5 )。和 SYN 一样,一个 FIN 将占用一个序号。
 ( 3 ) 服务器关闭客户端的连接,发送一个 FIN 给客户端(报文段 6 )。
 ( 4 ) 客户段发回 ACK 报文确认,并将确认序号设置为收到序号加 1 (报文段 7 )。

CLOSED: 这个没什么好说的了,表示初始状态。

LISTEN: 这个也是非常容易理解的一个状态,表示服务器端的某个 SOCKET 处于监听状态,可以接受连接了。

SYN_RCVD: 这个状态表示接受到了 SYN 报文,在正常情况下,这个状态是服务器端的 SOCKET 在建立 TCP 连接时的三次握手会话过程中的一个中间状态,很短暂,基本上用 netstat 你是很难看到这种状态的,除非你特意写了一个客户端测试程序,故意将三次 TCP 握手过程中最后一个 ACK 报文不予发送。因此这种状态时,当收到客户端的 ACK 报文后,它会进入到 ESTABLISHED 状态。

SYN_SENT: 这个状态与 SYN_RCVD 遥想呼应,当客户端 SOCKET 执行 CONNECT 连接时,它首先发送 SYN 报文,因此也随即它会进入到了 SYN_SENT 状态,并等待服务端的发送三次握手中的第 2 个报文。 SYN_SENT 状态表示客户端已发送 SYN 报文。

ESTABLISHED :这个容易理解了,表示连接已经建立了。

FIN_WAIT_1: 这个状态要好好解释一下,其实 FIN_WAIT_1 和 FIN_WAIT_2 状态的真正含义都是表示等待对方的 FIN 报文。而这两种状态的区别是: FIN_WAIT_1 状态实际上是当 SOCKET 在 ESTABLISHED 状态时,它想主动关闭连接,向对方发送了 FIN 报文,此时该 SOCKET 即进入到 FIN_WAIT_1 状态。而当对方回应 ACK 报文后,则进入到 FIN_WAIT_2 状态,当然在实际的正常情况下,无论对方何种情况下,都应该马上回应 ACK 报文,所以 FIN_WAIT_1 状态一般是比较难见到的,而 FIN_WAIT_2 状态还有时常常可以用 netstat 看到。

FIN_WAIT_2 :上面已经详细解释了这种状态,实际上 FIN_WAIT_2 状态下的 SOCKET ,表示半连接,也即有一方要求 close 连接,但另外还告诉对方,我暂时还有点数据需要传送给你,稍后再关闭连接。

TIME_WAIT: 表示收到了对方的 FIN 报文,并发送出了 ACK 报文,就等 2MSL 后即可回到 CLOSED 可用状态了。如果 FIN_WAIT_1 状态下,收到了对方同时带 FIN 标志和 ACK 标志的报文时,可以直接进入到 TIME_WAIT 状态,而无须经过 FIN_WAIT_2 状态。

CLOSING: 这种状态比较特殊,实际情况中应该是很少见,属于一种比较罕见的例外状态。正常情况下,当你发送 FIN 报文后,按理来说是应该先收到(或同时收到)对方的 ACK 报文,再收到对方的 FIN 报文。但是 CLOSING 状态表示你发送 FIN 报文后,并没有收到对方的 ACK 报文,反而却也收到了对方的 FIN 报文。什么情况下会出现此种情况呢?其实细想一下,也不难得出结论:那就是如果双方几乎在同时 close 一个 SOCKET 的话,那么就出现了双方同时发送 FIN 报文的情况,也即会出现 CLOSING 状态,表示双方都正在关闭 SOCKET 连接。

CLOSE_WAIT: 这种状态的含义其实是表示在等待关闭。怎么理解呢?当对方 close 一个 SOCKET 后发送 FIN 报文给自己,你系统毫无疑问地会回应一个 ACK 报文给对方,此时则进入到 CLOSE_WAIT 状态。接下来呢,实际上你真正需要考虑的事情是察看你是否还有数据发送给对方,如果没有的话,那么你也就可以 close 这个 SOCKET ,发送 FIN 报文给对方,也即关闭连接。所以你在 CLOSE_WAIT 状态下,需要完成的事情是等待你去关闭连接。

LAST_ACK: 这个状态还是比较容易好理解的,它是被动关闭一方在发送 FIN 报文后,最后等待对方的 ACK 报文。当收到 ACK 报文后,也即可以进入到 CLOSED 可用状态了。

最后有 2 个问题的回答,我自己分析后的结论(不一定保证 100% 正确)

1、 为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?

这是因为服务端的 LISTEN 状态下的 SOCKET 当收到 SYN 报文的建连请求后,它可以把 ACK 和 SYN ( ACK 起应答作用,而 SYN 起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的 FIN 报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭 SOCKET, 也即你可能还需要发送一些数据给对方之后,再发送 FIN 报文给对方来表示你同意现在可以关闭连接了,所以它这里的 ACK 报文和 FIN 报文多数情况下都是分开发送的。

2、 为什么 TIME_WAIT 状态还需要等 2MSL 后才能返回到 CLOSED 状态?

这是因为:虽然双方都同意关闭连接了,而且握手的 4 个报文也都协调和发送完毕,按理可以直接回到 CLOSED 状态(就好比从 SYN_SEND 状态到 ESTABLISH 状态那样);但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的 ACK 报文会一定被对方收到,因此对方处于 LAST_ACK 状态下的 SOCKET 可能会因为超时未收到 ACK 报文,而重发 FIN 报文,所以这个 TIME_WAIT 状态的作用就是用来重发可能丢失的 ACK 报文,并保证于此。

实时查询memcached状态的两个快捷命令

查询实时的状态,类似于“top”命令。 

在命令行下执行任一命令(第二个办法需要通过php): 

1. watch "echo stats | nc 127.0.0.1 11211"

结果如下:

STAT pid 13785
STAT uptime 1377436
STAT time 1227764242
STAT version 1.2.6
STAT pointer_size 32
STAT rusage_user 9.265591
STAT rusage_system 36.541444
STAT curr_items 6
STAT total_items 1093
STAT bytes 24628
STAT curr_connections 19
STAT total_connections 79352
STAT connection_structures 117
STAT cmd_get 609575
STAT cmd_set 1093
STAT get_hits 608483
STAT get_misses 1092
STAT evictions 0
STAT bytes_read 14703639
STAT bytes_written 2297950214
STAT limit_maxbytes 52428800
STAT threads 1
END 

2. watch '/www/php/bin/php -r '"'"'$m=new Memcache;$m->connect("127.0.0.1", 11211);print_r($m->getstats());'"'" 

结果如下:

Array
(
    [pid] => 13785
    [uptime] => 1377469
    [time] => 1227764275
    [version] => 1.2.6
    [pointer_size] => 32
    [rusage_user] => 9.266591
    [rusage_system] => 36.541444
    [curr_items] => 6
    [total_items] => 1093
    [bytes] => 24628
    [curr_connections] => 16
    [total_connections] => 79372
    [connection_structures] => 117
    [cmd_get] => 609593
    [cmd_set] => 1093
    [get_hits] => 608501
    [get_misses] => 1092
    [evictions] => 0
    [bytes_read] => 14704073
    [bytes_written] => 2298032330
    [limit_maxbytes] => 52428800
    [threads] => 1

上面命令假设memcached按默认情况运行,即服务器地址为127.0.0.1,端口为11211。请按实际情况修改

Linux 下Apache+MySQL+PHP安装及配置过程

环境:本文中的Linux操作系统为CentOS 5.2,Linux 2.6+ 内核 ,Apache+MySQL+PHP 安装及基本配置过程记录下来以供参考:


一. Apache Web服务器的源代码安装,Tarball安装方式:
1. 源码包:httpd-2.2.6.tar.gz 从 www.apache.org 下载到此目录下:/usr/local/src 同时在 /usr/local 下创建一个httpd目录:mkdir httpd
2. 解压安装包:tar -zxvf httpd-2.2.6.tar.gz
3. 进入解压后的安装包:cd httpd-2.2.6
4. 配置:./configure --prefix=/usr/local/httpd --enable-cgi ( 意义支持CGI)
5. 编译:make
6. 安装:make install
7. 启动web服务:
   /usr/local/httpd/bin/apachectl start 或 service httpd start
   或者:开机后立即启动web服务
   vi /etc/rc.d/rc.local
   新加一行
   /usr/local/httpd/bin/apachectl start 或 chkconfig --level 345 httpd on
8. 配置Apache服务器
   Apache 配制文件及目录是:/usr/local/httpd/conf/httpd.conf
   Apache默认存放主页的位置应该是:/usr/local/httpd/apache/htdocs
   DocumentRoot "/usr/local/httpd/htdocs" 这个是存放网页的目录,我们应该把网页的目录指定到哪里,这样当访问网址时,就调用这个目录的文件。
   <Directory "/opt/apache/htdocs"  这句应该和DocumentRoot 的目录保持一致。
    系统自动添加了这一行,如果没有则自己加入这一行。
   LoadModule php5_module        modules/libphp5.so
   找到: DirectoryIndex index.html index.html.var
   改为: DirectoryIndex index.html index.html.var index.php
   找到: AddType application/x-tar .tgz
   添加: AddType application/x-httpd-php .php (注意空格)   
   这两项配置就是告诉Apache Server,以后收到的Url用户请求,凡是以php作为后缀,就需要调用php5_module模块mod_php5.so/ php5apache2.dll)进行处理。 mod_php 是把PHP做为APACHE一个内置模块。让apache http服务器本身能够支持PHP语言,不需要每一个请求就启动PHP解释器来解释PHP 。

unix/linux 下,so后缀文件是一个DSO文件,DSO与windows系统下的dll是等价概念,都是把一堆函数封装在一个二进制文件中。调用它们的进程把它们装入内存后,会将其映射到自己的地址空间。DSO全称为Dynamic Shared Object,即动态共享对象。DLL全称为Dynamic Link Library 即动态链接库。

注 :对存放网页的目录执行命令:chmod 755 目录名 chmod -R 755 目录名

9. 重启apache服务器:/usr/local/httpd/bin/apachectl restart

二、编译安装MySQL (源码包安装)
1. /usr/sbin/groupadd mysql            // 建立mysql组
2. /usr/sbin/useradd -g mysql mysql    // 建立mysql用户并且加入到mysql组中
3. tar zxvf mysql-5.1.38.tar.gz
4. cd mysql-5.1.38/
5.  ./configure --prefix=/usr/local/mysql/ --enable-thread-safe-client
6. make && make install
7. cp /usr/local/src/mysql/support-files/my-medium.cnf /etc/my.cnf 在 support-files目录下有4个模版文件,我们选择其中一个Mysql的配置文件,覆盖/etc/my.cnf(系统默认的配置,其中设置了性能参数和Mysql的一些路径参数);
8. cd /usr/local/mysql     //进入mysql目录
9. /usr/local/webserver/mysql/bin/mysql_install_db --basedir=/usr/local/mysql --datadir= /usr/local/mysql/data --user=mysql  //初试化表并且规定用mysql用户来访问。初始化表以后就开始给mysql和root用户设定访问权限;
10. chown -R root .       //设定root能访问/usr/local/mysql;
11. chown -R mysql data   //设定mysql用户能访问/usr/local/mysql/data ,里面存的是mysql的数据库文件.这个目录是在/etc/my.cnf中有配置,mysql_install_db时产生;
12. chown -R mysql data/.  //设定mysql用户能访问/usr/local/mysql/data/mysql下的所有文件;
13. chgrp -R mysql .    //(此处 .前面有空格哦)设定mysql组能够访问/usr/local/mysql;
14. /usr/local/mysql/bin/mysqld_safe --user=mysql &   //运行mysql;
15. /usr/local/src/mysql/bin/mysqladmin -u root password 'yourpassword' //MYSQL默认安装密码为空,为mysql设置密码,利用的是/usr/local/src/mysql/bin/下的mysqladmin文件;
16. 启动MySQL服务:
    cp /usr/local/src/mysql/support-files/mysql.server /etc/init.d/mysql
    vi /etc/init.d/mysql
    修改如下定义使其内容为:
    basedir=/usr/local/mysql
    datadir=/usr/local/mysql/data

    chmod +x mysql   //赋予shell脚本可执行权限:
    chkconfig --level 345 mysql on 
    service mysql restart
    Shutting down MySQL...                  [  OK  ]
    Starting MySQL                               [  OK  ] 

17. 连接:
   /usr/local/src/mysql/bin/mysql -u root -p
   Enter password:
   Welcome to the MySQL monitor.  Commands end with ; or \g.
   Your MySQL connection id is 5 to server version: 4.1.14-standard
   Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
   mysql>

三、PHP的源代码安装,Tarball安装方式:
1. 源码包:php-5.2.4.tar.gz,从www.php.net 下载到此目录下:/usr/local/src 同时在/usr/local下创建一个php目录:mkdir php
2. 解压安装包:tar -zxvf php-5.2.4.tar.gz
3. 进入解压后的安装包:cd php-5.2.4
4. 配置:./configure --prefix=/usr/local/php   设置PHP5 的安装路径。
    --with-apxs2=/usr/sbin/apxs    告诉PHP查找Apache 2.0的地方
    --with-libxml-dir=/usr/local/src/libxml2            告诉PHP放置libxml2库的地方。(在安装PHP检查是否先安装了libxml套件)
    --with-pdo-mysql=/usr/local/mysql           变量激活PDO(PHP数据对象抽象层)
    --with-mysql=/usr/local/mysql                  变量激活regularMySQL扩展功能。
    --with-mysqli=/usr/local/mysql/bin/mysql_config   变量激活新增加的MySQL功能。
    --with-config-file-path=/usr/local/php       是php的配置文件php.ini放置的目录

5. 编译:make
6. 安装:make install
7. 转存PHP基本配置文件并命名为php.ini:cp php.ini-dist /usr/local/php/php.ini
最后,重启Apache服务器,测试php是否一切正常工作 可以直接通过PHP程序内置的解析程序来运行一个.php文件。
[root@localhost /]# /usr/local/php/bin/php -f /var/www/html/phpinfo.php

注 :在我用的CentOS 5.2 的版本中 httpd 是系统默认安装的,编译安装php时通常要指定apxs的位置,这时编译php时会返回错误信息,会找不到路径。 这时只要将 httpd-devel 包装上便可以使用。
[root@localhost bin]# yum install httpd-devel
这时路径为: /usr/sbin/apxs

另其他的配置和目录位于:
# /etc/httpd/conf/httpd.conf
# /etc/httpd/conf.d/*.conf
# /usr/lib/httpd/modules/
# /var/www/html/
# /var/www/error/
# /var/www/icons/
# /var/www/cgi-bin/
# /var/log/httpd/
# /usr/sbin/apachectl
# /usr/sbin/httpd
# /usr/bin/htpasswd

当启动web服务器时 提示:
Starting httpd: httpd: Syntax error on line 206 of /etc/httpd/conf/httpd.conf: Cannot load /usr/lib/httpd/modules/libphp5.so into server: /usr/lib/httpd/modules/libphp5.so: cannot restore segment prot after reloc: Permission denied

原因:如果激活了SELinux ,新内核可能无法安装加载SELIinx
正确处理方法:
方法一 将/etc/selinux/config中设置的SELinux=disabled。之后reboot
编辑/etc/selinux/config,找到这段:
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - SELinux is fully disabled.
SELINUX=enforcing
把 SELINUX=enforcing 注释掉:#SELINUX=enforcing ,然后新加一行为:
SELINUX=disabled
保存,关闭。


编辑/etc/sysconfig/selinux,找到:
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - SELinux is fully disabled.
SELINUX=enforcing
如果SELINUX已经是 SELINUX=disabled,那么就不用改了,否则就把SELINUX=enforcing 注释掉,新加一行:
SELINUX=disabled
保存,退出。

如果碰到其他类似提示:
cannot restore segment prot after reloc: Permission denied
哪应该是SELinux的问题,可以考虑把它关闭。
-------------------------------------------------------------------------------------
如果将 SELinux 关闭后还是不行.执行下
chcon -t texrel_shlib_t
如: chcon -t texrel_shlib_t /usr/lib/httpd/modules/libphp5.so

方法二如果不想禁用SELinux,可安装selinux-policy-targeted-1.25-4.noarch.rpm的高版本。