分类目录归档:centos/nginx/apache

LNMP下为Nginx目录设置访问验证的用户名密码[转vpser.net]

有时候需要象Apache那样为指定的目录添加访问验证,一般在Apache下使用htpasswd来添加,而htpasswd是包含在apache2-utils里,一般LNMP一键安装包或自己编译安装LNMP都不会安装apache2-utils。

1、创建类htpasswd文件

执行:wget -c soft.vpser.net/lnmp/ext/htpasswd.sh;bash htpasswd.sh

按提示输入用户名、密码、及认证文件名。脚本会自动生成认证文件。记录下脚本返回的文件路径。如:/usr/local/nginx/conf/vpser.net.auth。

2、为Nginx添加auth认证配置

下面是以某域名下面的soft目录为例,在域名的server段里加上如下代码:
location ^~ /soft/
{
auth_basic “Authorized users only”;
auth_basic_user_file 这里写前面脚本返回的文件路径;
}

Authorized users only为提示信息,可以修改成自己想让他提示的信息;auth_basic_user_file 后面需要填htpasswd.sh脚本返回的人家文件的路径。按上面的提示修改好配置后,重启nginx,访问 http://yourdomainname/soft/ 就会提示输入用户名和密码。

注意,加上认证之后该目录下的PHP将不会被解析,会出现下载提示,如果想可以解析PHP可以将上面的配置改为:

location ^~ /soft/ {
location ~ .*\.(php|php5)?$ {
fastcgi_pass unix:/tmp/php-cgi.sock;
fastcgi_index index.php;
include fcgi.conf;
}
auth_basic “Authorized users only”;
auth_basic_user_file 这里写前面脚本返回的文件路径;
}

改进了公司的php开发流程

目前公司的开发流程是开发人员工作机win7 ,一台开发服务器,安装xen虚拟化,虚拟出n台vps,所有的vps安装centos + nginx + mysql + php-fpm 。每人一台vps或每个项目一台vps,通过samba做共享,开发机磁盘映射的方式进行远程开发。但这样做硬件资源上太过浪费,还一个问题是对网络硬盘提交svn时经常出现冲突及需要清理的问题,还经常在win下无法清理,需要进行ssh进行操作,比较麻烦。所以对公司的开发流程做出了一些改动!

开发环境 192.168.1.152这台vps运行php-fpm 开发人员win7运行nginx for win,并把每个win7的程序根目录共享出去,152 vps 按ip不同挂载所有开发人员的共享目录。 使nginx for win 远程调用152上的fast-cgi解析php.

这样,采用一台vps就可以为公司所有的开发人员提供php解析服务。win7电脑上无需安装php、php拓展或是php方面的设置,非常方便进行开发调试
当win7 svn ci操作时,svn服务器通过钩子脚本,自动对152(整合开发环境)及146(测试环境)二台vps进行svn up操作,这样多人同时开发时,直接localhost就可以看到自己开发时的效果,提交svn就可以在152上看到完整的效果了。

利用svn的钩子脚本实现测试服务器代码的即时更新

在使用svn钩子脚本之前,各个开发人员的开发环境中的代码采用svn进行管理,在测试环境中,每天由程序员手动svn up来更新测试环境中的代码,比较繁琐。

今天在svn服务器中使用了钩子脚本,开发人员每次ci操作都会自动调用该脚本实现测试环境中的svn up,因为公司的svn服务器与测试环境为同一台服务器,所以比较好操作

svn项目下面有hooks目录,里面存放的是全部的钩子脚本的模板

post-commit.tmpl 为客户端commit提交后触发

vi post-commit

[codesyntax lang=”bash”]

#!/bin/sh
WEB=/home/www/yefmanage
export LANG=en_US.UTF-8
svn update $WEB --username test --password test

[/codesyntax]

chmod 777 post-commit

测试一下,看脚本是否有权限问题

./post-commit

正常的话,就ok了!以后每次客户端操作,自动运行该脚本

php5使用autoload实现类的自动加载

常州这边的公司用的框架是09年写的,二年了,所以有了重写的冲动!

新版框架采用php5的autoload类自动加载机制,使应用开发时无需require相应的文件,非常爽

[codesyntax lang=”php”]

/**
 *
 * php5自动加载类功能函数
 * @param string $class_name
 */
function loader($class_name){
	$expandCfg=cfg('expand');
	if(!empty($expandCfg) && in_array($class_name,array_keys($expandCfg))){
		$classFile=$expandCfg[$class_name];
	}else{
		$classArr = preg_split("/(?=[A-Z])/", $class_name);
		$classSysArr=array('dao','module','base','core','parent');
		$classArrLast=strtolower($classArr[count($classArr)-1]);
		if(in_array($classArrLast, $classSysArr)){
			if('base'==$classArrLast || 'core'==$classArrLast){
				$classFile=CORE_PATH.strtolower($classArr[0]).'.'.$classArrLast.'.class.php';
			}elseif('parent'==$classArrLast){
				$classFile=SITE_PATH.$classArrLast.'/'.strtolower($classArr[0]).'.'.$classArrLast.'.class.php';
			}else{
				$classFile=INCLUDE_PATH.$classArrLast.'/'.strtolower($classArr[0]).'/'.strtolower($classArr[0]).'.'.strtolower($classArr[1]).'.'.strtolower($classArr[2]).'.class.php';
			}
			//debug($classFile);

		}
		unset($classArr,$classArrLast);
	}
	if(isset($classFile) && file_exists($classFile)){
		include($classFile);
	}
}

spl_autoload_register('loader');

[/codesyntax]

另框架在上线后,自动把运行时的错误信息存log文件

[codesyntax lang=”php”]

register_shutdown_function('error_handler');
/**
 *
 * 判断当前页是否来自ajax提交
 */
function is_ajax()
{
	if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && trim($_SERVER['HTTP_X_REQUESTED_WITH']) == 'XMLHttpRequest'){
		return true;
	}else{
		return false;
	}
}

function error_handler() {
    if(isset($run_count) && $run_count === 1)
        return false;
    static $run_count = 1;
    //  获取错误信息
    $error_array = error_get_last();
    // 对notice级的错误进行清除
    if($error_array['type'] == 8) {
        $error_array = array();
    }
    if(empty($error_array) === false) {
        $url = htmlspecialchars($_SERVER['REQUEST_URI']);  // 当前请求访问url地址,
        $date = date('Y-m-d H:i:s',time());  // 当前时间
        $error = implode(' | ',$error_array);  // 将错误代码全部转化为数据.
        file_put_contents(PATH.'/log/error'.date('Y_m_d').'.txt',"$date|$url,$error; \r\n",FILE_APPEND);  // 写入日志文件中. 保护一行一条, 并且循环增加开启.
    }
}

[/codesyntax]

使用Varnish代替Squid做网站缓存加速器的详细解决方案[转]

我曾经写过一篇文章──《初步试用Squid的替代产品──Varnish Cache网站加速器》,但当时仅仅是用着玩,没做深入研究。

今天写的这篇关于Varnish的文章,已经是一篇可以完全替代Squid做网站缓存加速器的详细解决方案了。网上关于Varnish的资料很少,中文资料更是微乎其微,希望本文能够吸引更多的人研究、使用Varnish。

在我看来,使用Varnish代替Squid的理由有三点:
1、Varnish采用了“Visual Page Cache”技术,在内存的利用上,Varnish比Squid具有优势,它避免了Squid频繁在内存、磁盘中交换文件,性能要比Squid高。
2、Varnish的稳定性还不错,我管理的一台图片服务器运行Varnish已经有一个月,没有发生过故障,而进行相同工作的Squid服务器就倒过几次。
3、通过Varnish管理端口,可以使用正则表达式快速、批量地清除部分缓存,这一点是Squid不能具备的。

点击在新窗口中浏览此图片


下面来安装Varnish网站缓存加速器(Linux系统):
1、创建www用户和组,以及Varnish缓存文件存放目录(/var/vcache):

/usr/sbin/groupadd www -g 48
/usr/sbin/useradd -u 48 -g www www
mkdir -p /var/vcache
chmod +w /var/vcache
chown -R www:www /var/vcache

2、创建Varnish日志目录(/var/logs/):

mkdir -p /var/logs
chmod +w /var/logs
chown -R www:www /var/logs

3、编译安装varnish:

wget http://blog.s135.com/soft/linux/varnish/varnish-1.1.2.tar.gz
tar zxvf varnish-1.1.2.tar.gz
cd varnish-1.1.2
./configure –prefix=/usr/local/varnish
make && make install

4、创建Varnish配置文件:

vi /usr/local/varnish/vcl.conf

输入以下内容:

引用
backend myblogserver {
set backend.host = “192.168.0.5”;
set backend.port = “80”;

acl purge {
“localhost”;
“127.0.0.1”;
“192.168.1.0”/24;
}

sub vcl_recv {
if (req.request == “PURGE”) {
if (!client.ip ~ purge) {
error 405 “Not allowed.”;
}
lookup;
}

if (req.http.host ~ “^blog.s135.com”) {
set req.backend = myblogserver;
if (req.request != “GET” && req.request != “HEAD”) {
pipe;
}
else {
lookup;
}
}
else {
error 404 “Zhang Yan Cache Server”;
lookup;
}
}

sub vcl_hit {
if (req.request == “PURGE”) {
set obj.ttl = 0s;
error 200 “Purged.”;
}
}

sub vcl_miss {
if (req.request == “PURGE”) {
error 404 “Not in cache.”;
}
}

sub vcl_fetch {
if (req.request == “GET” && req.url ~ “\.(txt|js)$”) {
set obj.ttl = 3600s;
}
else {
set obj.ttl = 30d;
}
}

这里,我对这段配置文件解释一下:
(1)、Varnish通过反向代理请求后端IP为192.168.0.5,端口为80的web服务器;
(2)、Varnish允许localhost、127.0.0.1、192.168.0.***三个来源IP通过PURGE方法清除缓存;
(3)、Varnish对域名为blog.s135.com的请求进行处理,非blog.s135.com域名的请求则返回“Zhang Yan Cache Server”;
(4)、Varnish对HTTP协议中的GET、HEAD请求进行缓存,对POST请求透过,让其直接访问后端Web服务器。之所以这样配置,是因为POST请求一般是发送数据给服务器的,需要服务器接收、处理,所以不缓存;
(5)、Varnish对以.txt和.js结尾的URL缓存时间设置1小时,对其他的URL缓存时间设置为30天。

5、启动Varnish

ulimit -SHn 51200
/usr/local/varnish/sbin/varnishd -n /var/vcache -f /usr/local/varnish/vcl.conf -a 0.0.0.0:80 -s file,/var/vcache/varnish_cache.data,1G -g www -u www -w 30000,51200,10 -T 127.0.0.1:3500 -p client_http11=on

6、启动varnishncsa用来将Varnish访问日志写入日志文件:

/usr/local/varnish/bin/varnishncsa -n /var/vcache -w /var/logs/varnish.log &

7、配置开机自动启动Varnish

vi /etc/rc.local

在末尾增加以下内容:

引用
ulimit -SHn 51200
/usr/local/varnish/sbin/varnishd -n /var/vcache -f /usr/local/varnish/vcl.conf -a 0.0.0.0:80 -s file,/var/vcache/varnish_cache.data,1G -g www -u www -w 30000,51200,10 -T 127.0.0.1:3500 -p client_http11=on
/usr/local/varnish/bin/varnishncsa -n /var/vcache -w /var/logs/youvideo.log &

8、优化Linux内核参数

vi /etc/sysctl.conf

在末尾增加以下内容:

引用
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.ip_local_port_range = 5000    65000

再看看如何管理Varnish:
1、查看Varnish服务器连接数与命中率:

/usr/local/varnish/bin/varnishstat

点击在新窗口中浏览此图片

2、通过Varnish管理端口进行管理:
用help看看可以使用哪些Varnish命令:

/usr/local/varnish/bin/varnishadm -T 127.0.0.1:3500 help
引用
Available commands:
ping [timestamp]
status
start
stop
stats
vcl.load
vcl.inline
vcl.use
vcl.discard
vcl.list
vcl.show
param.show [-l] []
param.set
help [command]
url.purge
dump.pool

3、通过Varnish管理端口,使用正则表达式批量清除缓存:
(1)、例:清除类似http://blog.s135.com/a/zhangyan.html的URL地址):

/usr/local/varnish/bin/varnishadm -T 127.0.0.1:3500 url.purge /a/

(2)、例:清除类似http://blog.s135.com/tech的URL地址:

/usr/local/varnish/bin/varnishadm -T 127.0.0.1:3500 url.purge w*$

(3)、例:清除所有缓存:

/usr/local/varnish/bin/varnishadm -T 127.0.0.1:3500 url.purge *$

4、一个清除Squid缓存的PHP函数(清除Varnish缓存同样可以使用该函数,无需作任何修改,十分方便):

  1. <?php
  2. function purge($ip, $url)
  3. {
  4. $errstr = ”;
  5. $errno = ”;
  6. $fp = fsockopen ($ip, 80, $errno, $errstr, 2);
  7. if (!$fp)
  8. {
  9. return false;
  10. }
  11. else
  12. {
  13. $out = “PURGE $url HTTP/1.1\r\n”;
  14. $out .= “Host:blog.s135.com\r\n”;
  15. $out .= “Connection: close\r\n\r\n”;
  16. fputs ($fp, $out);
  17. $out = fgets($fp , 4096);
  18. fclose ($fp);
  19. return true;
  20. }
  21. }
  22. purge(“192.168.0.4”, “/index.php”);
  23. ?>

附1:Varnish官方网站:http://www.varnish-cache.org/

附2:2007年12月10日,我写了一个每天0点运行,按天切割Varnish日志,生成一个压缩文件,同时删除上个月旧日志的脚本(/var/logs/cutlog.sh):
/var/logs/cutlog.sh文件内容如下:

引用
#!/bin/sh
# This file run at 00:00
date=$(date -d “yesterday” +”%Y-%m-%d”)
pkill -9 varnishncsa
mv /var/logs/youvideo.log /var/logs/${date}.log
/usr/local/varnish/bin/varnishncsa -n /var/vcache -w /var/logs/youvideo.log &
mkdir -p /var/logs/youvideo/
gzip -c /var/logs/${date}.log > /var/logs/youvideo/${date}.log.gz
rm -f /var/logs/${date}.log
rm -f /var/logs/youvideo/$(date -d “-1 month” +”%Y-%m*”).log.gz

设置在每天00:00定时执行:

/usr/bin/crontab -e

或者

vi /var/spool/cron/root

输入以下内容:

引用
0 0 * * * /bin/sh /var/logs/cutlog.sh

采用日志的形式,做memcache主到从的同步

需求:多台memcache共同工作,一台memcache服务器为主服务器A 其它的memcache服务器为B,C,D…

后台对memcache进行delete及set操作时,把操作命令存至redis或是其它媒介中,采用redis lists 做一简单的队阵方式保存操作的命令,也就是把A的日志记录压入队阵中

然后服务器跑一php的脚本,不停的循环从redis 中弹出A的命令日志,最后,把命令给B,C,D等从服务器执行,这样就达到了主从一至的要求。

目前只是简单的想法,准备找时间深入一下,弄一个主从备份的脚本,并且加上主从切换的功能。

linux下配置mongodb,无需编译!

1.认识及了解MongoDB

MongoDB 是一个面向集合的,模式自由的文档型数据库.

面向集合, 意思是数据被分组到若干集合,这些集合称作聚集(collections). 在数据库里每个聚集有一个唯一的名字,可以包含无限个文档. 聚集是RDBMS中表的同义词,区别是聚集不需要进行模式定义.
模式自由, 意思是数据库并不需要知道你将存入到聚集中的文档的任何结构信息.实际上,你可以在同一个聚集中存储不同结构的文档.
文档型, 意思是我们存储的数据是键-值对的集合,键是字符串,值可以是数据类型集合里的任意类型,包括数组和文档. 我们把这个数据格式称作 "[BSON]" 即 "Binary Serialized dOcument Notation."


集 文档数据库,键值对存储和关系型数据库的优点于一身.

MongoDB (名称来自"humongous") 是一个可扩展的,高性能,开源,模式自由,面向文档的数据库.使用C++编写,MongoDB特点:

    *     面向文档存储(类JSON数据模式简单而强大)

    *      动态查询

    *      全索引支持,扩展到内部对象和内嵌数组

    *      查询记录分析

    *      快速,就地更新

    *      高效存储二进制大对象 (比如照片和视频)

    *      复制和故障切换支持

    *     Auto- Sharding自动分片支持云级扩展性

    *      MapReduce 支持复杂聚合

    *      商业支持,培训和咨询

所 谓"面向集合"(Collenction-Orented),意思是数据被分组存储在数据集中, 被称为一个集合(Collenction)。每个集合在数据库中都有一个唯一的标识名,并且可以包含无限数目的文档。集合的概念类似关系型数据库 (RDBMS)里的表(table),不同的是它不需要定义任何 模式(schema)。
模式自由(schema-free),意味着对于存储在mongodb数据库中的文件,我们不需要知道它的任何结构定义。如果需要的话,你完全可以把不同 结构的文件存储在同一个数据库里。
存储在集合中的文档,被存储为键-值对的形式。键用于唯一标 识一个文档,为字符串类型,而值则可以是各种复杂的文件类型。我们称这种存储形式为 BSON(Binary Serialized dOcument Format)。

哪些公司在用MongoDB
sourceforge、github等。

MongoDB 有个缺点,存储的数据占用空间过大。

MongoDB的主要目标是在键/值存储方式(提供了高性能和高度伸缩性)以及传统的RDBMS系统 (丰富的功能)架起一座桥梁,集两者的优势于一身。根据官方网站的描述,Mongo 适合用于以下场景:

    * 网站数据:Mongo非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。
    * 缓存:由于性能很高,Mongo也适合作为信息基础设施的缓存层。在系统重启之后,由Mongo搭建的持久化缓存层可以避免下层的数据源过载。
    * 大尺寸,低价值的数据:使用传统的关系型数据库存储一些数据时可能会比较昂贵,在此之前,很多时候程序员往往会选择传统的文件进行存储。
    * 高伸缩性的场景:Mongo非常适合由数十或数百台服务器组成的数据库。Mongo的路线图中已经包含对MapReduce引擎的内置支持。
    * 用于对象及JSON数据的存储:Mongo的BSON数据格式非常适合文档化格式的存储及查询。

自然,MongoDB的使用也会有 一些限制,例如它不适合:

    * 高度事务性的系统:例如银行或会计系统。传统的关系型数据库目前还是更适用于需要大量原子性复杂事务的应用程序。
    * 传统的商业智能应用:针对特定问题的BI数据库会对产生高度优化的查询方式。对于此类应用,数据仓库可能是更合适的选择。
    * 需要SQL的问题
Via:http://www.infoq.com/cn/news/2009/09/mongodb

性能

在 我的使用场合下,千万级别的文档对象,近10G的数据,对有索引的ID的查询不会比mysql慢,而对非索引字段的查询,则是全面胜出。 mysql实际无法胜任大数据量下任意字段的查询,而mongodb的查询性能实在让我惊讶。写入性能同样很令人满意,同样写入百万级别的数 据,mongodb比我以前试用过的couchdb要快得多,基本10分钟以下可以解决。补上一句,观察过程中mongodb都远算不上是CPU杀手。
Via:http://www.wentrue.net/blog/?p=772

2. 安装及配置
说明,MongoDB下载然后解压缩以后就可以直接使用了,不需要编译及安装。

在页面http://www.mongodb.org/display/DOCS/Downloads中找到适合于你所在操作系统的MongoDB版本。

[root@CentOS_Test_Server software]# wget http://downloads.mongodb.org/linux/mongodb-linux-i686-1.4.2.tgz

/home/software是存放软件的目录,把mongodb解压到其它的目录下

直接解压缩到目录/usr/local/webserver 下。
[root@CentOS_Test_Server software]# tar zxvf mongodb-linux-i686-1.4.2.tgz -C /usr/local/webserver/

[root@CentOS_Test_Server webserver]# ls
eaccelerator_cache  mongodb-linux-i686-1.4.2  mysql  nginx  php  squid

将目录改名,方便以后使用方便。
[root@CentOS_Test_Server webserver]# mv mongodb-linux-i686-1.4.2/ mongodb

[root@CentOS_Test_Server software]# cd /usr/local/webserver/mongodb
[root@CentOS_Test_Server mongodb]# ls
bin  GNU-AGPL-3.0  include  lib  README  THIRD-PARTY-NOTICES

直接查看README文件的内容,里面的说明对使用MongoDB也会很有帮助。
[root@CentOS_Test_Server mongodb]# more README

MongoDB
=======

Welcome to MongoDB!

Package Contents
—————-

  bin/mongod            – MongoDB server
  bin/mongo             – MongoDB client

  bin/mongodump         – MongoDB dump tool – for backups, snapshots, etc..
  bin/mongorestore      – MongoDB restore a dump
  bin/mongoexport       – Export a single collection to test (json,csv)
  bin/mongoimportjson   – Import a json file into a collection

  bin/mongofiles        – Utility for putting and getting files from MongoDB gridfs

Useful Resources
—————-

 MongoDB Website

 * http://www.mongodb.org/

Documentation

 * http://www.mongodb.org/display/DOCS/Documentation

 MongoDB Maillists & IRC

 * http://www.mongodb.org/display/DOCS/Community

如果直接输入命令./mongod,则 MongoDB的数据直接保存在/data/db目录(windows操作系统下是c:\data\db目录), 默认监听在27017端口。
如 果你启动MongoDB时没有指定任何参数,同时目录/data/db也不存在,则会报错。

[root@CentOS_Test_Server bin]# ./mongod –help | grep fork
  –fork                    fork server process
[root@CentOS_Test_Server bin]# ./mongod –help | grep dbpath
  –dbpath arg (=/data/db/) directory for datafiles
                            dbpath
  –fastsync            indicate that this instance is starting from a dbpath
[root@CentOS_Test_Server bin]# ./mongod –help | grep port
  –port arg                specify port number
  –source arg          when slave: specify master as <server:port>

运 行./mongod –help命令时mongodb提示了一下,也就是32位操作系统只支持最大2G的文件,如果你的应用中数据量很大,超过了2G,推荐安装64位的操作 系统。2Gb or Not 2Gb – File limits说明 了为什么32位操作系统只支持最大2G的文件。

[root@CentOS_Test_Server bin]# ./mongod –help | more

** NOTE: when using MongoDB 32 bit, you are limited to about 2 gigabytes of data
**       see http://blog.mongodb.org/post/137788967/32-bit-limitations for more

创建目录保存MongoDB数据的目录。
[root@CentOS_Test_Server bin]# mkdir /home/mongodb_data

启动MongoDB

[root@CentOS_Test_Server bin]# ./mongod –fork –dbpath=/home/mongodb_data –logpath /home/mongodb_data/mongodb.log –logappend
all output going to: /home/mongodb_data/mongodb.log
forked process: 3799

[root@CentOS_Test_Server bin]# ps aux | grep mongo
root      3799  0.0  0.7  59032  2008 ?        Ssl  16:59   0:00 ./mongod –fork –dbpath=/home/mongodb_data –logpath /home/mongodb_data/mongodb.log –logappend
root      3825  0.0  0.2   3920   628 pts/1    S+   17:00   0:00 grep mongo

[root@CentOS_Test_Server bin]# netstat -antl | grep 27017
tcp        0      0 0.0.0.0:27017               0.0.0.0:*                   LISTEN

停止 MongoDB的进程时不能用kill -9,而最好用kill -15,否则会导致出现问题。

Sending a Unix INT or TERM signal

You can cleanly stop mongod using a SIGINT or SIGTERM signal on Unix-like systems. Either ^C, "kill -2 PID," or kill -15 PID will work.

Please note that sending a KILL signal kill -9 will probably cause damage as mongod will not be able to cleanly exit.  (In such a scenario, run the repairDatabase command.)


同时会自动启动一个端口为28017的服务,此服务用于监控MongoDB的状态
[root@CentOS_Test_Server bin]# netstat -a | grep 28017
tcp        0      0 *:28017                     *:*                         LISTEN

用curl可以在启动MongoDB所在的服务器上面直接访问, 如果想从其它的访问访问此服务,则必须在防火墙上开放28017端口。
[root@CentOS_Test_Server bin]# curl localhost:28017
<html><head><title>mongodb CentOS_Test_Server:27017 </title></head><body><h2>mongodb CentOS_Test_Server:27017 </h2><p>
<pre>db version v1.4.2, pdfile version 4.5
git hash: 53749fc2d547a3139fcf169d84d58442778ea4b0
sys info: Linux domU-12-31-39-01-70-B4 2.6.21.7-2.fc8xen #1 SMP Fri Feb 15 12:39:36 EST 2008 i686 BOOST_LIB_VERSION=1_37
…..

我在服务器上打开了28017端口,不知道为什么 在其它的电脑上面输入地址http://192.168.1.111:28017/无法访问,暂时不知道是什么原因。
[root@CentOS_Test_Server bin]# iptables -A RH-Firewall-1-INPUT -p tcp -m state –state NEW -m tcp –dport 28017 -j ACCEPT
[root@CentOS_Test_Server bin]# /etc/init.d/iptables save
Saving firewall rules to /etc/sysconfig/iptables:          [  OK  ]

更多MongoDB启动的问题,请移步 Starting and Stopping Mongo,http://www.mongodb.org/display/DOCS/Starting+and+Stopping+Mongo

3. 测试
[root@CentOS_Test_Server bin]# ls
运行MongoDB下面bin目录下的mongo命 令,就可以进入MongoDB的shell界面了,跟MySQL有点类似,输入命令help,其它的看帮助基本上就明白了。
mongo  mongod  mongodump  mongoexport  mongofiles  mongoimport  mongorestore  mongos  mongosniff  mongostat
[root@CentOS_Test_Server bin]# ./mongo
MongoDB shell version: 1.4.2
url: test
connecting to: test
type "help" for help
> help
HELP
        show dbs                     show database names
        show collections             show collections in current database
        show users                   show users in current database
        show profile                 show most recent system.profile entries with time >= 1ms
        use <db name>                set curent database to <db name>
        db.help()                    help on DB methods
        db.foo.help()                help on collection methods
        db.foo.find()                list objects in collection foo
        db.foo.find( { a : 1 } )     list objects in foo where a == 1
        it                           result of the last line evaluated; use to further iterate

在MongoDB中,在使用Database或Collection前不需要提前创建,在使用的过程中会 自动创建。
更多的有关信息请移步MongoDB Tutorial

a.测试一
我们来测试一下就明白了
> use recommender //
在此之前我可从来没有创建过数据库recommender
> a={name: "caihuafeng"} //也就是json对象,大家看起来是不是非常熟悉
{ "name" : "caihuafeng" }
> b={website: "1616.net"}
{ "website" : "1616.net" }
> db.data.save(a) //
在此之前我可没有创建过表data,在数据库recommender的表data中保存数据a,可以理解为往MySQL的表data中添加一条记录
> db.data.save(b) //在数据库recommender的表data中保存数据b,可以理解为往MySQL的表data中添加一条记录
> db.data.find()   //显示数据库recommender的表data中的所有数据
{ "_id" : ObjectId("4bee745a0863b1c233b8b7ea"), "name" : "caihuafeng" }
{ "_id" : ObjectId("4bee745f0863b1c233b8b7eb"), "website" : "1616.net" }
> show collections //显示数据库recommender中的所有表(collection在这里相当于MySQL中的表)
data
system.indexes //这个表是自动创建的

显示数据库recommender中website为1616.net的记录,相当于MySQL中的 SELECT * FROM data WHERE website='1616.net';
> db.data.find({website:"1616.net"})
{ "_id" : ObjectId("4bee745f0863b1c233b8b7eb"), "website" : "1616.net" }

显示 数据库recommender中name为caihuafeng的记录,相当于MySQL中的SELECT * FROM data WHEREname ='caihuafeng';
> db.data.find({name:"caihuafeng"})
{ "_id" : ObjectId("4bee745a0863b1c233b8b7ea"), "name" : "caihuafeng" }

MongoDB 比其它的关系型数据库更加灵活,因为每一行的记录都可以有不同的结构,而且表的结构根本上不需要提前创建,灵活极了。

b.测试二
发现就是在写js代码,然后跟数据库结合起来了。
> for (var i = 1; i <= 10; i++) db.data.save({"x":6, "name":"caihuafeng" + i});
> db.data.find();
{ "_id" : ObjectId("4bee745a0863b1c233b8b7ea"), "name" : "caihuafeng" }
{ "_id" : ObjectId("4bee745f0863b1c233b8b7eb"), "website" : "1616.net" }
{ "_id" : ObjectId("4bee804ba23d558eb6687117"), "x" : 6, "name" : "caihuafeng1" }
{ "_id" : ObjectId("4bee804ba23d558eb6687118"), "x" : 6, "name" : "caihuafeng2" }
{ "_id" : ObjectId("4bee804ba23d558eb6687119"), "x" : 6, "name" : "caihuafeng3" }
{ "_id" : ObjectId("4bee804ba23d558eb668711a"), "x" : 6, "name" : "caihuafeng4" }
{ "_id" : ObjectId("4bee804ba23d558eb668711b"), "x" : 6, "name" : "caihuafeng5" }
{ "_id" : ObjectId("4bee804ba23d558eb668711c"), "x" : 6, "name" : "caihuafeng6" }
{ "_id" : ObjectId("4bee804ba23d558eb668711d"), "x" : 6, "name" : "caihuafeng7" }
{ "_id" : ObjectId("4bee804ba23d558eb668711e"), "x" : 6, "name" : "caihuafeng8" }
{ "_id" : ObjectId("4bee804ba23d558eb668711f"), "x" : 6, "name" : "caihuafeng9" }
{ "_id" : ObjectId("4bee804ba23d558eb6687120"), "x" : 6, "name" : "caihuafeng10" }

> var cursor = db.data.find();
> while (cursor.hasNext()) {print(tojson(cursor.next()))};
{ "_id" : ObjectId("4bee745a0863b1c233b8b7ea"), "name" : "caihuafeng" }
{ "_id" : ObjectId("4bee745f0863b1c233b8b7eb"), "website" : "1616.net" }
{
        "_id" : ObjectId("4bee804ba23d558eb6687117"),
        "x" : 6,
        "name" : "caihuafeng1"
}
{
        "_id" : ObjectId("4bee804ba23d558eb6687118"),
        "x" : 6,
        "name" : "caihuafeng2"
}
{
        "_id" : ObjectId("4bee804ba23d558eb6687119"),
        "x" : 6,
        "name" : "caihuafeng3"
}
{
        "_id" : ObjectId("4bee804ba23d558eb668711a"),
        "x" : 6,
        "name" : "caihuafeng4"
}
{
        "_id" : ObjectId("4bee804ba23d558eb668711b"),
        "x" : 6,
        "name" : "caihuafeng5"
}
{
        "_id" : ObjectId("4bee804ba23d558eb668711c"),
        "x" : 6,
        "name" : "caihuafeng6"
}
{
        "_id" : ObjectId("4bee804ba23d558eb668711d"),
        "x" : 6,
        "name" : "caihuafeng7"
}
{
        "_id" : ObjectId("4bee804ba23d558eb668711e"),
        "x" : 6,
        "name" : "caihuafeng8"
}
{
        "_id" : ObjectId("4bee804ba23d558eb668711f"),
        "x" : 6,
        "name" : "caihuafeng9"
}
{
        "_id" : ObjectId("4bee804ba23d558eb6687120"),
        "x" : 6,
        "name" : "caihuafeng10"
}

> db.data.find({x:6}, {name:true}).forEach(function(x) {print(tojson(x));});
{ "_id" : ObjectId("4bee804ba23d558eb6687117"), "name" : "caihuafeng1" }
{ "_id" : ObjectId("4bee804ba23d558eb6687118"), "name" : "caihuafeng2" }
{ "_id" : ObjectId("4bee804ba23d558eb6687119"), "name" : "caihuafeng3" }
{ "_id" : ObjectId("4bee804ba23d558eb668711a"), "name" : "caihuafeng4" }
{ "_id" : ObjectId("4bee804ba23d558eb668711b"), "name" : "caihuafeng5" }
{ "_id" : ObjectId("4bee804ba23d558eb668711c"), "name" : "caihuafeng6" }
{ "_id" : ObjectId("4bee804ba23d558eb668711d"), "name" : "caihuafeng7" }
{ "_id" : ObjectId("4bee804ba23d558eb668711e"), "name" : "caihuafeng8" }
{ "_id" : ObjectId("4bee804ba23d558eb668711f"), "name" : "caihuafeng9" }
{ "_id" : ObjectId("4bee804ba23d558eb6687120"), "name" : "caihuafeng10" }

只取前3条记录,跟MySQL中的limit是类似的意思。
> db.data.find().limit(3);
{ "_id" : ObjectId("4bee745a0863b1c233b8b7ea"), "name" : "caihuafeng" }
{ "_id" : ObjectId("4bee745f0863b1c233b8b7eb"), "website" : "1616.net" }
{ "_id" : ObjectId("4bee804ba23d558eb6687117"), "x" : 6, "name" : "caihuafeng1"

4.MongoDB的主从复制(Master/Slave)配置及测试

主从复制有什么用呢? 比如,在两台服务器上分别部署了MongoDB,当一台出现了问题以后,另外一台可以接管服务,同时也起备份的作用。
MongoDB supports replication of data between servers for failover and redundancy.

MongoDB支持4种形式的复制,推荐用master/slave复制
    *  Master-Slave Replication
    * Replica Pairs
    * Replica Sets
    * Limited Master-Master Replication

All else being equal, master/slave is recommended for MongoDB version 1.4.

与Master及Slave相关的帮助选项
[root@CentOS_Test_Server bin]# ./mongod –help | grep master
  –master              master mode
  –source arg          when slave: specify master as <server:port>
                        master ops to slave

[root@CentOS_Test_Server bin]# ./mongod –help | grep slave
  –slave               slave mode
  –source arg          when slave: specify master as <server:port>
  –only arg            when slave: specify a single database to replicate
  –slavedelay arg      specify delay (in seconds) to be used when applying
                        master ops to slave
  –autoresync          automatically resync if slave data is stale

启动MongoDB的Master服务
[root@CentOS_Test_Server bin]# ./mongod –fork –master –dbpath /home/masterdb/ –port 27018 –logpath /home/masterdb/mongodb.log –logappend
all output going to: /home/masterdb/mongodb.log
forked process: 11463
[root@CentOS_Test_Server bin]# ls /home/masterdb/
local.0  local.ns  mongodb.log  mongod.lock

启动MongoDB的Slave服务
[root@CentOS_Test_Server bin]# ./mongod –fork –slave –source localhost:27018 –autoresync –slavedelay 30 –dbpath /home/slavedb/ –port 27019 –logpath /home/slavedb/mongodb.log –logappend
all output going to: /home/slavedb/mongodb.log
forked process: 11848
[root@CentOS_Test_Server bin]# ls /home/slavedb/
local.0  local.ns  mongodb.log  mongod.lock  _tmp

测试主从复制的功能
登录到 MongoDB的Master服务,插入一条数据
[root@CentOS_Test_Server bin]# ./mongo localhost:27018
MongoDB shell version: 1.4.2
url: localhost:27018
connecting to: localhost:27018/test
type "help" for help
> use recommender
switched to db recommender
> db.data.insert({name: "caihuafeng"})
> db.data.find()
{ "_id" : ObjectId("4beedc31e0e4fff2ce0295f6"), "name" : "caihuafeng" }

登录MongoDB的Slave服务,我们发现刚才保存到Master里面的数据已经复制到Slave了,这正是我们要看到的效果。
[root@CentOS_Test_Server bin]# ./mongo localhost:27019
MongoDB shell version: 1.4.2
url: localhost:27019
connecting to: localhost:27019/test
type "help" for help
> use recommender
switched to db recommender
> db.data.find()
{ "_id" : ObjectId("4beedc31e0e4fff2ce0295f6"), "name" : "caihuafeng" }

我们再看一下Slave服务上面产生的同步日志(/home/slavedb/mongodb.log)
Sun May 16 01:39:29 repl: from host:localhost:27018
Sun May 16 01:39:29 resync: dropping database recommender
Sun May 16 01:39:29 resync: cloning database recommender to get an initial copy
Sun May 16 01:39:29 allocating new datafile /home/slavedb/recommender.ns, filling with zeroes…
Sun May 16 01:39:29 done allocating datafile /home/slavedb/recommender.ns, size: 16MB, took 0.451 secs
Sun May 16 01:39:29 allocating new datafile /home/slavedb/recommender.0, filling with zeroes…
Sun May 16 01:39:31 done allocating datafile /home/slavedb/recommender.0, size: 64MB, took 1.397 secs
Sun May 16 01:39:31 allocating new datafile /home/slavedb/recommender.1, filling with zeroes…
Sun May 16 01:39:31 building new index on { _id: 1 } for recommender.data
Sun May 16 01:39:31 Buildindex recommender.data idxNo:0 { name: "_id_", ns: "recommender.data", key: { _id: 1 } }

为 了让MongoDB的主从服务可以自动启动,可以把下面的两条命令加到/etc/rc.local中。
/usr/local/webserver/mongodb/bin/mongod –fork –master –dbpath /home/masterdb/ –port 27018 –logpath /home/masterdb/mongodb.log –logappend

/usr/local/webserver/mongodb/bin/mongod –fork –slave –source localhost:27018 –autoresync –slavedelay 30 –dbpath /home/slavedb/ –port 27019 –logpath /home/slavedb/mongodb.log –logappend

附:
Sun May 16 00:59:47 waiting for connections on port 27018
Sun May 16 00:59:47 web admin interface listening on port 28018

Sun May 16 01:12:27 waiting for connections on port 27019
Sun May 16 01:12:27 web admin interface listening on port 28019

mongodb的端口为27017时,相应的web admin监听的端口为28017
mongodb 的端口为27018时,相应的web admin监听的端口为28018
mongodb的端口为27019时,相应的web admin监听的端口为28019

找到了一个规律,就是web admin的端口就是将mongodb的端口的第二位改为8,猜测应该是这样的。

http://www.mongodb.org/display/DOCS/Master+Slave
http://www.mongodb.org/display/DOCS/Replication

5.MongoDB的Sharding功能
MongoDB的Sharding功能将在1.6版本中出现,将在2010年7月份发布。

MongoDB has been designed to scale horizontally via an auto-sharding architecture. Auto-sharding permits the development of large-scale data clusters that incorporate additional machines dynamically, automatically accomodate changes in load and data distribution, and ensure automated failover.

Sharding will be production-ready in MongoDB v1.6, estimated to be released in July, 2010. In the meantime, an alpha version of sharding is available in the 1.5.x development branch. Please see the limitations page for progress updates and current restrictions.

http://www.mongodb.org/display/DOCS/Sharding

6. 总结
在 写这篇文章以前,我没有用过MongoDB, 以前简单的看过一些MongoDB的资料,只是有点了解,今天自己动手安装测试了一下以后对MongoDB有了更加深入一点的了解,再学习几天基本上就可 以在项目中实际使用了,比如MongoDB的读写性能也有必要再测试一下,虽然已经有不少人已经测试过了,证明MongoDB的读写性能比MySQL高, 不过功能没有MySQL强。

其实TC的Table Database也能实现一些关系型数据库的功能,也是值得深入研究一下的,其实以前我简单的研究过。Tokyo Cabinet及Tokyo Tyrant的命令行接口

Table Database的特点是支持检索,支持多列字段,支持列索引,性能不如其它结构。
Table Database提供了类似RMDB的存储功能,一个主键可以有多个字段,例如,在RMDB中user表可能会有user_id、name和 password等字段,而在Table Database也提供这种支持。
Via:http://willko.javaeye.com/blog/506728

http://zhliji2.blogspot.com/2009/05/tokyo-cabinetdbm.html

下面的文章也比较精彩,对MongoDB感兴趣的可以看一看。
[译] MongoDB 入门教程:http://chenxiaoyu.org/blog/archives/242
http://www.fuchaoqun.com/2010/01/mongodb-in-action/
http://blog.chenlb.com/2010/05/mongodb-vs-mysql-query-performance.html
http://www.wentrue.net/blog/?p=772
http://www.mikespook.com/index.php/archives/524
http://hi.baidu.com/ywdblog/blog/item/44e02e9bfe5a87bfc8eaf425.html
http://www.infoq.com/cn/news/2009/09/mongodb
MongoDB 1.6 发布:
http://xiexiejiao.cn/database/mongodb-1-6-release.html
http://m.cnblogs.com/66952/1673308.html

MongoDB中文介绍:http://www.mongodb.org/display/DOCSCN/Home
MongoDB文档首 页:
http://www.mongodb.org/display/DOCS/Home

Nginx虚拟主机防Webshell安全检测程序完美版(图)[转]

作者:Rainy fox   来源:http://www.key0.cn/

我们先来看下nginx.conf

  server
  {
    listen       80;
    server_name  www.a.com;
    index index.html index.htm index.php;
    root  /data/htdocs/www.a.com/;

    #limit_conn   crawler  20;   
                            
    location ~ .*\.(php|php5)?
    {     
      #fastcgi_pass  unix:/tmp/php-cgi.sock;
      fastcgi_pass  127.0.0.1:9000;
      fastcgi_index index.php;
      include fcgi.conf;
    }

}

  server
  {
    listen       80;
    server_name  www.b.com;
    index index.html index.htm index.php;
    root  /data/htdocs/www.b.com/;

    #limit_conn   crawler  20;   
                            
    location ~ .*\.(php|php5)?
    {     
      #fastcgi_pass  unix:/tmp/php-cgi.sock;
      fastcgi_pass  127.0.0.1:9000;
      fastcgi_index index.php;
      include fcgi.conf;
    }

}

nginx在80端口接受到访问请求后,会把请求转发给9000端口的php-cgi进行处理

而如果修改php.ini中open_basedir= ../../../../../ ,针对两个不同的网站,www.a.com , www.b.com都会把请求发送给9000处理,而如果先访问www.a.com那么../../../../../就会变成A网站的根目录地址,然后这时候如果你访问www.b.com,那么open_basedir仍然是A网站的根目录,但是对于B来说,又是不允许访问的,所以就造成了,第二个站点打开以后会出现no input files,那么有什么解决办法呢?

我们可以把不同的虚拟主机发送到不同的php-cgi端口进行处理,当然响应的php-fpm配置文件中的open_basedir也不同。。我们来看看怎么配置。。

首先,nginx.conf配置如下

 server
  {
    listen       80;
    server_name  www.a.com;
    index index.html index.htm index.php;
    root  /data/htdocs/www.a.com/;

    #limit_conn   crawler  20;   
                            
    location ~ .*\.(php|php5)?
    {     
      #fastcgi_pass  unix:/tmp/php-cgi.sock;
      fastcgi_pass  127.0.0.1:9000;
      fastcgi_index index.php;
      include fcgi.conf;
    }

}

  server
  {
    listen       80;
    server_name  www.b.com;
    index index.html index.htm index.php;
    root  /data/htdocs/www.b.com/;

    #limit_conn   crawler  20;   
                            
    location ~ .*\.(php|php5)?
    {     
      #fastcgi_pass  unix:/tmp/php-cgi.sock;
      fastcgi_pass  127.0.0.1:9001;
      fastcgi_index index.php;
      include fcgi.conf;
    }

}

注意:www.a.com 的请求发送到9000端口 , www.b.com的请求发送到9001端口,依次类推

nginx配置修改了,相对的,php-fpm.conf也要修改

每个站点建一个conf

A站点

#cp /usr/local/webserver/php/etc/php-fpm.conf /usr/local/webserver/php/etc/www.a.com.conf

#vi /usr/local/webserver/php/etc/www.a.com.conf

找到php_defines,添加

<value name="open_basedir">/data/htdocs/www.a.com:/tmp:/var/tmp</value>

 

B站点

#cp /usr/local/webserver/php/etc/php-fpm.conf /usr/local/webserver/php/etc/www.b.com.conf

#vi /usr/local/webserver/php/etc/www.b.com.conf

找到php_defines,添加

<value name="open_basedir">/data/htdocs/www.b.com:/tmp:/var/tmp</value>

 

找到listen_address,修改为

<value name="listen_address">127.0.0.1:9001</value>   注意这里的端口号

 

最后要修改php-fpm启动脚本

#vi /usr/local/webserver/php/sbin/php-fpm

 

注释掉原来的 #php_fpm_BIN –fpm php_opts,田间

php_fpm_BIN –fpm –fpm-config /usr/local/webserver/php/etc/www.a.com.conf

php_fpm_BIN –fpm –fpm-config /usr/local/webserver/php/etc/www.b.com.conf

启动服务

#/usr/local/webserver/php/sbin/php-fpm restart

查看端口

#netstat -tln

 

开了9000 9001分别处理两个站点请求

两个php-cgi主进程加载不同的conf文件,这样就完美解决了虚拟主机webshell能跨目录的问题

当然,启动之前记得conf里面的max_children,开启php-cgi子进程数,相应要减少一些,以免造成内存不足

REST做api

  REST(Representational State Transfer表述性状态转移)是一种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。REST提出了一些设计概念和准则:   1.网络上的所有事物都被抽象为资源(resource);   2.每个资源对应一个唯一的资源标识(resource identifier);   3.通过通用的连接器接口(generic connector interface)对资源进行操作;   4.对资源的各种操作不会改变资源标识;   5.所有的操作都是无状态的(stateless)。   对于当今最常见的网络应用来说,resource identifier是url,generic connector interface是HTTP,第4条准则就是我们常说的url不变性。这些概念中的resouce最容易使人产生误解。resouce所指的并不是数 据,而是数据+特定的表现形式(representation),这也是为什么REST的全名是Representational State Transfer的原因。举个例子来说,“本月卖得最好的10本书”和“你最喜欢的10本书”在数据上可能有重叠(有一本书即卖得好,你又喜欢),甚至完 全相同。但是它们的representation不同,因此是不同的resource。   REST之所以能够简化开发,是因为其引入的架构约束,比如Rails 1.2中对REST的实现默认把controller中的方法限制在7个:index、show、new、edit、create、update和 destory,这实际上就是对CURD的实现。更进一步讲,Rails(也是当今大部分网络应用)使用HTTP作为generic connector interface,HTTP则把对一个url的操作限制在了4个之内:GET、POST、PUT和DELETE。   REST之所以能够提高系统的可伸缩性,是因为它强制所有操作都是stateless的,这样 就没有context的约束,如果要做分布式、做集群,就不需要考虑context的问题了。同时,它令系统可以有效地使用pool。REST对性能的另 一个提升来自其对client和server任务的分配:server只负责提供resource以及操作resource的服务,而client要根据 resource中的data和representation自己做render。这就减少了服务器的开销。   既然REST有这样的好处,那我们应该义无反顾地拥抱它啊!目前一些大牛(像DHH)都已经开 始投入到了REST的世界,那我们这些人应该做什么或者说思考写什么你呢?我觉得我们应该思考两个问题:   如何使用REST;   REST和MVC的关系。   第一个问题假设REST是我们应该采用的架构,然后讨论如何使用;第二个问题则要说明REST 和当前最普遍应用的MVC是什么关系,互补还是取代?   我们先来谈谈第一个问题,如何使用REST。我感觉,REST除了给我们带来了一个崭新的架构 以外,还有一个重要的贡献是在开发系统过程中的一种新的思维方式:通过url来设计系统的结构。根据REST,每个url都代表一个resource,而 整个系统就是由这些resource组成的。因此,如果url是设计良好的,那么系统的结构就也应该是设计良好的。对于非高手级的开发人员来说,考虑一个 系统如何架构总是一个很抽象的问题。敏捷开发所提倡的Test Driven Development,其好处之一(我觉得是最大的好处)就是可以通过testcase直观地设计系统的接口。比如在还没有创建一个class的时候就 编写一个testcase,虽然设置不能通过编译,但是testcase中的方法调用可以很好地从class使用者的角度反映出需要的接口,从而为 class的设计提供了直观的表现。这与在REST架构中通过url设计系统结构非常类似。虽然我们连一个功能都没有实现,但是我们可以先设计出我们认为 合理的url,这些url甚至不能连接到任何page或action,但是它们直观地告诉我们:系统对用户的访问接口就应该是这样。根据这些url,我们 可以很方便地设计系统的结构。   让我在这里重申一遍:REST允许我们通过url设计系统,就像Test Driven Development允许我们使用testcase设计class接口一样。   OK,既然url有这样的好处,那我们就着重讨论一下如何设计url。网络应用通常都是有 hierarchy的,像棵大树。我们通常希望url也能反映出资源的层次性。比如对于一个blog应用:/articles表示所有的文章, /articles/1表示id为1的文章,这都比较直观。遗憾的是,网络应用的资源结构永远不会如此简单。因此人们常常会问这样一个问 题:RESTful的url能覆盖所有的用户请求吗?比如,login如何RESTful?search如何RESTful?   从REST的概念上来看,所有可以被抽象为资源的东东都可以使用RESTful的url。因此 对于上面的两个问题,如果login和search可以被抽象为资源,那么就可以使用RESTful的url。search比较简单,因为它会返回搜索结 果,因此可以被抽象为资源,并且只实现index方法就可以了(只需要显示搜索结果,没有create、destory之类的东西)。然而这里面也有一个 问题:search的关键字如何传给server?index方法显然应该使用HTTP GET,这会把关键字加到url后面,当然不符合REST的风格。要解决这个问题,可以把每次search看作一个资源,因此要创建create和 index方法,create用来在用户点击“搜索”按钮是通过HTTP POST把关键字传给server,然后index则用来显示搜索结果。这样一来,我们还可以记录用户的搜索历史。使用同样的方法,我们也可以对 login应用REST,即每次login动作是一个资源。   现在,我们来看复杂一些的东东。如何用url表达“category为ruby的 article”?一开始可能想到的是/category/ruby/articles,这种想法很直观。但是我觉得里面的category是不需要的, 我们可以直接把“/ruby”理解为“category是ruby”,也就是说“ruby”出现的位置说明了它指的就是category。OK, /ruby/articles,单单从这个url上看,我们能获得多少关于category的信息呢?显然category隐藏在了url后面,这样做到 底好不好,应该是仁者见仁,智者见智了。对于如何表达category这样的东西,我还没想出很好的方式,大家有什么好idea,可以一起讨论。   另外还有一种url形式,它对应到程序中的继承关系。比如product是一个父类,book 和computer是其子类。那么所有产品的url应该是/products,所有书籍的url应该是/books,所有电脑的url应该是 /computers。这一想法就比较直观了,而且再次验证了url可以帮助我们进行设计的论点。   让我再说明一下我的想法:如果每个用户需求都可以抽象为资源,那么就可以完全使用REST。   由此看来,使用REST的关键是如何抽象资源,抽象得越精确,对REST的应用就越好。因此, 如何改变我们目前根深蒂固的基于action的思想是最重要的。   有了对第一个问题的讨论,第二个问题就容易讨论多了。REST会取代MVC吗?还是彼此是互补 关系(就像AOP对于OOP)?答案是It depends!如果我们可以把所有的用户需求都可以抽象为资源,那么MVC就可以退出历史的舞台了。如果情况相反,那么我们就需要混合使用REST和 MVC。   当然,这是非常理想的论断。可能我们无法找到一种方法可以把所有的用户需求都抽象为资源,因为 保证这种抽象的完整性(即真的是所有需求都可以)需要形式化的证明。而且即使被证明出来了,由于开发人员的能力和喜好不同,MVC肯定也会成为不少人的首 选。但是对于希望拥抱REST的人来说,这些都没有关系。只要你开发的系统所设计的问题域可以被合理地抽象为资源,那么REST就会成为你的开发利器。

写的一个vpn自动重连脚本

XML/HTML代码
  1. #!/bin/sh   
  2. VPN=`ifconfig | grep ppp0`   
  3. #echo $VPN   
  4. if [ -z "$VPN" ]   
  5. then   
  6. pon myvpn   
  7. route add -net 10.10.10.0 netmask 255.255.255.0 dev ppp0   
  8. else   
  9. echo $VPN >/dev/null   
  10. fi  

 

公司内部的服务器连接到外网的vpn ,从而方便进行远程内部访问及操作。内部服务器系统是ubuntu 10.04 server 64位版,外网服务器windows 2003 做vpn服务。linux 中的pptp-linux登陆后需要执行route添加路由才能访问vpn内网。

脚本的意思是监控ppp0连接是否正常,如果没有ppp0接连则自动开启vpn拨号,并把日志写入root邮件 /var/mail/root

脚本编写后放入crontab -e   

* * * * * root /root/vpn.sh