shell编程中文本处理中用到的几张图

Posted: 2009年11月10日星期二
在网上找到几个shell文本处理的几个常用命令的使用方法,觉得比较好,就贴在博客中,权当备忘,由于在google图片搜索出来的,不知道原载作者是谁,如知道,告诉我一声,加上原作者地址,下面的图直接看比较小,可以直接点击图,看大图,或者下载下来作为文件保存
正则表达式:

vi使用

sed使用

awk使用

分析the address already in use产生的原因

Posted: 2009年11月5日星期四
最近在维护一个别人写的程序时遇到一个它的程序启动不了的情况,具体情况如下,服务器端按照它的方式不能正常关闭,就用kill命令把它的程序结束掉了,再启动程序时报如下的错误:the address already in use,问了公司的同事,同事也告诉不可能啊,要不就是由什么链入了系统库了,当时我也不懂也没有在意,没有去查,这几天我刚好在学习linux网络编程,也碰到了这个问题,通过查找资料,了解到,并不是什么链入了系统库了,而是下面将要说明的情况:
一般情况认为,server socket已经关闭,理应释放了ip address及port资源,但是事实并不一定是这样的,因为大部分socket连接是基于tcp协议多次握手连接的基础上,以保证数据传输的完整性,我们都知道tcp协议是一种可靠的协议,它有3次握手,四次挥手过程,下面是4次挥手过程
(1)当服务器端处于ESTABLISHED状态时, 服务器欲主动关闭连线,发送FIN至客户端,进入到FIN-WAIT-1状态,等待客户端回应ACK,表示等待确认客户端得知服务器端要关闭连线
(2)当客户端收到服务器端的FIN时,立即回应ACK给服务器端,进入到CLOSE-WAIT状态,表示须等到应用程序没有任何资料要传送给服务器端, 客户端才决定关闭连线
(3)服务器端收到客户端回应的ACK,表示确认客户端得知服务器要关闭连线,此刻等待客户端发送FIN
(4)客户端决定关闭连线,发送FIN至服务器端,进入到LAST-ACK状态,等待服务器端回应ACK,表示等待确认服务器端得知客户端要关闭连线
(5)服务器端收到客户端的FIN后,随即回应ACK,进入TIME_WAIT状态,表示服务器端得知客户端要关闭连线,且等待2MSL时间,以防客户端再次发送FIN
(6)客户端收到服务器端回应的ACK后,进入CLOSED状态,表示客户端已确认服务器端已得知它要关闭连线,才进行关闭连线
(7)服务器端等待2MSL时间,才进入CLOSED状态,关闭连线,并自连线表中移除
在上述的第(5),(7)点,此刻TIME-WAIT的用意在于,虽服务器已确认客户端要关闭连线,且回应了ACK给客户端,但不保证客户端会收到ACK ,一旦ACK遗漏,
客户端会再次发送FIN给服务器端,再次进行确认,所以服务器端须进入TIME-WAIT状态,等待2MSL时间,预防客户端会再次发送FIN,进行连线关闭的确认。

从上面的4次挥手过程得知,我们直接结束游戏的服务器端,它并没有马上释放它的ip及port资源就在于服务器端进入了time_wait状态,有可能客户端没有
收到ack资源,导致不停的发送fin请求,导致直接结束服务器端,导致重启起不来,下面是我用C写的一个程序怎么重现上面所出现的实例,以及怎么避免上面所
出现的情况
1.客户端

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main()
{
struct sockaddr_in server;
int sock;
char buf[32];
int n;

sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket");
exit(1);
}

server.sin_family = AF_INET;
server.sin_port = htons(1234);
server.sin_addr.s_addr = inet_addr("127.0.0.1");

if(connect(sock, (struct sockaddr *)&server, sizeof(server)) != 0){
perror("connetc");
exit(1);
}

n = read(sock, buf, sizeof(buf));
if(n < 0) {
perror("read");
return 1;
}

printf("%d, %s\n", n, buf);

close(sock);

return 0;
}

帮上面的代码保存为一个client.c文件,通过下面命令进行编译
gcc -o client client.c
2.重现出现情况的服务器端

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main(int argc, char *argv[])
{
int sock0;
struct sockaddr_in addr;
struct sockaddr_in client;
int len;
int sock;

sock0 = socket(AF_INET, SOCK_STREAM, 0);
if (sock0 < 0) {
perror("socket");
return 1;
}

addr.sin_family = AF_INET;
addr.sin_port = htons(1234);
addr.sin_addr.s_addr = INADDR_ANY;
if(bind(sock0, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
perror("bind");
return 1;
}

if (listen(sock0, 5) !=0) {
perror("listen:");
return 1;
}
while (1) {
len = sizeof(client);
sock = accept(sock0, (struct sockaddr *)&client, &len);
if (sock < 0) {
perror("accept:");
break;
}

printf("accepted connection from %s\n",
inet_ntoa(client.sin_addr));
if(send(sock, "Hello", 5, 0) < 1) {
perror("write:");
return 1;
}

close(sock);
}
close(sock0);

return 0;
}

把上面的程序保存为一个server1.c文件,执行下面的命令进行编译
gcc -o server1 server1.c
3.避免上述情况发生的服务器端

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main(int argc, char *argv[])
{
int sock0;
struct sockaddr_in addr;
struct sockaddr_in client;
int len;
int sock;
int yes = 1;

sock0 = socket(AF_INET, SOCK_STREAM, 0);
if (sock0 < 0) {
perror("socket");
return 1;
}

addr.sin_family = AF_INET;
addr.sin_port = htons(1234);
addr.sin_addr.s_addr = INADDR_ANY;
setsockopt(sock0,
SOL_SOCKET, SO_REUSEADDR, (const char *)&yes, sizeof(yes));
if(bind(sock0, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
perror("bind");
return 1;
}

if (listen(sock0, 5) !=0) {
perror("listen:");
return 1;
}
while (1) {
len = sizeof(client);
sock = accept(sock0, (struct sockaddr *)&client, &len);
if (sock < 0) {
perror("accept:");
break;
}

printf("accepted connection from %s\n",
inet_ntoa(client.sin_addr));
if(send(sock, "Hello", 5, 0) < 1) {
perror("write:");
return 1;
}

close(sock);
}
close(sock0);

return 0;
}

把上面的程序保存为一个server2.c文件,执行下面的命令进行编译
gcc -o server2 server2.c

启动服务器端
./server1
在另外一个终端中启动客户端
./clinet
得到如下的内容
5, Hello
在服务器的终端通过ctrl + c结束刚刚起来的服务器端,在一分钟内再启动服务器端,你就可以发现出现下面的错误信息
bind: Address already in use
过1分钟后(Linux系统默认time_wait的时间为60秒)就可以发现可以起来了。
为规避上面的情况,再启动server2,再重复上面的步骤,发现已经没有这种情况了。

上面只是一个具体的实例,并不保证数据的完整性,具体到它们的程序中,具体进行分析。

c开发的中的man使用技巧

Posted: 2009年11月2日星期一
在c语言开发过程中,经常需要进行查找函数的说明,在linux下有man命令,比较容易获取c的标准库函数的说明,在ubuntu下若要查看C语言的函数说明,需要安装manpages-dev包,具体安装方法如下
sudo apt-get install manpages-dev
若对于英文不好的同学,可以再安装一个中文的语言包:manpages-zh,这个语言包并不一定包含所有的函数说明,只是其中的一部分,安装方法如下:
sudo apt-get install manpages-zh
通常对于一些不常用的函数可以直接通过man 函数名,可以得到所需的函数说明,对于函数名跟系统命令相同时,就不会得到你想要的函数说明,具体怎么区分怎么才能得到了我想要的函数说明呢?
通常做法如下所示
1. man -k 函数名 |grep ^函数名
2.通过查到的结果,一般会在后面加一个括号带一个数字,再通过man 刚刚得到的数字 函数名 得到我们想要的函数帮助文档
譬如查看c语言read函数说明
man read |grep ^read
得到的结果如下:
zhou@lingjie:~$ man -k read |grep ^read
read (2) - read from a file descriptor
readahead (2) - perform file readahead into page cache
readahead-list (8) - manual page for readahead-list: 0.20050517.0220
readahead-watch (8) - manual page for readahead-watch: 0.20050517.0220
readdir (2) - read directory entry
readdir (3) - read a directory
readdir_r (3) - read a directory
readelf (1) - Displays information about ELF files.
readline (3readline) - get a line from a user with editing
readlink (1) - display value of a symbolic link
readlink (2) - read value of a symbolic link
readlinkat (2) - read value of a symbolic link relative to a directory ...
readom (1) - read or write data Compact Discs
readprofile (1) - a tool to read kernel profiling information
readv (2) - read or write data into multiple buffers

那么我查看C的函数说明就是如下的命令
man 2 read
就可以得到我们想要的函数说明了。

利用iptables端口映射实现跨多机房内网访问

Posted: 2009年10月9日星期五
公司在外地的移动机房,由于公司采用的电信通网络,公司的机房跟外地的移动机房连接及其不稳定,丢包以及连接中断是家常便饭,由于需要程序需要数据交换,这种网络状况基本上不可能,公司放了一个机器放在一个双线机房用iptables端口转发实现数据交换,进行服务器维护,但是最近公司有个需求需要直接用公司的机器访问,外地移动机房内的内网DB,这台DB没有外网地址就得进行多次转发。由于放在移动机房的只有一个linux机器具有外网IP,而这台机器上也有mysql,占用了3306端口,这就需要把移动机房中的转发机器的其它端口转发到内网DB的3306上,同时为安全起见只允许机房的ip地址访问转发的端口,具体需求拓扑如下所示:

下面是实现过程
在中转机房的机器上执行

iptables -A INPUT -p tcp -s 219.x.x.x -d 220.x.x.x --dport 5300 -j ACCEPT
iptables -A PREROUTING -s 219.x.x.x -d 220.x.x.x -p tcp --dport 5300 -j DNAT --to-destination 221.x.x.x
iptables -A POSTROUTING -p tcp --dport 5300 -j SNAT --to-source 220.x.x.x


在移动机房的机器上执行下面的语句

iptables -A PREROUTING -d 221.x.x.x -p tcp --dport 5300 -j DNAT --to-destination 192.168.0.6:3306
iptables -A POSTROUTING -p tcp --dport 3306 -j SNAT --to-source 192.168.0.5


通过执行上面的语句,公司的机器可以通过直接访问中转机房的220.x.x.x的5300直接访问到移动机房内网的机器

搭建linux ris服务器批量在dell服务器上安装windows 2003

Posted: 2009年10月7日星期三
以前写了一个《使用kickstart批量安装Linux》对于sa来说节省了很大部分时间,现在又一批机器需要安装windows 2003由于有一台linux安装服务器,为节约服务器着想,决定在这台服务器上面安装一个linux ris服务器,其实在网上有一堆文章介绍搭建一个linux ris服务器批量安装windows,对于一般的pc来说照着他们的做也许没有问题很简单就能搭建出来,但是对于服务器而言就比较的麻烦了,首先我们的这批服务器是dell的服务器,安装windows 2003需要dell的安装引导盘,引导盘的作用就是用来加载驱动程序,而网上的文章基本没有介绍有关如何加载驱动?加载驱动有什么技巧以及注意的地方。我也问了我的一些sa的朋友,几个朋友都告诉我他们是一台台手动去安装,问他们原因,他们说配置驱动很麻烦。事实证明他们说的确实是这样,如果你安装的机器是10台以内,我建议你还是别照着我的做了,一台台手动安装比较的快。

本文的中演示的是安装windows 2003 i386版本。并不适用其它版本,对于window 2003之前的版本可以参照linux ris安装文档进行相应的更改,对于vista之后的windows更不适用,vista之后的版本都改成了wds进行批量部署。
实施方案的拓扑图如下所示
          ┌────────┐
          │   Boot Server   │
          │(DHCP TFTP samba)│
          └───┬────┘
                  │
          ┌───┴───┐
          │     Switch    │
          └───┬───┘
                   │
      ┌─────┴──────┐
      │                         │
┌──┴───┐        ┌───┴───┐
│Client(PxE)  │        │Client(PxE)    │
└──────┘        └───────┘
实施步骤
1.配置启动服务器
2.配置安装方案
3.启动待安装服务器,进行系统安装

启动服务器就一个普通的linux pc能够连接上网络,下面说说我要安装的服务器配置
dell 1950:
CPU: E5410*2(2330MHZ)
mem: 2G*4
raid控制卡: PERC 6/i
网卡: NetXtreme II Broadcom
配置启动服务器
启动服务器的目的是帮助待安装机器上启动Red Hat Linux安装程序。启动服务器上需要搭建一个DHCP 服务器和一个TFTP 服务器,一个nfs用来传输网络镜像文件。前者是为了给待安装机器分配IP地址,后者则是提供了一个让待安装机器下载启动镜像的途径。
首先配置DHCP服务
1) 安装DHCP服务器包(RPM包名:dhcpd)。
2)配置服务器IP地址
3) 编辑DHCP服务器配置文件 /etc/dhcp.conf。

ddns-update-style interim;
ignore client-updates;
allow booting;
allow bootp;

subnet 192.168.0.0 netmask 255.255.255.0 {
option routers 192.168.0.1;
option subnet-mask 255.255.255.0;
option domain-name-servers 192.168.0.1;
range dynamic-bootp 192.168.0.128 192.168.0.254;
default-lease-time 21600;
max-lease-time 43200;
next-server 192.168.0.4;
filename "pxelinux.0";
}
}

注:
一般参数基本一样,下面我说以下几个重要,平时作为dhcp服务器,不常用的几个参数
allow booting;allow bootp;这两句话的意思是能作为pxe的启动服务器,给他们分配ip地址,next-server作用是指定tftp服务器的地址,filename,找到tftp服务器后找下载那个启动文件,搭建tftp服务器
4) 给启动服务器配置一个IP,这个IP必须在DHCP服务器定义的子网内。上例中配置的启动服务器的ip地址为192.168.0.4。
5) 启动DHCP服务。
service dhcpd start
配置TFTP服务器(如没有安装xinetd软件包,先安装这个软件包)

1) 安装TFTP服务器包(RPM包名:tftpd)。
2) 编辑TFTP 服务器的配置文件 /etc/xinetd.d/tftp。配置文件如下:
service tftp
{
socket_type = dgram
protocol = udp
wait = yes
user = dpan
server = /usr/sbin/in.tftpd
server_args = -s /tftpboot -m /tftpboot/rules -vv
disable = no
}

注:
这里选定了/tftpboot为TFTP 服务器的根目录位置。
-m /tftpboot/rules 这里指定一个规则文件,这个文件的作用下文中指出,
-vv的作用是把tftp的log详细输出,log文件为/var/log/message,作用为便于调试。
3)建立/tftpboot/rules文件,文件内容如下:
ri ^[a-z]: # Remove “drive letters”
rg \\ / # Convert backslashes to slashes
rg \# @ # Convert hash marks to @ signs
rg /../ /..no../ # Convert /../ to /..no../
rg A a
rg B b
rg C c
rg D d
rg E e
rg F f
rg G g
rg H h
rg I i
rg J j
rg K k
rg L l
rg M m
rg N n
rg O o
rg P p
rg Q q
rg R r
rg S s
rg T t
rg U u
rg V v
rg W w
rg X x
rg Y y
rg Z z
r ^/(.*) \1

这个文件的作用是把所有的查找大写的内容转为小写,由于windows不区分大小写,故统一改成小写。
4)启动TFTP服务
service xinetd start

由于windows的ris安装是通过windows共享文件的方式进行文件传输后,在linux下可以通过samba实现与windows进行文件共享,进而实现了ris安装
配置samba服务器
1) 安装samba服务器包(RPM包名:samba)。
2)配置服务器IP地址
3) 编辑samba服务器配置文件 /etc/samba/smb.conf

[global]
null passwords = true
workgroup = MYGROUP
server string = Samba Server
security = share
load printers = no
disable spoolss = yes
debug level = 2
log file = /var/log/samba/%m.log
max log size = 0
dns proxy = no
[wininstall]
path = /tftpboot
browsable = true
read only = No
writable = yes
guest ok = Yes

配置启动信息
在windows下可以通过expand解压缩光盘中的文件,由于linux下面没有这个工具,但是有人写了一个叫cabextract的工具可以解压windows光盘中的压缩文件,具体可以在http://www.cabextract.org.uk/下载到你所需的版本,
由于我采用的centos 5.2 32位版,为简单着想我安装的是rpm包,具体操作如下
1)下载
wget http://www.cabextract.org.uk/cabextract-1.2-1.i386.rpm
2)安装
rpm -ivh cabextract-1.2-1.i386.rpm
上传windows 2003的iso镜像或者光盘中的内容到服务器的一个目录,这里我采用上传一个windows 2003的iso镜像到dpan目录下。并把光盘挂载到/tftpboot的win2k3目录下
1)建立win2k3目录
mkdir /tftpboot/win2k3
2)挂载iso文件到/mnt目录下
mount -o loop /dpan/windows2003.iso /mnt
3)为方便我们往后面往里面添加驱动或者添加启动后的脚本文件,我们把光盘中的内容复制到/tftpboot下的win2k3目录下
cp -r /mnt/* /tftpboot/win2k3
4)进入/tftpboot目录,配置windows ris启动文件信息(每行为一个命令)

cd /tftpboot
cabextract win2k3/i386/startrom.n1_
sed -i -e 's/NTLDR/W2K3L/gi' startrom.n12
mv startrom.n12 /tftpdpan/w2k3.0
cabextract win2k3/i386/setupldr.ex_
sed -i -e 's/winnt\.sif/wi2k3\.sif/gi' setupldr.exe
sed -i -e 's/ntdetect\.com/ntdetect\.2k3/gi' setupldr.exe
mv setupldr.exe /tftpdpan/w2k3l
cp win2k3/i386/ntdetect.com /tftpdpan/ntdetect.2k3

5)复制pxe的启动镜像到/tftpboot目录
启动镜像pxelinux.0可以在syslinux安装包里获得。安装好syslinux安装包后,将pxelinux.0复制到/tftpboot
cp /usr/lib/syslinux/pxelinux.0 /tftpboot
6)启动镜像pxelinux.0文件在执行过程中,会读取同目录下pxelinux.cfg文件夹下的配置文件以确定它应该加载什么启动文件。
建立启动配置文件存放文件夹
mkdir /tftpboot/pxelinux.cfg
建立启动配置文件default
default win2k3
label win2k3
kernel w2k3.0

建立应答文件/tftpboot/wi2k3.sif,文件内容如下所示

[data]
AutoPartition = "0"
floppyless = "1"
msdosinitiated = "1"
UnattendedInstall = "Yes"
OriSrc = "\\192.168.0.4\wininstall\win2k3\i386"
OriTyp = "4"
LocalSourceOnCD = "1"
DisableAdminAccountOnDomainJoin = "1"

[SetupData]
OsLoadOptions = "/fastdetect"
SetupSourceDevice = "\Device\LanmanRedirector\192.168.0.4\wininstall\win2k3"

[Unattended]
UnattendMode = "FullUnattended"
FileSystem = "LeaveAlone"
NtUpgrade = "No"
OverwriteOemFilesOnUpgrade = "No"
DriverSigningPolicy = "Ignore"
UpdateInstalledDrivers = "Yes"
ConfirmHardware = "No"
ExtendOEMPartition = "0"
TargetPath = "\WINDOWS"
UnattendSwitch = "Yes"
WaitForReboot = "No"
CrashDumpSetting = "0"
OemSkipEula = "Yes"
OEMSkipWelcome = "1"
InstallFilesPath = "\\192.168.0.4\wininstall\win2k3\i386"
LegacyNIC = "1"

[UserData]
ProductKey = "11111-11111-11111-11111-11111"
FullName = "abc"
OrgName = "xyz"
ComputerName = *

[GuiUnattended]
AdminPassword = 123456
EncryptedAdminPassword = "No"
OEMSkipRegional = "1"
TimeZone = "220"
OemSkipWelcome = "1"

[Identification]
JoinWorkgroup = WORKGROUP

[RemoteInstall]
Repartition = "No"
UseWholeDisk = "No"

[Networking]
InstallDefaultComponents = "Yes"


完成后目录结构如下所示
|-- w2k3l
|-- ntdetect.2k3
|-- pxelinux.0
|-- pxelinux.cfg
|  `-- default
|-- win2k3
|  |-- i386
|  |-- autorun.inf
|  |-- bootfont.bin
|  |-- docs
|  |-- i386
|  |-- $oem$
|  |-- printers
|  |-- readme.htm
|  |-- setup.exe
|  |-- support
|  |-- win51
|  |-- win51ia
|  `-- win51ia.sp1
|-- rules
|-- w2k3.0
`-- wi2k3.sif

经过以上的操作基本可以把dell 1950起来到蓝色的安装界面,要是有不需要任何驱动的机器,基本可以完成安装。由于是服务器,有些特定的硬件需要提前加载好驱动,安装起来比较的麻烦,下面告诉你怎样加载驱动,
首先是NetXtreme II Broadcom网卡驱动,既然是网络安装,那么首先需要加载的一定是网卡驱动,由于Broadcom公司提供了ris的驱动(不是系统下的驱动),具体这可在Broadcom驱动下载页中下载到相应的驱动,我需要的驱动下载地址为:http://www.broadcom.com/docs/driver_download/NXII/win_2k3_RIS-5.0.0.zip
下载解压
wget http://www.broadcom.com/docs/driver_download/NXII/win_2k3_RIS-5.0.0.zip
mkdir -p /tftpdpan/nicdriver
unzip win_2k3_RIS-5.0.0.zip -d /tftpdpan/nicdriver


由于要驱动网卡,需要一个binlserver, BINL读取所有新的与网络接口卡相关的 .inf 文件,并在映像中创建 .pnf 文件。
配置binl server,用来加载网卡驱动
1)服务器下载
wget http://oss.netfarm.it/guides/ris-linux-0.4.tar.gz
2)解压
tar xf ris-linux-0.4.tar.gz
3)执行
cd ris-linux-0.4
./infparser.py /tftpdpan/nicdrivers/Server/W2K3_W2K8/RIS/
./binlsrv.py -d
cp /tftpdpan/nicdrivers/Server/W2K3_W2K8/RIS/b06nd51x.sys /tftpdpan/win2k3/i386
启动被安装服务器,现在就可以加载到网卡驱动了

加载完网卡驱动还有找不到磁盘,需要加载raid磁盘驱动:
通过光盘安装过windows的用户知道在开始时蓝色屏幕上有一个按F6的提示,这个提示是用来通过软盘加载磁盘驱动,这类驱动是windows系统中的驱动,可以下载好windows驱动,解压好驱动放在一个指定的目录,再通过应答文件,一般可以加载上这类驱动,这类驱动加载完毕后不必在系统中再安装这类驱动。加载这类驱动有注意点:文件要有正确的oem数字签名(一般提供驱动的厂商都带数字签名),乱改动这类文件,同时不在配置文件中写明去掉数字签名认证,是不能加载的。
下面通过一个实例说明怎么加载dell的PERC 6/i raid卡的驱动,完成ris的驱动加载
1)下载dell的perc 6/i驱动
wget ftp://ftp.us.dell.com/SAS-RAID/DELL_MULTI-DEVICE_A07_R211422.exe
2)建立加载驱动的目录
mkdir -p /tftpboot/win2k3/\$oem\$/textmode
3)解压驱动文件
unzip DELL_MULTI-DEVICE_A07_R211422.exe -d /tftpboot/win2k3/\$oem\$/textmode
4)配置自动应答文件wi2k3.sif,在文件的末尾加上如下内容
[MassStorageDrivers]
"DELL PERC5 and PERC6/CERC6 RAID Controller Driver (Server 2003 32 bit)"=OEM

[OEMBootFiles]
nodev.inf
oemsetup.inf
percsas.cat
percsas.sys
txtsetup.oem
同时在wi2k3.sif中的[Unattended]段添加如下字段
OemPreInstall = "Yes"
注意了[MassStorageDrivers]段中的字符是编辑txtsetup.oem文件查看PERC_32中后面的字符段得到的结果,[OEMBootFiles]段中下面的配置就是刚刚解压后的所有文件,这样就完成了对raid卡驱动的加载
完成后目录结构如下所示
|-- w2k3l
|-- ntdetect.2k3
|-- pxelinux.0
|-- pxelinux.cfg
|  `-- default
|-- win2k3
|  |-- i386
|  |-- autorun.inf
|  |-- bootfont.bin
|  |-- docs
|  |-- i386
|  |-- $oem$
|    |-- textmode
|    |-- nodev.inf
|    |-- oemsetup.inf
|    |-- percsas.cat
|    |-- percsas.sys
|    `-- txtsetup.oem
|  |-- printers
|  |-- readme.htm
|  |-- setup.exe
|  |-- support
|  |-- win51
|  |-- win51ia
|  `-- win51ia.sp1
|-- rules
|-- w2k3.0
`-- wi2k3.sif
以上就可以完成对raid卡为PERC 6/i 网卡为:NetXtreme II Broadcom的机器批量安装。但安装完成后还需手动打补丁包、安装简单的软件如rar,以及执行一写安全脚本命令等。这样如果一台台去操作,工作量大。
学习了以下某些盗版光盘的制作方法,完成该系统的优化操作(由于这部分已经快是一个成型的windows系统,故建立的这部分文件千万注意了为windows文件格式,最好用windows下的文本编辑器进行编辑操作,用vi编辑的话会有两个后果,一是文件保存是两者的换行符不一致,而如果写了中文的话,两者保存了文件的编码方式不一致,导致执行不了这部分的命令)。
CMDLINES.TXT 这个文件位于$OEM$目录下,安装是当进行到注册组件(也就安装到剩余13分钟)时这个特殊的脚本被安装程序调用
下面是一个典型的
[COMMANDS]
"install.cmd"
"REGEDIT32.EXE /S youhua.reg"
"update.cmd"
这个文件的内容总是以" [COMMANDS]"为起头;总是使用引号(")来标记下面需要执行的每条命令CMDLINES.TXT是一个比较受限制的命令行接口,这就意味着很多传统DOS命令将不能由它进行调用,但是外部命令(比如REGEDIT32.EXE)还是可以调用的.
注意路径问题,这里的youhua.reg、update.cmd和install.cmd的路径为cmdlines.txt的同级目录.在$oem$目录下建立一个youhua.reg和install.cmd文件,youhua.reg文件为注册表优化的一部分参数,install.cmd为打补丁和安装网卡驱动的一些操作,install.cmd为添加网卡驱动的操作,下载网卡驱动,放置在$oem$目录下的DrvInst下,下面为几个文件的具体实例
install.cmd

@ echo off
@ color 0a

@ echo 安装网卡驱动中。。。。。 2>>%HOMEDRIVE%/errlog.txt

@ cd DrvInst 2>>%HOMEDRIVE%/errlog.txt

BDrv5706.msi /qn 2>>%HOMEDRIVE%/errlog.txt

if %errorlevel% EQU 0 (
@ echo 网卡驱动安装成功 2>>%HOMEDRIVE%/errlog.txt
@ cd ..
@ goto win2k3sp2 2>>%HOMEDRIVE%/errlog.txt
) else (
@ echo 网卡驱动安装失败 继续安装WINDOWS_2003_SP2 补丁 2>>%HOMEDRIVE%/errlog.txt
@ cd ..
@ goto win2k3sp2 2>>%HOMEDRIVE%/errlog.txt
)

:win2k3sp2

@echo 安装WINDOWS_2003_SP2补丁中。。。。 2>>%HOMEDRIVE%/errlog.txt

sp2.exe /passive /norestart 2>>%HOMEDRIVE%/errlog.txt

if %errorlevel% EQU 0 (
@ echo WINDOWS_2003_SP2补丁安装成功 2>>%HOMEDRIVE%/errlog.txt
) else (
@ echo WINDOWS_2003_SP2补丁安装失败 详细见errlog日志 2>>%HOMEDRIVE%/errlog.txt
)

youhua.reg

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\netBT\Parameters]
"SMBDeviceEnabled"=dword:0
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa]
"RestrictAnonymous"=dword:1
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters]
"SynAttackProtect"=dword:1
[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System]
"DisableCAD"=dword:1
[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System]
"DontDisplayLastUserName"=dword:1
[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System]
"DontDisplayLockedUserId"=dword:3
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon]
"DontDisplayLastUserName"=dword:1
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\Wds\rdpwd\Tds\tcp]
"PortNumber"=dword:12345
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp
"PortNumber"=dword:12345

完成后目录结构如下所示
|-- w2k3l
|-- ntdetect.2k3
|-- pxelinux.0
|-- pxelinux.cfg
|  `-- default
|-- win2k3
|  |-- i386
|  |-- autorun.inf
|  |-- bootfont.bin
|  |-- docs
|  |-- i386
|  |-- $oem$
|    |-- install.cmd
|    |-- youhua.reg
|    |-- cmdlines.txt
|    |-- DrvInst
|      |-- BDrv5706.msi
|      |-- 0x0409.ini
|      |-- DrvFiles.cab
|      |-- instmsia.exe
|      |-- instmsiw.exe
|      |-- setup.exe
|      |-- Setup.ini
|  |-- textmode
|      |-- nodev.inf
|      |-- oemsetup.inf
|      |-- percsas.cat
|      |-- percsas.sys
|      `-- txtsetup.oem
|  |-- printers
|  |-- readme.htm
|  |-- setup.exe
|  |-- support
|  |-- win51
|  |-- win51ia
|  `-- win51ia.sp1
|-- rules
|-- w2k3.0
`-- wi2k3.sif
上一步部分不是说有一部分命令不能执行吗,还有办法在应答文件中添加即自动应答的GuiRunOnce段中添加执行脚本,具体就是在第一次登录系统时执行脚本,脚本放置在$oem$下的$1目录里,这个目录里的内容会放在系统安装盘下根目录下,由于windows自动安装中不能自动分区通过GuiRunOnce,使用系统自带的diskpart命令实现自动分区,使用系统自带的cacls等命令实现分区及系统安全
在wi2k3.sif文件中添加如下内容,实现分区和系统安全及其其它命令
[GuiRunOnce]
%systemdrive%\diskpart.cmd
%systemdrive%\setup.cmd
下面是实现后的目录结构
|-- w2k3l
|-- ntdetect.2k3
|-- pxelinux.0
|-- pxelinux.cfg
|  `-- default
|-- win2k3
|  |-- i386
|  |-- autorun.inf
|  |-- bootfont.bin
|  |-- docs
|  |-- i386
|  |-- $oem$
|    |-- install.cmd
|    |-- youhua.reg
|    |-- cmdlines.txt
|    |-- DrvInst
|      |-- BDrv5706.msi
|      |-- 0x0409.ini
|      |-- DrvFiles.cab
|      |-- instmsia.exe
|      |-- instmsiw.exe
|      |-- setup.exe
|      |-- Setup.ini
|  |-- textmode
|      |-- nodev.inf
|      |-- oemsetup.inf
|      |-- percsas.cat
|      |-- percsas.sys
|      `-- txtsetup.oem
|  |-- $1
|      |-- diskpart.cmd
|      |-- diskpart.txt
|      |-- setup.cmd
|  |-- printers
|  |-- readme.htm
|  |-- setup.exe
|  |-- support
|  |-- win51
|  |-- win51ia
|  `-- win51ia.sp1
|-- rules
|-- w2k3.0
`-- wi2k3.sif

下面是几个文件的具体内容
diskpart.cmd

@ echo off
for %%i in (d,e,f,g,h) do mountvol %%i: /D > nul
%windir%\system32\diskpart /s %systemdrive%\diskpart.txt
echo y | format D: /FS:NTFS /V:GAME /Q /X /A:4096
if %errorlevel% EQU 0 (
@ echo format D: success....
) else (
@ echo format D: fail....
)
echo y | format E: /FS:NTFS /V:OTHER /Q /X /A:4096
if %errorlevel% EQU 0 (
@ echo format E: success....
) else (
@ echo format E: fail....
)


diskpart.txt

select disk 0
create partition extended
create partition logical size=30800
assign letter=D
create partition logical
assign letter=E


setup.cmd

@ echo off

@del /f /q %WINDIR%\Web\printers
@del /f /q %WINDIR%\Web\printers\images
@del /f /q %WINDIR%\Web\printers\PrtCabs
@del /f /q %WINDIR%\Help\iisHelp

wmic useraccount where name='administrator' call Rename test
net user dpan 123456 /add /passwordchg:yes /expires:never
net localgroup "Remote Desktop Users" dpan /add
net user epan 654321 /add /passwordchg:yes /expires:never
net localgroup "Remote Desktop Users" epan /add
net localgroup Users dpan /del
Net user epan 654321

Cacls D:\ /e /c /d epan
Cacls C:\ /t /e /c /g epan:f
Cacls E:\ /t /e /c /g epan:f
Cacls C:\ /e /c /d dpan
Cacls D:\ /t /e /c /g dpan:f
Cacls E:\ /e /c /d dpan
Cacls C:\ /e /c /d everyone
Cacls D:\ /e /c /d everyone
Cacls E:\ /e /c /d everyone
Cacls C:\ /e /c /r everyone
Cacls D:\ /e /c /r everyone
Cacls E:\ /e /c /r everyone

del %systemdrive%\diskpart.cmd
del %systemdrive%\diskpart.txt
del %systemdrive%\%0

eaccelerator真的能加速你的php吗?

Posted: 2009年8月3日星期一
经常看到很多介绍安装php的文章中,提到安装一个eaccelerator加速php程序,我按照他们的需求安装了,确实能用了,可是经过我的压力测试,发现他确实没有实现那些文章所谓的加速功能,是我配置错了,还是具体哪有问题,下面介绍一下我的配置情况,对于php的安装,搜索引擎一搜索网上一大堆,我就不累赘了,现在说说我的安装和eaccelerator的过程
php安装软件及版本
nginx/0.8.7
php-5.2.8
eaccelerator-0.9.5.3
eaccelerator安装

/usr/local/bin/phpize
./configure --enable-eaccelerator=shared --with-php-config=/usr/local/php/bin/php-config
make
sudo make install

eaccelerator配置
分成两块,一块是采用eaccelerator加速的就在php.ini文件中加入如下内容

[eaccelerator]
extension_dir = "/usr/local/lib/php/extensions"
extension="/no-debug-non-zts-20060613/eaccelerator.so"
eaccelerator.shm_size="16"
eaccelerator.cache_dir="/tmp/eaccelerator_cache"
eaccelerator.enable="1"
eaccelerator.optimizer="1"
eaccelerator.check_mtime="1"
eaccelerator.debug="0"
eaccelerator.filter=""
eaccelerator.shm_max="0"
eaccelerator.shm_ttl="0"
eaccelerator.shm_prune_period="0"
eaccelerator.shm_only="0"
eaccelerator.compress="1"
eaccelerator.compress_level="9"

添加cache目录

mkdir /tmp/eaccelerator_cache

另一块就是初始化安装不配置任何参数进行测试
eaccelerator加速测试
ab -c 200 -n 10000 http://www.test.com/phpinfo.php
测试结果

Server Software: nginx/0.8.7
Server Hostname: www.test.com
Server Port: 80

Document Path: /test.php
Document Length: 25 bytes

Concurrency Level: 200
Time taken for tests: 1.523543 seconds
Complete requests: 10000
Failed requests: 0
Write errors: 0
Non-2xx responses: 10000
Total transferred: 2160000 bytes
HTML transferred: 250000 bytes
Requests per second: 6563.65 [#/sec] (mean)
Time per request: 30.471 [ms] (mean)
Time per request: 0.152 [ms] (mean, across all concurrent requests)
Transfer rate: 1384.27 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 1.8 0 15
Processing: 4 22 7.9 24 67
Waiting: 1 18 9.7 20 66
Total: 6 23 7.4 24 67

Percentage of the requests served within a certain time (ms)
50% 24
66% 24
75% 24
80% 25
90% 31
95% 32
98% 41
99% 61
100% 67 (longest request)

不采用eaccelerator加速测试
ab -c 200 -n 10000 http://www.test.com/phpinfo.php
测试结果

Server Software: nginx/0.8.7
Server Hostname: www.test.com
Server Port: 80

Document Path: /test.php
Document Length: 25 bytes

Concurrency Level: 200
Time taken for tests: 1.373767 seconds
Complete requests: 10000
Failed requests: 0
Write errors: 0
Non-2xx responses: 10011
Total transferred: 2162376 bytes
HTML transferred: 250275 bytes
Requests per second: 7279.25 [#/sec] (mean)
Time per request: 27.475 [ms] (mean)
Time per request: 0.137 [ms] (mean, across all concurrent requests)
Transfer rate: 1536.65 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 2 3.0 2 21
Processing: 4 24 11.4 23 94
Waiting: 2 17 12.9 15 93
Total: 5 26 11.1 26 94

Percentage of the requests served within a certain time (ms)
50% 26
66% 29
75% 31
80% 31
90% 32
95% 34
98% 83
99% 92
100% 94 (longest request)


结果说明:
通过ab的测试,从结果来看(只需要看黑体部分的内容就OK了),Requests per second(每秒事务数),Time per request(平均事务响应时间),Time per request(每个请求实际运行时间的平均值),这3个值在不采用eaccelerator加速的情况下,性能更强
总结:
不知是我的配置和测试的问题?还是在新的php版本中eaccelerator确实出现兼容性问题?

mysql数据类型区别之BLOB与TEXT

Posted: 2009年7月17日星期五
当数据量比较小时我们会选择使用占用空间相对较小的char或varchar数据类型,当数据量相对较大时通常会选择blob或text数据类型来存储他们。他们都可以存储可变数量的文本数据,在TEXT或BLOB列的存储或检索过程中,不存在大小写转换。两者的区别在于,blob能保存存储二进制数据,比如相片,blob也没有字符集概念,并且排序和比较基于列值字节的数值值。TEXT列有一个字符集,并且根据字符集的校对规则对值进行排序和比较。有4种blob类型,分别为:TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB。它们只是可容纳值的最大长度不同。text类型也有相对应的4种数据类型,分别为:TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT。在大多数方面,可以将BLOB列视为能够足够大的VARBINARY列。同样,可以将TEXT列视为VARCHAR列。BLOB和TEXT在以下几个方面不同于VARBINARY和VARCHAR:
1、当保存或检索BLOB和TEXT列的值时不删除尾部空格。(这与VARBINARY和VARCHAR列相同)。
2、请注意比较时将用空格对TEXT进行扩充以适合比较的对象,正如CHAR和VARCHAR。
3、对于BLOB和TEXT列的索引,必须指定索引前缀的长度。对于CHAR和VARCHAR,前缀长度是可选的。
4、BLOB和TEXT列不能有 默认值。
当对blob和text数据类型执行大量删除操作时存在很到的性能问题,删除操作能给数据表格留下很大的的空洞,以后填入这些空洞的插入操作存在性能问题,下面通过一个具体事例来说明这个空洞问题。

mysql> create table t(id varchar(100), context text);
Query OK, 0 rows affected (0.02 sec)
mysql> insert into t values(1, repeat('beijing', 100)),(2, repeat('beijing', 100)),(3, repeat('beijing', 100));
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0

再连续执行如下语句16次

mysql> insert into t select * from t;
Query OK, 196608 rows affected (1.20 sec)
Records: 196608 Duplicates: 0 Warnings: 0

退出mysql,在操作系统下查看mysql数据文件夹下的,t.MYD文件大小

[root@backup ~]# du -sh /usr/local/mysql/data/test/t*
12K /usr/local/mysql/data/test/t.frm
268M /usr/local/mysql/data/test/t.MYD
4.0K /usr/local/mysql/data/test/t.MYI

从上面看到数据文件大小为268M。
进入mysql中删除id为1的数据,通过以上数据插入操作,我们知道id为1的数据应该为总数据的1/3。

mysql> delete from t where id=1;
Query OK, 131072 rows affected (1.11 sec)

退出mysql,继续在操作系统下查看mysql数据文件夹下的,t.MYD文件大小

[root@backup ~]# du -sh /usr/local/mysql/data/test/t*
12K /usr/local/mysql/data/test/t.frm
268M /usr/local/mysql/data/test/t.MYD
4.0K /usr/local/mysql/data/test/t.MYI

从上面可以看到数据大小并没有发生变化,这就产生了上面所说的空洞,接下来通过optimize table对表进行碎片整理,避免空洞造成的性能问题

mysql> optimize table t;
+--------+----------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+--------+----------+----------+----------+
| test.t | optimize | status | OK |
+--------+----------+----------+----------+
1 row in set (0.99 sec)

再次退出mysql,在操作系统下查看mysql数据文件夹下的,t.MYD文件大小

[root@backup ~]# du -sh /usr/local/mysql/data/test/t*
12K /usr/local/mysql/data/test/t.frm
179M /usr/local/mysql/data/test/t.MYD
4.0K /usr/local/mysql/data/test/t.MYI

可以发现表的数据文件变小了,说明空洞所占领的空间已经被回收。对于采用了blob字段或text字段的数据表格,建议定期对表格进行optimize table操作,避免因空洞带来的性能问题。
由于text和blob数据量大,对于text和blob数据类型的检索,一般不建议直接采用mysql对他们进行检索。同时建议吧text和blob数据列分离到单独的表中,这样避免text或blob数据删除所带来的性能问题。

mysql数据类型区别之char与varchar

Posted: 2009年7月15日星期三
也许在使用mysql创建数据表时经常有这样的疑问,是选择char还是varchar,text还是blob数据类型呢?其实选择什么都行,都能完成我们的需求,但是,选择好合适的数据类型不仅能节约磁盘空间还能提高访问速度达到mysql调优的目的。
1、char和varchar
char和varchar都能存储字符串,其中char是固定长度,varchar是可变长度字符类型。下面通过一个实例来来说明两者的数据存储的区别

mysql> create table c(c char(4), v varchar(4));
Query OK, 0 rows affected (0.03 sec)
mysql> insert into c values('ab ', 'ab ');
Query OK, 1 row affected(0.00 sec)

通过在mysql函数cancat,在字符的末尾添加字符的功能可以看出他的存储情况

mysql> select concat(c, '+'), concat(v, '+') from c;
+----------------+----------------+
| concat(c, '+') | concat(v, '+') |
+----------------+----------------+
| ab+ | ab + |
+----------------+----------------+
1 row in set (0.00 sec)

从上可以看出在mysql检索时通常会删除掉char数据类型的空格。
由于char是固定长度,所以他的处理速度比varchar要快得多,但是他比较消耗存储空间,程序还得考虑他末尾的空格问题对于那些长度变化不大,并且对查询速度有较高要求的数据可以考虑使用char数据类型来存储。
下面来说说在不同的存储引擎条件下两者的使用原则
1、myisam存储引擎:建议使用固定长度的char数据类型来代替可变长度的varchar数据类型
2、memory存储引擎:都使用固定长度的数据行存储,因此使用char或varchar都没有关系,两者都被当作char数据类型进行处理
3、innodb存储引擎:建议使用可变的varchar数据类型,理由:对于innodb数据表,内部的行存储格式没有区分固定长度和可变长度列(所有的数据行都指向数据列值的头指针),因此使用固定长度的char数据类型不一定比使用可变数据长度的数据类型性能好,因而,主要的性能因素是数据行使用的存储总量,由于char数据列占用的空间比varchar数据列要大,因此varchar存储的空间要小,对于磁盘io来说越小的空间,处理数据能力越强。

putty vs SecureCRT

Posted: 2009年5月15日星期五
作为一名linux的sa,每天都会跟ssh终端打交道,选择配置好一个优秀的ssh终端工具对提高工作效率有很大的帮助。一般情况下有两种选择,一种是免费的putty和收费的SecureCRT。最初我选择的是免费putty,当我管理几台服务器时,确实是比较好的一种选择putty,不会记住用户名,密码,安全性好。在没有配置的情况下,putty的显示效果要比SecureCRT好。再者文件小,功能齐全,而且不需要安装,可以随时的打开使用。当我管理的不是几台linux服务器,而是几十台服务器后发现就不好了,每次都要输入IP地址,打开多台服务器时,不能作为tab显示,结果显示的窗口过多,当打开多个窗口是在任务栏上显示的标题不能标示对应打开的服务器,而是需要打开每个窗口去确认,确实不方便。而采用SecureCRT就没有这些问题。同时通过配置SecureCRT能够基本达到putty的显示效果,下面是我的配置SecureCRT的参数
1,配置终端类型,显示颜色
Options->SessionOptions ->Emulation,然后把Terminal类型改成xterm,并点中ANSI Color复选框。
2,配置字体,编码方式
字体设置:Options->SessionOptions->Appearance->font然后改成新宋体,文字大小设置为11号。
character改成utf-8的方式。
3,去掉显示的下划线
Options->SessionOptions->Appearance->Current color选择编辑,在新打开的窗口去掉show underline
4,vi中颜色显示效果
在打开的终端中,编辑/etc/profile 在文末添加如下内容
export TERM=xterm-color
添加完毕后执行如下内容,使之生效
source /etc/profile
同时用vi打开文件转入命令形式,输入如下命令
syntax on
如果是c语言的文件就接着输入set filetype=c,如果是jsp的话就输入,set filetype=jsp,对shell语言的话,不设置也能颜色显示,其它同理。就完成终端vi的颜色显示,不过遗憾的是对vi颜色显示支持不是很好,需要配置很多的系统参数。

采用tokyo cabinet搭建表格型DBM

Posted: 2009年5月12日星期二
DBM(DataBase Manager)的特征是:按键-值对的方式进行存储,使用hash进行查找,由于没有提供更高级的sql功能,它的效率远远超过传统的关系型数据库。现主流的dbm有:Berkeley DB(现属于oracle公司,是互联网部署最多的一款dbm),Gdbm(GNU Database Manager) QDBM: Quicker Database Manager,Tokyo cabinet,CDB:Constant Databases,Tokyo cabinet是基于QDBM再开发的一款DBM,它本身也只提供数据库引擎,所谓数据库引擎是指它提供了除SQL处理层以外的所有关系数据库的功能(如事务性(ACID)支持,数据存储,数据恢复等)。前面提到dbm的特征是一些键-值对的形式出现,那么Tokyo Cabinet作为一款dbm,它也不例外,怎么样才能实现跟普通的关系数据库一样的表格功能呢?Tokyo Cabinet的作者开发了一款Tokyo Tyrant的工具,可以采用它调用Tokyo Cabinet数据库引擎,实现跟管理数据库一样的数据库表格的功能,下面通过一个普通的员工信息表进行演示说明
表格内容如下

在普通的关系数据库mysql中建立这个表格的sql语句如下
create table staffs (
id int primary key,
name varchar(255),
sex enum ( 'male', 'female' ),
birthday date,
div varchar(255)
);

而根据上面所说的按键-值对方式进行存储,那么这样想的话,那不是得分成,几个db,分别是名字db,性别db,出生年月db和职务db,那这样的话表格的逻辑不是乱了吗!如果这样的话,估计没有几个人用,下面介绍采用tokyo tyrant的命令就可以做成这个表格,实现与普通关系型数据库提供的sql使用方式。
建立数据库
tctmgr create casket
插入数据

tctmgr put casket 1 "name" "张三" "sex" "male" \
"birthday" "19900101" "div" "brd,dev"
tctmgr put casket 5 "name" "李四" "sex" "female" \
"birthday" "19850523" "div" "dev"
tctmgr put casket 23 "name" "王五" "sex" "male" \
"birthday" "19881013" "div" "hr"

查询所有数据
tctmgr list -pv casket
--------
1 name 张三 sex male birthday 19900101 div brd,dev
5 name 李四 sex female birthday 19850523 div dev
23 name 王五 sex male birthday 19881013 div hr

条件查询
通过主键进行查询,查询用户id为23的职员信息
tctmgr get casket 23
--------
name 李四
sex female
birthday 19850523
div dev

通过不是主键进行查询

#查询以王开头的用户
tctmgr search -pv casket name STRBW "王"
-------
23 name 王五 sex male birthday 19881013 div hr
#查询以85年出生以后的男职员
tctmgr search -pv casket birthday NUMGE 19850101 sex STREQ "male"
--------
1 name 张三 sex male birthday 19900101 div brd,dev
23 name 王五 sex male birthday 19881013 div hr

附查询条件表达式(前面加~,相当于标准sql中的非)
* STREQ : 完全包含字符串,相当于标准sql中的where 字段=‘字符串’
* STRINC : 包含此字符串,相当于标准sql中like ‘*字符串*’
* STRBW : 以此字符串开头的内容,相当于标准sql中like ‘字符串*’
* STREW : 以此字符串结尾的内容,相当于标准sql中like ‘*字符串’
* STRAND : 包含在某区间内的内容,如标准sql中like ‘a-z’,那么他只能是a到z的字母
* STROR : 不包含在某区间内的内容,如标准sql中like ‘!a-z’,那么他只能是数字或其他的符号
* STRRX : 组合式结构,如标准sql中like “a“!b-m”#”
* NUMEQ : 数值大小一样 相当于标准sql中 where a=‘1’
* NUMGT : 数值大于某一值 相当于标准sql中 where a>‘1’
* NUMGE : 数值大于等于某一值 相当于标准sql中 where a>=‘1’
* NUMLT : 数值小于某一值 相当于标准sql中 where a<‘1’
* NUMLE : 数值小于某一值 相当于标准sql中 where a<=‘1’
* NUMBT : 数值处于某一数值区间,相当于标准sql中 where a> 1 and a < 10
* NUMOREQ : 数值不处于某一数值的区间,如果是a大于1,小于10的话,那这个表达式右边的内容应该相当于标准sql中 where a< 1 or a > 10
附排序
* STRASC : 按字面大小的升序排序
* STRDESC : 按字面大小的降序排序
* STRASC : 按数字大小的升序排序
* STRDESC : 按数字大小的降序排序
删除操作

tctmgr out casket 23
#确认结果
tctmgr list -pv casket
--------
1 name 张三 sex male birthday 19900101 div brd,dev
5 name 李四 sex female birthday 19850523 div dev

服务器故障[原创]

Posted: 2009年5月11日星期一
今天下午放在idc机房的机器无缘无故的就down掉了,打电话给机房的人要求重启,并要求告知原因,机房人告知机器没有打开,我把服务器上的日志分析了半天,发现没有任何down掉了日志,排除了机器故障,而处在同一个机柜里的服务都是好的,排除了供电故障,那么只有一种可能就是有人人为的把我的服务器的电源给拔掉了。我严重鄙视做这种事情的人。

web站点优化的理解[原创]

Posted: 2009年5月10日星期日
在网上看到很多文章在介绍web站点的优化方案,确实有作用,但都是片面的单独从一个角度去写的一个优化方案,很少有人比较全面的写一个优化方案,几乎都是要不从web页面上讲优化的条条款款,要不单独的从服务器上讲优化的条条款款,要不从db上写优化的条条款款。但这些优化方案局限性很大,很少有文章能提到一个全面的优化方案,下面是我自己所理解的一点web站点优化方案,个人认为前端优化是最重要的。当你的一个页面很大,到了一个页面2M,你服务器端优化做得再好,也是空的,你能及时的响应用户的请求,但是国内的用户现在的一个带宽情况你应该知道,光打开一个也面要多久时间,同时你服务器端的带宽是多少,带宽能承受得多少个用户同时并发,算算就知道了。再如果一个页面链接请求几百个,你服务器端优化得再好,承受的并发单台也只能做到不到十万个并发连接,同时浏览器还有对同一域名的并发限制,多域名的话,查询dns也是需要时间的。而国内做前端做得好的不是很多,包括alex排名非常高的各大网站(去掉google,baidu,页面元素太少,它们也确实做得很好),几乎前端做得很烂,真正做得好的是美国yahoo网站,大家可以去看看他的做法。yahoo工程师写了web前端优化的34条建议可以去看看,同时通过yahoo工程师写的firefox插件yslow去分析优化结果及优化建议。
再一个就是后端db的优化,因为db的连接是有限的,当数据量达到一定得规模,及出现db大并发时,db应该也是一个最慢的,当一个不合理的sql,很有可能就导致你网站的性能大打折扣,前端的web服务器优化得再好,也是空的,后端的db反应不过来,前端永远等待后端的结果,最好的做法就是少用db,能静态化页面,尽量静态化,能把数据缓存到cache中尽量缓存到cache中,优化sql链接,优化sql语句,当数据达到一定得数量级就分库,分表等操作。
第三个就是服务器的优化,这个做好,能基本提高大的并发,优化的方法应该用压力工具压(如:ab,webbench)几个简单的测试页面,进行调优,不是水平特别菜的sa的话,通过搜索引擎去查找别人的方案,依葫芦画瓢,基本上能达到一个不是很坏的结果。
再往后优化的话就是从架构上去做服务器的优化,不在本文讨论范围之类,这基本是包括最基本的优化方案,也是大部分站点能做的事情。做了以上的优化为老板节省了服务器及带宽资源。同时也使sa的工作量变少,因为管理的服务器越少,花在服务器维护的时间就越少,节省出来的时间可以做更多有意义的事情。
附yahoo的调查结果,后台只占5%,而前端高达95%之多,其中有88%的东西是可以优化的。

yslow更新到2.0[原创]

Posted: 2009年5月8日星期五
今天早上启动firefox发现yslow更新了新的版本,做为一个前端页面分析的一个好工具,更新后,界面变了,功能也变强了,首先在grad选项卡上,优化的内容增多了,以前是13条,现在又增加了,增加到22个,以前只是一个简单的列表,现在对各个选项进行分类,这样的话,就能对开发人员更明确,要优化的地方在那。评分选项上,各个参数如果不是A的话,会列出各个选项中做得不好的内容,不像以前点击后直接到yahoo deverloper的建议页面,现在得出的结果更明确。componets选项上,以前只是做一个列表。能做各个选项进行一个排序,现改成了分类列出,对于css中的图片,以前也是作为一个图片列表,不能很好明白这个图片到底出现在那,现在就能更仔细的得出结果,同时多了cookie发送和接收大小的列,headers显示及expires的列,每个文件响应时间及etage,action选项,功能更强,显示更好。statistics变化不大,准确的说,到现在还没有发现有变化在那。对于tools选项功能不多,值得一提的是有一个叫all smush.it的小工具,它是一个在线批量压缩图片工具,支持批量压缩图片,在无损图片质量的前提下达到图片大小的最优化压缩。压缩完毕之后下载zip格式压缩包,解压后便可以使用图片了。

为php添加pdo_oci模块的几种方法[原创]

Posted: 2009年5月7日星期四
最近公司的一部分开发决定采用框架进行开发,需要php_oci的php扩展模块。比较遗憾的最新的pdo_oci的版本还是05年开发的,安装过程如不注意会有比较多的问题,本人总结了一下它的几种安装方法,写下来进行备忘。
第一种就是在编译时添加--with-pdo-oci参数,这种方式的话,如果是刚开始搭建php环境的话应该是一种比较好的一种方式,具体安装步骤如下
首先安装oracle客户端,安装方法请查看我以前写的"Linux下编译安装PHP的oracle扩展",
值得注意的是,如果你采用rpm包安装的是64位的客户端的话,必须得为oracle客户端的include建立一个软连接,具体建立方法如下

ln -s /usr/lib/oracle/10.2.0.4/client64 /usr/lib/oracle/10.2.0.4/client

ln -s /usr/include/oracle/10.2.0.4/client64 /usr/include/oracle/10.2.0.4/client

再就是在编译时添加如下编译选项进行编译安装
--with-pdo-oci=instantclient,/usr,10.2.0.4
具体说明一下,instantclient即oracle的instant client的意思,/usr 就是oracle instant client安装目录,10.2.0.4 是oracle instant client版本,默认情况下如果写成这样的话,它会自动到/usr/include/oracle/10.2.0.4/client和/usr/lib/oracle/10.2.0.4/client查找依赖库文件,如果安装的64位的oracle instant client的话就必须得建立上面的一个软链接,不然就找不到所依赖的oci.h头文件而报错。其它的也就是跟普通的php安装一样,不需要任何特别的操作就能安装好php的PDO_OCI的扩展。
第二种方式即通过php的pear执行安装,这种适合于已经部署好了php环境,需要添加一个pdo_oci的扩展
如果在编译过程中没有添加--enable-sigchild参数的话,安装起来应该是最快的,最简单,最灵活。如果编译时添加了此参数的话,这种方式就不适合你,就别浪费时间了,安装时会报错。安装方法如下
添加oracle环境
export ORACLE_HOME=/usr/lib/oracle/10.2.0.4/client64/lib
添加oracle instant client的头文件的软链接
for i in /usr/include/oracle/10.2.0.4/client64/*;do;ln -s $i /usr/include;done
下载PDO_OCI进行安装
curl -O http://pecl.php.net/get/PDO_OCI-1.0.tgz
pear install PDO_OCI-1.0.tgz

在php.ini文件当中修改extension的路径及添加pdo_oci的扩展,
将extension_dir = "./"修改为extension_dir = "/usr/local/webserver/php/lib/php/extensions/no-debug-non-zts-20060613/"同时在它后面添加如下内容
extension=pdo_oci.so
重新启动http服务器即完成pdo_oci的安装,如不需要了,可以通过直接执行
pear uninstall PDO_OCI进行卸载
第三种安装方法直接编译pdo_oci的扩展包
安装前,如果你采用rpm包安装的是64位的客户端的话,必须得为oracle客户端的include建立一个软连接,具体建立方法如下

ln -s /usr/lib/oracle/10.2.0.4/client64 /usr/lib/oracle/10.2.0.4/client

ln -s /usr/include/oracle/10.2.0.4/client64 /usr/include/oracle/10.2.0.4/client

下载PDO_OCI进行安装
curl -O http://pecl.php.net/get/PDO_OCI-1.0.tgz
tar xf PDO_OCI-1.0.tgz
cd PDO_OCI-1.0
/usr/local/php/bin/phpize
./configure --with-pdo-oci=instantclient,/usr,10.2.0.4 --with-php-config=/usr/local/php/bin/php-config
make
make install

在php.ini文件当中修改extension的路径及添加pdo_oci的扩展,
将extension_dir = "./"修改为extension_dir = "/usr/local/webserver/php/lib/php/extensions/no-debug-non-zts-20060613/"同时在它后面添加如下内容
extension=pdo_oci.so
重新启动http服务器即完成pdo_oci的安装.
以上几种安装方法,安装完成后通过以下两种方式可以检验是否安装成功
安装完成执行php -m应该可以查看到PDO_OCI这么一行文字,表示安装成功,或通过phpinfo可以看到如下图所示的内容


表示安装成功。至此就是我总结的几种安装方法。

Linux下编译安装PHP的oracle扩展[原创]

Posted: 2009年5月5日星期二
oralce做为全球最大的数据库软件,php作为全球应用最广的web站点开发语言,两者结合开发的软件的开源软件不是很多,在互联网上大部分都是采用的LAMP平台即Linux+Apache+Mysql+PHP的组合方式进行软件开发与部署,真正采用Linux+Apache+Oracle+PHP的WEB应用站点并不是特别的多,甲骨文公司一直想把lamp平台上的那个M(mysql)变成O(Oracle)。下面通过一个实例编译安装PHP的Oracle扩展。本示例采用的2台服务器进行部署,一台专门跑web程序,一台专门跑Oracle DB。下面的示例是搭建一个能连接oracle的web应用服务器。
部署方法分一下几种步骤
1.下载安装oracle客户端
2.下载安装apache
3.下载安装php
4.配置apache
5.测试
下载安装Oracle 客户端
从oracle官网下载oracle的rpm客户端,具体下载页面如下
http://www.oracle.com/technology/software/tech/oci/instantclient/index.html
根据你的oracle db版本及操作系统下载相应版本的oracle客户端,本示例中采用64位centos操作系统oracle 10.2.1的oracle db,为安装简便话建议采用下载rpm软件包进行安装,具体只需要下载以下两个软件包,
oracle-instantclient-basic-10.2.0.4-1.x86_64.rpm
oracle-instantclient-devel-10.2.0.4-1.x86_64.rpm
安装软件需注册,免费注册登录后可免费下载oracle 客户端。下载完成后上传到服务器进行安装,通过简单的rpm命令即可完成安装
rpm -ivh oracle-instantclient-basic-10.2.0.4-1.x86_64.rpm
rpm -ivh oracle-instantclient-devel-10.2.0.4-1.x86_64.rpm
下载apache,安装apache
wget http://apache.etoak.com/httpd/httpd-2.2.11.tar.bz2
tar xf httpd-2.2.11.tar.bz2
cd httpd-2.2.11
./configure --prefix=/usr/local/apache --enable-module=so
make
make install

建立启动脚本
cp build/rpm/httpd.init /etc/rc.d/init.d/httpd
修改启动脚本/etc/rc.d/init.d/httpd
找到以下几行

apachectl=/usr/sbin/apachectl
httpd=${HTTPD-/usr/sbin/httpd}
CONFFILE=/etc/httpd/conf/httpd.conf

分别对应修改为:

apachectl=/usr/local/apache/bin/apachectl
httpd=${/usr/local/apache/bin/httpd}
CONFFILE=/usr/local/apache/conf/httpd.conf

设定apache自启动

chmod +x /etc/init.d/httpd
chkconfig --add httpd
chkconfig httpd on

下载安装php

yum -y install zlib zlib-devel gd gd-devel libjpeg libjpeg-devel libpng libpng-devel
wget http://cn.php.net/get/php-5.2.9.tar.bz2/from/cn2.php.net/mirror
tar xf php-5.2.9.tar.bz2
cd php-5.2.9
./configure \
--with-oci8=instantclient,/usr/lib/oracle/10.2.0.4/client64/lib \
--prefix=/usr/local/php \
--with-config-file-path=/usr/local/php/etc \
--with-apxs2=/usr/local/apache/bin/apxs \
--with-zlib \
--enable-mbstring \
--with-gd \
--with-jpeg-dir
make
make install
cp php.ini-dist /usr/local/php/etc/php.ini

配置apahce使它支持php,编辑/usr/local/apache/conf/httpd.conf文件,在AddType application/x-gzip .gz .tgz后添加如下内容

AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps

编辑apache的启动脚本是它启动时加载到oracle的客户端文件,编辑/usr/local/apache/bin/envvars在文件的开头添加如下内容
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
export PATH
export ORACLE_BASE=/usr/lib/oracle
export ORACLE_HOME=$ORACLE_BASE/10.2.0.4/client64
export ORACLE_SID=oracle_sid
export PATH=$ORACLE_HOME/bin:$PATH
export LD_LIBRARY_PATH=$ORACLE_HOME/lib:/usr/lib
export NLS_DATE_FORMAT="yyyy-mm-dd HH24:MI:SS"

以上就完成了LAOP平台的搭建,可以启动apache进行测试

/etc/init.d/httpd start

在网站的根目录中建立phpinfo文件进行测试
phpinfo();
?>

打开phpinfo页面可以看到有一个oci8的选项,说明php的oracle扩展已经安装成功。
也可以通过下面的这个命令检查输出的内容是否包含oci选项确认php的oracle扩展安装是否成功
/usr/local/php/bin/php -m

多子网的dhcp服务器[原创]

Posted: 2009年5月4日星期一
在局域网建设当中,为便于管理,经常会搭建多个子网,对于多子网的dhcp服务器,也许有人会采用dhcp中继,或三层交换机或路由器自带的dhcp功能进行搭建,以上的成本比较的高,通过安装一台廉价的Linux PC就能解决这些问题,Linux自带的dhcp软件结合虚拟网卡就能够实现多子网的dhcp服务器,现在通过一个实例进行说明
本次实例的拓扑图如下

说明:
实例中两个子网的地址分别为:192.168.0.0/24和192.168.1.0/24
dhcp服务器的两个网卡地址分别为:192.168.0.1/24和192.168.1.1/24

配置dhcp服务器
先配置dhcp服务器的网卡地址eth0.0
ifconfig eth0:0 192.168.0.1 netmask 255.255.255.0 up
配置dhcp服务器的网卡地址eth0.1
ifconfig eth0:1 192.168.1.1 netmask 255.255.255.0 up
安装配置dhcp服务
1) 安装DHCP服务器包(RPM包名:dhcpd)。
2)配置服务器IP地址
3) 编辑DHCP服务器配置文件 /etc/dhcp.conf。

ddns-update-style interim;
ignore client-updates;
option time-offset -18000; # Eastern Standard Time
default-lease-time 21600;
max-lease-time 432000;
option domain-name-servers 192.168.0.1;
subnet 192.168.0.0 netmask 255.255.255.0 {
pool{
range 192.168.0.2 192.168.0.254;
option routers 192.168.0.1;
option broadcast-address 192.168.0.255;
option subnet-mask 255.255.255.0;
}
}
subnet 192.168.1.0 netmask 255.255.255.0 {
pool{
range 192.168.1.2 192.168.1.254;
option routers 192.168.1.1;
option broadcast-address 192.168.1.255;
option subnet-mask 255.255.255.0;
}
}

编辑提供dhcp的服务网卡地址/etc/sysconfig/dhcpd
DHCPDARGS="eth0:0 eth0:1"
启动dhcp服务
/etc/init.d/dhcpd start

以上就通过单台廉价的linux PC完成对2子网的dhcp服务器的配置,同样使用于更多个子网的dhcp服务器的配置。

判断远端主机死活,发送飞信短信通知[原创]

Posted: 2009年4月28日星期二
写了个脚本判断远端主机的死活,每隔5分钟检查一次,远端主机是否正常,如死掉了就发送飞信短信到管理员手机上,若管理员不处理,每隔5分钟发一次。脚本内容如下:

#!/bin/sh
IP=172.16.10.100
healthcheck(){
ping -c 1 -w 1 $IP > /dev/null
return $?
}
send_message(){
curl -d username=15000000000 -d password=123456 -d sendto=15000000000 -d message="远端主机$IP已经down掉了" http://sms.api.bz/fetion.php
}
while true; do
while healthcheck; do
echo "health ok!"
sleep 300
done
echo "fail over!"
send_message
sleep 300
done

说明:curl中的几个参数进行说明一下文中采用了http://sms.api.bz的web发送接口,通过curl post数据到http://sms.api.bz,username是飞信的用户名,password是飞信的密码,sendto是发送到飞信好友手机(要发送飞行短信,只能发送给飞信的好友用户)。下面就是一个循环,每隔300秒进行检查,当服务器死掉后,自动发送短信到飞信的好友手机上,如服务器一直没有起来,就每隔300秒再进行一次检查,发送1条报警短信。

感谢http://sms.api.bz提供web发送接口。

搭建Tokyo Tyrant的故障转移

Posted: 2009年4月27日星期一
以前写了一篇关于tokyo tyrant的replication实现了高可靠性,文中最后说了它的几个缺点,本文中将通过tokyo tyrant更高级的特性,故障转移机制,解决这些问题。本文介绍tokyo tyrant的的故障转移机制,有点像lvs的主从机制。当主DB down掉的时候,自动的把备份DB转为主db,提供服务,而不需要人工的干预。同时采用tokyo tyrant的replication机制,保证数据完整性的同时,还具有遇到故障自动切换主从服务器,实现高可靠性。
下面是一个tokyo tyrant的故障转移的实例,现看实现原理图

在同一台机器上打开3个窗口。
在终端A中创建主DB更新log文件夹
mkdir /tmp/ulog-a
在终端A中启动服务ttserver -port 1978 -ulog /tmp/ulog-a -sid 1 -mhost localhost -mport 1979 -rts /tmp/a.rts /tmp/casket-a.tch
在终端B中创建辅DB更新log文件夹mkdir /tmp/ulog-b
在终端B中启动辅DBttserver -port 1979 -ulog /tmp/ulog-b -sid 2 -mhost localhost -mport 1978 -rts /tmp/b.rts /tmp/casket-b.tch
在终端C中对主DB插入测试数据tcrmgr put -port 1978 localhost TTTest TestByZLJ
在终端C中查询主DBtcrmgr get -port 1978 localhost TTTest
在终端C中查询辅DBtcrmgr get -port 1979 localhost TTTest
模拟主DB down掉,在终端A中按下Ctrl+C
在终端C中对辅db进行数据插入操作tcrmgr put -port 1979 localhost test TTTest
在终端C中对辅DB进行数据检索操作tcrmgr get -port 1979 localhost test
在终端A中重新启动主DBttserver -port 1978 -ulog /tmp/ulog-a -sid 1 -mhost localhost -mport 1979 -rts /tmp/a.rts /tmp/casket-a.tch
在终端C中对主DB进行数据检索tcrmgr get -port 1978 localhost test
最后查询得到的结果还是TTTest,在对辅DB进行插入操作的时候主DB已经down掉了,而当主DB重新起来后,对主DB再次进行查询得到了我们想要的结果。也就是说主DB重新起来后自动的从辅DB进行数据同步操作,保证数据的完整性,同时也为SA有时间去处理这类故障。

使用kickstart批量安装Linux

Posted: 2009年4月26日星期日
作为一名SA,在工作当中会经常安装Linux操作系统,对多台服务器配置同样的环境。如果一个个去安装,一台台去配置,那是一件吃力不讨好的事情。现只要你有一台安装好的Linux,要安装的服务器能支持pxe网络启动安装,所有的服务器能组建在一个局域网,几十台服务器不到半个小时不仅安装好系统同时也完成基本的配置。在Redhat系列操作系统中有个叫Kickstart软件,它的作用是的按照事先设计好的方式自动安装操作系统。最常见的方式是网络安装,也可以采用CDROM或硬盘安装。本文主要介绍Kickstart的网络安装。其中kickstart网络安装方式支持nfs,ftp,http的方式进行安装。本文中实例是通过nfs的方式安装centos,同样适合于安装redhat,fedora等操作系统。
本文的实施方案的拓扑图如下所示
                 ┌────────┐
                 │  Boot Server   │
                 │(DHCP TFTP NFS)│
                 └────┬───┘
                          │
                ┌────┴───┐
                │      Switch   │
                └────┬───┘
                         │
          ┌───────┴───────┐
          │                            │
  ┌───┴───┐              ┌───┴───┐
  │  Client(PxE)│              │  Client(PxE)│
  └───────┘              └───────┘实施步骤
1.配置启动服务器
2.配置安装方案
3.启动待安装服务器,进行系统安装

配置启动服务器
启动服务器的目的是帮助待安装机器上启动Red Hat Linux安装程序。启动服务器上需要搭建一个DHCP 服务器和一个TFTP 服务器,一个nfs用来传输网络镜像文件。前者是为了给待安装机器分配IP地址,后者则是提供了一个让待安装机器下载启动镜像的途径。
首先配置DHCP服务
1) 安装DHCP服务器包(RPM包名:dhcpd)。
2)配置服务器IP地址
3) 编辑DHCP服务器配置文件 /etc/dhcp.conf。

ddns-update-style interim;
ignore client-updates;
allow booting;
allow bootp;

subnet 192.168.0.0 netmask 255.255.255.0 {
    option routers            192.168.0.1;
    option subnet-mask        255.255.255.0;
    option domain-name-servers    192.168.0.1;
    range dynamic-bootp 192.168.0.128 192.168.0.254;
    default-lease-time 21600;
    max-lease-time 43200;
    #deny unknown-clients;

    #group pxe {
        next-server 192.168.0.4;
        filename "/centos/pxelinux.0";
        #host client { hardware ethernet 00:00:00:00:00:00; fixed-address 192.168.0.100; }
     }     
}

注:如需给指定的服务器进行安装的话,就去掉上面的注释。
    简单说一下文中的注释,deny unknown-clients;拒绝给为授权机器分配IP地址
    next-server 指定启动服务器地址,filename指定启动文件地址。
    host client为mac地址为00:00:00:00:00:00的client服务器指定IP地址为:192.168.0.100.

4) 给启动服务器配置一个IP,这个IP必须在DHCP服务器定义的子网内。
5) 启动DHCP服务。
service dhcpd start

配置TFTP服务器(如没有安装xinetd软件包,先安装这个软件包)

1) 安装TFTP服务器包(RPM包名:tftpd)。
2) 编辑TFTP 服务器的配置文件 /etc/xinetd.d/tftp。配置文件如下:

service tftp
{
    socket_type     = dgram
    protocol        = udp
    wait            = yes
    user            = root
    server          = /usr/sbin/in.tftpd
    server_args     = -s /tftpboot
    disable         = no
}

这里选定了/tftpboot为TFTP 服务器的根目录位置。
3)启动TFTP服务
service xinetd start
4)建立存放Linux安装程序的内核/根文件系统文件的目录
mkdir /tftpboot/centos
复制Centos光盘的/isolinux目录下Linux安装程序内核/根文件系统文件initrd.img 和vmlinuz到
/tftpboot/centos
5)将启动镜像文件pxelinux.0复制到TFTP服务器根目录。
启动镜像pxelinux.0可以在syslinux安装包里获得。安装好syslinux安装包后,将pxelinux.0复制到/tftpboot/centos
cp /usr/lib/syslinux/pxelinux.0 /tftpboot/centos
启动镜像pxelinux.0文件在执行过程中,会读取配置文件以确定它应该载入什么Linux内核文件来运行。所有的配置文件都放在启动服务器的/tftpboot/centos/pxelinux.cfg/目录下。
建立启动配置文件存放文件夹mkdir /tftpboot/centos/pxelinux.cfg
6)建立启动配置文件default

default centos5
label centos5
kernel vmlinuz
append load initrd=initrd.img ksdevice=eth0 ks=nfs:192.168.0.4:/home/centos/ks.cfg devfs=nomount


配置nfs
配置nfs共享目录,nfs的配置文件为/etc/exports
/home/centos *(ro,no_root_squash)
启动nfs相关服务
service portmap start
service nfs start
确认共享目录成功了
showmount -e localhost
若得到结果包含/home/centos * ,说明成功配置好nfs

配置安装方案
配置文件为/home/centos/ks.cfg

text
install
repo --name=epel --baseurl=http://download.fedora.redhat.com/pub/epel/5/x86_64/
nfs --server=192.168.0.4 --dir=/home/centos/
keyboard us
lang en_US
key --skip
xconfig --defaultdesktop=GNOME --depth=8 --resolution=640x480
network --bootproto=dhcp --device=eth0 --onboot=on
#network --bootproto=dhcp --device=eth1 --onboot=on
rootpw --iscrypted $1$Sl6MDA1O$Z2HRda3FpCmaSRqrmD.gD0
user --name test --homedir /home/test --iscrypted --password=$1$IXb255iK$wZq/pCb2o70P1F8pXnI6P/ --shell=/bin/bash --groups=test,wheel
firewall --disabled
auth --useshadow --enablemd5
selinux --disabled
timezone --isUtc Asia/Shanghai
bootloader --location=mbr
logging --level=info

clearpart --all --drives=sda
part /boot --bytes-per-inode=4096 --fstype="ext3" --size=150
part swap --bytes-per-inode=4096 --fstype="swap" --size=2048
part pv.01 --size=1 --grow
volgroup lvm pv.01
logvol / --vgname=lvm --size=20480 --name=root
logvol /var --vgname=lvm --size=20480 --name=var
logvol /tmp --vgname=lvm --size=20480 --name=tmp
logvol /data --vgname=lvm --size=1 --grow --name=data
reboot

%packages
@editors
@development-libs
@base
@development-tools
-firstboot-tui
ntp
net-snmp-utils
net-snmp-libs
net-snmp
openssl-devel
nrpe
nagios-plugins
nagios-plugins-all

%post --log=/mnt/sysimage/root/anaconda-post.log --erroronfail
/bin/cat << EOF >/etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=none
HWADDR=`ifconfig eth0 |grep HWaddr |awk '{print $5}'`
ONBOOT=yes
NETMASK=`ifconfig eth0|sed -e 's/^.*Mask:\([^ ]*\)$/\1/p' -e d`
IPADDR=`ifconfig eth0|sed -e 's/^.*inet addr:\([^ ]*\).*$/\1/p' -e d`
GATEWAY=`netstat -rn|grep eth0|awk '{print $2}' | grep -v 0.0.0.0`
TYPE=Ethernet
EOF
echo "nameserver 192.168.0.1" > /etc/resolv.conf

#disable ipv6
sed -i '/NETWORKING_IPV6=/s/yes/no/' /etc/sysconfig/network
echo "alias net-pf-10 off" >> /etc/modprobe.conf
echo "alias ipv6 off" >> /etc/modprobe.conf
/sbin/chkconfig --level 35 ip6tables off

### Setting to ssh
/usr/bin/patch /etc/ssh/sshd_config << EOF
13c13
< #Port 22
---
> Port 30000
39a40
> PermitRootLogin no
60c61
< PasswordAuthentication yes
---
> PasswordAuthentication no
110c111
< #UseDNS yes
---
> UseDNS no
EOF
/sbin/restorecon /etc/ssh/sshd_config

/bin/mkdir ~test/.ssh
/bin/chmod 700 ~test/.ssh
/bin/cat << EOF > ~test/.ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA3NhtQhIrjeJy5WIlohdTn9SooaTsxpSiBljhx189b08DyC3xALH6R87RvX7+6jwJF/TqzwhZ495HTDfl7en98Dp97Xi8tYibPm9E3QBil9PGG+952flgVxTZZvS+D/rJ/7vuIp8iAiO9u3JUsZWP7X0dIaNhrnVfL31juk8I/EippzzMkjzUeRg62UizCxVD7AynwnqAsPdr6kcv9MGAZOvg7lDMv2Orbgsl0nakwtt+jmtQPGziLW+nQFVlHXTekmiJ2bDfURlRDWaegOftD+qGN3pIjO1TFCxgZccagYAVg1Jm+mFHIMIlmwpTcmBXO9DjjAhj6BXVbBNArqU5lQ== test@test.com
EOF
/bin/chmod 644 ~test/.ssh/authorized_keys
/bin/chown -R test:test ~test/.ssh/

### disable not wheel group user use su chang to root
sed -i '6s/^#auth/auth/g' /etc/pam.d/su

### Setting SNMP
/bin/cat << EOF > /etc/snmp/snmpd.conf
com2sec localhost localhost COMMUNITY_STRING
com2sec localnet 192.168.0.0/24 COMMUNITY_STRING

group test v1 localhost
group test v2c localhost
group test v1 localnet
group test v2c localnet

view all included .1 80

access test "" any noauth exact all none none
access test "" any noauth exact all all none

disk / 100000
EOF
/sbin/restorecon /etc/snmp/snmpd.conf

### disable CTRL-ALT-DELETE
/usr/bin/patch /etc/inittab << EOF
32c32,33
< ca::ctrlaltdel:/sbin/shutdown -t3 -r now
---
> #ca::ctrlaltdel:/sbin/shutdown -t3 -r now
> ca::ctrlaltdel:ca::ctrlaltdel:/usr/bin/logger 'CTRL-ALT-DELETE trap is disabled'
EOF
/sbin/restorecon /etc/inittab

### vim
/bin/sed -i "8 s/^/alias vi='vim'/" /root/.bashrc
/bin/echo 'syntax on' > /root/.vimrc

### ntp time set
/bin/echo '15 3 * * * /usr/sbin/ntpdate 192.168.0.4 > /dev/null 2>&1' >> /var/spool/cron/root

### Setting nagios monitor
/bin/cat << EOF > /etc/nagios/nrpe.cfg
log_facility=daemon
pid_file=/var/run/nrpe.pid
server_port=5666
#If you want monitor to oracle please change nrpe_uset and nrpe_group to oracle user an oracle group
nrpe_user=nrpe
nrpe_group=nrpe
allowed_hosts=192.168.0.4
dont_blame_nrpe=0
debug=0
command_timeout=60
connection_timeout=300
command[check_ping]=/usr/lib64/nagios/plugins/check_ping -H 172.16.10.13 -w 500,10% -c 1000,25%
command[check_load]=/usr/lib64/nagios/plugins/check_load -w 9.0,7.0,6.0 -c 10.0,8.0,7.0
command[check_disk_root]=/usr/lib64/nagios/plugins/check_disk -w 20% -c 10% -p /
command[check_disk_var]=/usr/lib64/nagios/plugins/check_disk -w 20% -c 10% -p /var
command[check_disk_tmp]=/usr/lib64/nagios/plugins/check_disk -w 20% -c 10% -p /tmp
command[check_swap]=/usr/lib64/nagios/plugins/check_swap.pl -w 50% -c 10%
command[check_zombie_procs]=/usr/lib64/nagios/plugins/check_procs -w 5 -c 10 -s Z
command[check_total_procs]=/usr/lib64/nagios/plugins/check_procs -w 150 -c 200 -s RSZDT
command[check_users]=/usr/lib64/nagios/plugins/check_users -w 3 -c 5
command[check_ssh]=/usr/lib64/nagios/plugins/check_ssh -H 127.0.0.1 -p 65508
command[check_ntp]=/usr/lib64/nagios/plugins/check_ntp -H 172.16.10.13 -w 1 -c 2
#Check Oracle Start
#command[check_oracle_tns]=/usr/lib64/nagios/plugins/check_oracle --tns oracle_tns_name
#command[check_oracle_db]=/usr/lib64/nagios/plugins/check_oracle --db oracle_sid
#command[check_oracle_login]=/usr/lib64/nagios/plugins/check_oracle --login oracle_tns_name
#command[check_oracle_cache]=/usr/lib64/nagios/plugins/check_oracle --cache oracle_tns_name DB_username DB_passwd 80 90
#command[check_oracle_tablespace]=/usr/lib64/nagios/plugins/check_oracle --tablespace oracle_tns_name DB_username DB_passwd tab 90 80
#Check Oracle End
#command[check_http]=/usr/lib64/nagios/plugins/check_http -H 127.0.0.1
#command[check_dig]=/usr/lib64/nagios/plugins/check_dig -H 127.0.0.1 -l zhliji2.blogspot.com
#command[check_smtp]=/usr/lib64/nagios/plugins/check_smtp -H 127.0.0.1
#command[check_pop]=/usr/lib64/nagios/plugins/check_pop -H 127.0.0.1
#command[check_imap]=/usr/lib64/nagios/plugins/check_imap -H 127.0.0.1 -p 143
#command[check_clamd]=/usr/lib64/nagios/plugins/check_clamd -H /tmp/clamd.socket
#command[check_amavisd]=/usr/lib64/nagios/plugins/check_tcp -H 127.0.0.1 -p 10024
#command[check_spamd]=/usr/lib64/nagios/plugins/check_tcp -H 127.0.0.1 -p 783
#command[check_mysql]=/usr/lib64/nagios/plugins/check_mysql -H 127.0.0.1 -u root -p mysql root's password
EOF
/sbin/chkconfig nrpe on

###Setting IPtables
cat << EOF > /etc/sysconfig/iptables
*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [1:140]
:ping - [0:0]
-A INPUT -p icmp -m icmp --icmp-type 8 -m state --state NEW -j ping
-A INPUT -i lo -j ACCEPT
-A INPUT -s 192.168.0.0/255.255.255.255.0 -i eth0 -j ACCEPT
-A INPUT -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i eth0 -p icmp -m icmp --icmp-type 0 -j ACCEPT
-A INPUT -i eth0 -p icmp -m icmp --icmp-type 3 -j ACCEPT
-A INPUT -i eth0 -p icmp -m icmp --icmp-type 3/4 -j ACCEPT
-A INPUT -i eth0 -p icmp -m icmp --icmp-type 4 -j ACCEPT
-A INPUT -i eth0 -p icmp -m icmp --icmp-type 11 -j ACCEPT
-A INPUT -i eth0 -p icmp -m icmp --icmp-type 12 -j ACCEPT
-A INPUT -i eth0 -p icmp -m icmp --icmp-type 14 -j ACCEPT
-A INPUT -i eth0 -p icmp -m icmp --icmp-type 16 -j ACCEPT
-A INPUT -i eth0 -p icmp -m icmp --icmp-type 18 -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 30000 -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,PSH,URG -j DROP
-A INPUT -i eth0 -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,PSH,ACK,URG -j DROP
-A INPUT -i eth0 -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,ACK,URG -j DROP
-A INPUT -i eth0 -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP
-A INPUT -i eth0 -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j DROP
-A INPUT -i eth0 -p tcp -m tcp --tcp-flags FIN,SYN FIN,SYN -j DROP
-A ping -p icmp -m icmp --icmp-type 8 -m limit --limit 1/sec -j RETURN
-A ping -p icmp -j REJECT --reject-with icmp-port-unreachable
COMMIT
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
EOF

###disable serverices
for i in `ls /etc/rc3.d/S*`
do
CURSRV=`echo $i|cut -c 15-`
case $CURSRV in
crond | irqbalance | microcode_ctl | network | random | iptables |sshd | syslog | snmpd | nagios | nrpe )
;;
*)
chkconfig --level 235 $CURSRV off
;;
esac
done

说明:上面的脚本比较的长,它不仅完成了系统安装,还完成了一些共通的初始化配置。
下面简单介绍一下里面的几个比较重要的参数
repo --name=epel --baseurl=http://download.fedora.redhat.com/pub/epel/5/x86_64/
为方便安装时能配置好nagios监控我在安装时添加了一个额外的安装源epel,进行安装安装nrpe。如果你没有网络可以不设定这个选项。
rootpw --iscrypted $1$Sl6MDA1O$Z2HRda3FpCmaSRqrmD.gD0
设定root的秘密为:123456
user --name test --homedir /home/test --iscrypted --password=$1$IXb255iK$wZq/pCb2o70P1F8pXnI6P/ --shell=/bin/bash --groups=test,wheel
建立一个普通用户,用户名为test,组为test和wheel,密码为123456。
clearpart --all --drives=sda
清除第一块磁盘上的所有数据,它下面的参数是分区参数
分区采用普通分区加lvm两者方式混合分区
其中/boot分区为150M,swap分区为2G
根分区,var,tmp分区分别为20G,剩余的磁盘空间全部给data分区

%packages部分为要安装的软件
其中@开头的部分为软件组,-开头的为不要安装的软件包,什么都不加就代表要安装的单独软件包

%post --log=/mnt/sysimage/root/anaconda-post.log --erroronfail
这一部分是安装软件后的配置,所有配置失败的部分都进行log记录,log文件存放在/root/anaconda-post.log
/bin/cat << EOF >/etc/sysconfig/network-scripts/ifcfg-eth0
这一部分为设置它的网卡,由于最初设置的为dhcp方式分配的方式,现实中我们使用的服务器一般为固定IP
通过这几个脚本,自动把dhcp设定的IP地址转为固定IP地址

### Setting to ssh
这一部分为设定ssh,为安全起见,通过脚本更改ssh的默认端口为30000,禁止root用户远程登录,同时设定登录方式为采用密钥的方式,最后一部分是为test用户设定一个密钥,这个密钥我们平时可以通过puttygen的工具,生成的密钥,把公钥的内容粘贴这就行了。

### disable not wheel group user use su chang to root
禁止非wheel组的用户通过su命令切换到root用户

### Setting SNMP
这一部分时建立设定snmp的配置文件,我们通常会用监控软件对服务器进行监控,比如说,
通过cacti等类似的软件对服务器进行流量监控,就需要snmp服务。为方便我在这也加上了

### disable CTRL-ALT-DELETE
这一部分是禁止按下CTRL-ALT-DELETE组合键后服务器重启

### vim
这一部分是方便用vi的一些参数

### ntp time set
这一部分设定服务器的时间同步,每天3:15分跟时间服务器192.168.0.4进行时间同步

### Setting nagios monitor
这一部分时设定服务器监控,脚本比较的全,包括大部分常见的应用服务。

###Setting IPtables
这一部分是设定防火墙,只对外开放ssh端口,同时加了一些网络工具参数

### disable serverices
去掉不必要的服务,只保留必须的服务。

把centos的镜像文件放置到启动服务器的/home/centos目录下,把待安装服务器设定从网卡启动,就可以完成安装。

搭建Tokyo Tyrant replication

Posted: 2009年4月24日星期五
介绍了Tokyo Tyrant(以下简称tt)的备份和还原,保证了数据完整性,由于它不是实时备份,因而不能保证数据的完整性,当磁盘坏掉了,而这时数据没有备份,因而导致数据的不完整性。
为解决上述问题,大家知道mysql中有个replication机制可以解决数据的完整性,同样tt也有replication机制保证数据的完整性,具体实现方法,数据库服务器把本机的更新log,分批次的实时传输到别的数据库服务器,传输更新log的服务器就是我们常说的主服务器,接收更新log的服务器就是我们常说的辅服务器。replication的好处就是,管理者配置好服务器,
主辅DB服务器自动保持数据的一致性。当主服务器down后,可以把辅服务器变为主服务器
提供服务,而保证不间断服务,同时也使管理员有时间重新为辅服务器添加一个新辅服务器,重新搭建replication。
具体实现方法见下图

通过上图看到,平时辅服务器几乎不接受请求,因而造成资源浪费,特别在大压力的情况下
主服务器的负荷很重,而辅服务器几乎没有负荷。由于主服务器的数据几乎是同步的,可以采用读写分离的方式,分散服务器的压力。这也是许多高负荷系统对DB采取的一种方式。
具体实现如下图


下面通过一个实例来介绍通过tt实现replication
在同一台机器上启动3个终端
在终端A中创建主DB更新log文件夹
mkdir /tmp/ulog-master
在终端A中启动服务
ttserver -port 1978 -ulog /tmp/ulog-master /tmp/casket-master.tch
在终端A中创建辅DB更新log文件夹
mkdir /tmp/ulog-master
在终端B中启动辅DB
ttserver -port 1979 -ulog /tmp/ulog-slave -mhost localhost -mport 1978 -rts /tmp/slave.rts /tmp/casket-slave.tch
在终端C中对主DB插入测试数据
tcrmgr put -port 1978 localhost TTTest TestByZLJ
在终端C中查询主DB
tcrmgr get -port 1978 localhost TTTest
在终端C中查询辅DBtcrmgr get -port 1979 localhost TTTest
查询主DB跟查询辅DB得到同样的结果‘TTTestByZLJ’,虽然只是对主db进行了数据插入操作
但是查询辅db得到了同样的结果,这样的话就不用担心服务器磁盘坏了没有备份了。
但是replication也不是万能的,它也有它的缺点,主DB与辅DB的之间的传输有数10微秒到数100微秒的延迟,在大并发下,延迟期间,主DB down掉了,有可能在延迟时产生的数据就丢失了。同时主DB down掉以后,它不能自动的切换到辅DB,而需要人工的参与,不能实现自动化运维。

Tokyo Tyrant备份和还原

Posted:
人为的误操作,机器的不可靠性导致数据的丢失,这是会经常发生在我们的身边。为减少数据的丢失,定期的备份可以解决部分数据丢失的可能。

Tokyo Tyrant(以下简称tt)提供备份还原机制实现高可靠性的功能。
只需要简单简单的把数据库文件进行拷贝,就能完成备份功能,具体实现方法见下图

下面通过简单的实例进行测试:
在同一台机器上启动2个终端,在终端A中启动服务
ttserver /tmp/casket.tch
在终端B中插入测试数据
tcrmgr put localhost TTTest TestByZLJ
在终端B中查询刚刚插入的测试数据
tcrmgr get localhost TTTest
在终端B中备份数据库文件
tcrmgr copy localhost /tmp/backup.tch
模拟服务down掉,在终端A中按下ctrl-c键
模拟数据库文件丢失,在终端A中删除数据库文件
rm /tmp/casket.tch
还原数据库文件
cp /tmp/backup.tch /tmp/casket.tch
在终端A中重新启动服务
ttserver /tmp/casket.tch
在终端B中检索数据
tcrmgr get localhost TTTest
最后我们得到的结果还是:TestByZLJ,说明成功的还原了数据
以上只是通过简单的文件复制完成了数据备份与还原,这种方法有它的缺点就是,在上面的文件备份过程中更新的数据有可能就得不到还原。下面将通过另外一个功能解决以上的缺点
在mysql 可以通过binary log的方式恢复数据,oracle也有redo log的方式恢复数据,
tt同样也有通过更新log的方式恢复数据,也就是说,所有对db的更新操作在log中都有操作记录,通过tt自有的log还原数据机制能把数据还原回来。
下面通过简单的实例进行测试:
在同一台机器上启动2个终端,建立一个目录用来保持log
mkdir /tmp/ulog
在终端A中启动服务ttserver -ulog /tmp/ulog /tmp/casket.tch
在终端B中插入测试数据
tcrmgr put localhost TTTest TestByZLJ
在终端B中查询刚刚插入的测试数据
tcrmgr get localhost TTTest
模拟服务down掉,在终端A中按下ctrl-c键
模拟数据库文件丢失,在终端A中删除数据库文件
rm /tmp/casket.tch
备份更新log文件
mv /tmp/ulog /tmp/ulog-back
在终端A中重新启动服务
ttserver /tmp/casket.tch
通过更新log还原数据
tcrmgr restore localhost /tmp/ulog-back
在终端B中检索数据
tcrmgr get localhost TTTest
最后我们得到的结果还是:TestByZLJ,说明成功的还原了数据。
它有个缺点:每次操作都有log记录,慢慢的文件就会变得越来越大,很容易磁盘用尽,可以通过备份数据库文件和保存部分更新log文件,两者一起解决这个问题,具体做法:定期备份数据文件和更新log,对很老的备份更新log进行删除,当需要还原数据时,先通过还原备份数据库文件,由于在还原数据时写入的数据会写更新log文件,还原后再通过更新log文件
进行还原数据库时写入的数据,就可以完全的还原数据,具体做法看下图

php操作Tokyo Cabinet与操作memcache效率比较

Posted: 2009年4月22日星期三
先说我的服务器环境,1G内存,双核Xeon 2.00的CPU,服务器采用rpm方式部署apahce,php
Tokyo Cabinet的安装方法及PHP操作Tokyo Cabinet方法请见上篇

在测试之前,先安装一个php模块--Benchmark,安装方法如下
/usr/local/php/bin/pear install Benchmark

下面写一个脚本分别对tokyo cabinet进行一万次插入,一万次查询,一万次更新
一万次删除操作
脚本的内容如下

include_once( 'Benchmark/Timer.php' );
$timer = new Benchmark_Timer();
include_once( 'Net/TokyoTyrant.php' );
$tt = new Net_TokyoTyrant();
$tt->connect( 'localhost', 1978 );
$timer->start();
for ( $i = 0; $i < 10000; $i++) $tt->put( 'test_'.$i, $i );
$timer->setMarker('TOKYO CABINET - INSERT 10,000 RECOREDS');
for ( $i = 0; $i < 10000; $i++) $tt->get( 'test_'.$i );
$timer->setMarker('TOKYO CABINET - SELECT 10,000 RECOREDS');
for ( $i = 0; $i < 10000; $i++) $tt->put( 'test_'.$i, $i );
$timer->setMarker('TOKYO CABINET - UPDATE 10,000 RECOREDS');
for ( $i = 0; $i < 10000; $i++) $tt->out( 'test_'.$i );
$timer->setMarker('TOKYO CABINET - DELETE 10,000 RECOREDS');
$timer->stop();
$timer->display();
$tt->close();
?>

执行脚本得到的结果如下图


下面对memcache进行测试,为测试方便在同一台机器上执行一下脚步
memcached -d -m 256 -l 127.0.0.1 -p 11211 -u root
以root用户对memcahe分配256M的内存,分配的端口号为11211
下面再写一个脚本分别对memcahe进行一万次插入,一万次查询,一万次更新
一万次删除操作,脚本内容如下:

include_once( 'Benchmark/Timer.php' );
$timer = new Benchmark_Timer();
$memcache = new Memcache;
$memcache->connect('localhost', 11211);
$timer->start();
for ( $i = 0; $i <10000; $i++ ) $memcache->set( 'test_'.$i, $i );
$timer->setMarker('MEMCACHE - INSERT 10,000 RECOREDS');
for ( $i = 0; $i <10000; $i++ ) $memcache->get( 'test_'.$i );
$timer->setMarker('MEMCACHE - SELECT 10,000 RECOREDS');
for ( $i = 0; $i <10000; $i++ ) $memcache->replace( 'test_'.$i, $i );
$timer->setMarker('MEMCACHE - UPDATE 10,000 RECOREDS');
for ( $i = 0; $i <10000; $i++ ) $memcache->delete( 'test_'.$i );
$timer->setMarker('MEMCACHE - DELETE 10,000 RECOREDS');
$timer->stop();
$timer->display();
$memcache->close();

?>

执行的结果如下:


从上面测试的结果来看,tokyo cabinet的速度非常快,比memcahe稍差。
在执行1万次操作所花费的时间在1.2s左右,而memcahe所花的时间比tokyo cabinet快了0.2秒,但是memcache down掉后数据全部丢失,而tokyo cabinet即使重启了,db文件不坏掉,数据就不会丢失。

PHP操作tokyo Cabinet

Posted:
上篇我介绍了tokyo Cabinet,这篇我介绍通过php操作tokyo cabinet。需要的工具有php扩展模块Net_Tokyo_Tyrant,Tokyo Tyrant。

首先安装Tokyo Cabinet,安装方法

curl -O http://tokyocabinet.sourceforge.net/tokyocabinet-1.4.16.tar.gz
./configure
make
make install

安装tokyotyrant

curl -O http://tokyocabinet.sourceforge.net/tyrantpkg/tokyotyrant-1.1.23.tar.gz
./configure
make
make install


为php添加Net_Tokyo_Tyrant模块

/usr/local/php/bin/pear channel-discover openpear.org
/usr/local/php/bin/pear install openpear/Net_TokyoTyrant-beta

现为beta版,当有正式版请使用

/usr/local/php/bin/pear install openpear/Net_TokyoTyrant


启动服务

/usr/local/sbin/ttservctl start

说明:启动后的监听的端口为1978

编写php文件

include_once 'Net/TokyoTyrant.php';
$tt = new Net_TokyoTyrant();
$tt->connect( 'localhost', 1978 );
$tt->put('test', 'PHP connet to Tokyo cabinet');
echo $tt->get('test');

$tt->close();
?>

执行刚刚的php文件,你将看到如下的文字
PHP connet to Tokyo cabinet
以上就完成第一个php对Tokyo cabinet的操作
当在memcache中保存数据时,重启memcache服务,所有的数据全部丢失
当在tokyo cabinet中保存数据时,服务器重启数据不丢失。
下面通过一个例子证明这点
/usr/local/sbin/ttservctl restart
编写php文件

include_once 'Net/TokyoTyrant.php';
$tt = new Net_TokyoTyrant();
$tt->connect( 'localhost', 1978 );
//$tt->put('test', 'PHP connet to Tokyo cabinet');
echo $tt->get('test');

$tt->close();
?>

执行php脚本,得到的结果还是
PHP connet to Tokyo cabinet
说明它的数据全部保存在磁盘上而不是内存中。
下期将推出,比较memcache与tokyo cabinet的执行效率

Tokyo Cabinet介绍

Posted: 2009年4月20日星期一
Tokyo Cabinet是由一个名叫平林幹雄的日本人开发的一个管理数据库程序库,作者开发了一系列的开源程序。包括:
Tokyo Cabinet
tokyotyrant
QDBM(Quick Database Manager),
Hyper Estraier(a full-text search system for communities),
Estraier(a personal full-text search system)
Diqt:Multilingual Dictionary Searcher等。
现工作于日本的第一大社交网站mixi。
Tokyo Cabinet是一个DBM数据库,在整个数据库中它既没有数据表的概念也没有数据类型的概念,它由一系列的key-value对的记录构成,key和vlaue既可以是二进制数据也可以为字符数据,它们的长度可以是任意长度的字节序列,所有的记录都保存在文件中。所有记录由hash表,b+树或定长的数组组成。
Tokyo Cabinet基于GNU Lesser General Public License协议发布,采用C语言开发,它可以运行在任何支持C99和POSIX平台上使用。
相比一般的DBM数据库有以下几个特点:空间小,效率高,性能高,可靠性高,多种开发语言的支持(现已提供C,Perl,Ruby,Java,Lua的API),支持64位操作系统。
它的官方首页是:http://tokyocabinet.sourceforge.net/index.html
最新版本:tokyocabinet-1.4.14

稍后我将推出他在mixi开发者blog上发表一系列有关于tokyocabinet的文档

Linux硬盘读写能力的测试

Posted: 2009年4月19日星期日
今天对公司的几种类型的服务器分别做了,硬盘读写能力的测试。
测试的机器分别是:

测试的环境:Centos 5.2 x86_64 ,文件系统Ext3。
测试的过程:
先测试
通过以下两个脚本分别对服务器进行10次操作
读测试:

for i in 1 2 3 4 5 6 7 8 9 10;
do
sleep 10;
echo $'\n' $i;
hdparm -tT /dev/sda;
done

得出的结果如下图(单位:MB/sec)



看不清楚,请点击,查看大图
写测试

for i in 1 2 3 4 5 6 7 8 9 10;
do
sleep 10;
echo $'\n' $i;
dd if=/dev/zero of=/tmp/hdparm_write$i.tmp ibs=1M obs=1M count=1024;
done

说明:
对几个参数进行说明
sleep 10;间隔10S,
ibs=1M 一次读入1M
obs=1M 一次写入1M,
共1024个1M文件,也就是1G
测试的结果如下图(单位:MB/sec

开贴了

Posted: 2009年4月18日星期六
申请了这个博客很久了,一直没有好好利用它,原本打算自己买台主机空间搭建一个blog,发现在国内架个blog还得申请icp认证,真麻烦。没有办法,还是好好利用免费的博客空间。从网上下个模版,稍微修改一下,就搭建了一个blog平台。今天开始发表自己的文章到blog,尽量做到不转贴,希望得到大家的支持,多多交流。