自己写了个linux的打包备份程序

每天cron运行下面的脚本,备份多个web目录和mysql数据库,备份的文件按月分目录保存。

#!/bin/sh
todaystr=`date +%Y-%m-%d`
echo “today:${todaystr}”
month=`date +%Y-%m`
echo “month:${month}”

backuppath=”/opt/case/kbackup/${month}”

# mkdir
if [ ! -d "$backuppath" ]; then
mkdir ${backuppath}
fi
#exit 0

# web code
for var in web1 web4 web5 web6 web7 web8 ; do
echo “– $var”
mypath=”/opt/case/${var}/web”
myfile=”${backuppath}/${todaystr}_web_${var}.tar.gz”
echo $mypath
echo $myfile
tar zcvf $myfile $mypath
done

# mysql db
for var in db1 db2 db3 ; do
echo “– $var”
mypath=”/var/lib/mysql/${var}”
myfile=”${backuppath}/${todaystr}_mysqldb_${var}.tar.gz”
echo $mypath
echo $myfile
tar zcvf $myfile $mypath
done

换个思路——在多前端单一后端的架构中使用proxy

一般来说,apache的proxy有几个用途:

  • 负载均衡:一台server撑不住,通过proxy把业务处理分流到其他server,让网站更强壮;
  • 安全:前台用porxy或者squide挡一下,受到攻击或者黑客的时候让前端的proxy当靶子;
  • 应用整合:让某些目录proxy到其他webserver的其他端口,不同的server整合到同一个域名下。

在最近的一个项目中,同一个网站应用要推送到不同的前端ip和域名上,而且将会分布在几十台物理服务器上,但流量并不高。惯性思维想到的方案是——发布,再发布,不管数据库还是代码,有更新就从新发布到各个服务器上。虽说我们做了很多自动化的脚本,但是这种方式还是会出现一些问题:

  • 繁琐:每次更新完了beta还需要一个冗长的脚本执行过程,而且为了稳妥更新后的效果还需要去每个server上去人工查看;
  • 数据库无法统一,一些应用不好实现:为了让服务更快,不得不在每台server都放上数据库,但是这样,一来,因为mysql遇到直接dump导入就不能用mysql的主从方式,推送大各个server同步时间较长,不稳定;二来,一些用户信息不方便在各个server之间做同步。
  • 配置一台新的服务器需要时间。

在反复的纠结和测试之后,我采用apache的proxy实现了多前端单一后端的架构:

有应用A,B,C

有服务器:

P ->192.168.1.100
Q->192.168.1.101
R->192.168.1.102
S->192.168.1.103
T->192.168.1.104

给应用A分配的域名:

www.a1.com ->192.168.1.101 (Q)
www.a2.com ->192.168.1.101 (Q)
www.a3.com ->192.168.1.102 (R)
www.a4.com ->192.168.1.102 (R)
……

给应用B分配的域名:

www.b1.com ->192.168.1.101 (Q)
www.b2.com ->192.168.1.101 (Q)
www.b3.com ->192.168.1.102 (R)
www.b4.com ->192.168.1.102 (R)
……

以server P(192.168.1.100)为后端:

把A的后端放在P的81端口
把B的后端放在P的82端口
把C的后端放在P的83端口。

给Q,R,S,T的80配置好proxy和rewrite(具体的配置这里不复述,请百度上自己google一下)。

那么针对Q的80端口对应的目录下的.htaccess做如下配置:

RewriteEngine on

# A ——————–
# server  Q (2 sites)
RewriteCond %{HTTP_HOST} ^www.a1.com* [OR]
RewriteCond %{HTTP_HOST} ^www.a2.com*
RewriteRule ^(.*)$ http://192.168.1.100:81/$1 [P,L]
# END A ——————–

# B ——————–
# server  Q (2 sites)
RewriteCond %{HTTP_HOST} ^www.b1.com* [OR]
RewriteCond %{HTTP_HOST} ^www.b2.com*
RewriteRule ^(.*)$ http://192.168.1.100:82/$1 [P,L]
# END A ——————–

这样一来指向到serverQ的:

域名 www.a1.com www.a2.com 的所有请求通过反向代理转发到了 serverP的81端口
域名 www.b1.com www.b2.com 的所有请求通过反向代理转发到了 serverP的82端口

以此类推,不管前端有多少台服务器,我们只要搭建好了apache(proxy&rewrite),只需要通过ftp来维护.htaccess就能灵活设置多前端单一后端的proxy了。

PS:一般来说通过ftp软件是无法看到.htaccess文件的,每个ftp软件都有自己一套设置支持浏览这类文件,这里推荐一下filezilla这个免费ftp工具,只需把菜单中“服务器”->“强制显示隐藏文件”开启就可以正常显示隐藏文件了。

php实现简单的“分享”功能

看到人人和facebook都有一个分享的功能。

就是输入一个url,然后返回对方的title名称和很多该页面上的图片,操作者选择之后就提交到后端:

如我在renren上分享链接 http://www.dyee.org/bbs/thread-182935-1-2.html

会跳转到这样的页面:

cc

其中,红色区域是获得的网页title,而点击绿色部分就可以切换所要使用的图片。

我写的后端代码如下:

<?php
set_time_limit(0);
$url = trim($_REQUEST['url']);
if($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//curl_exec($ch);
$output = curl_exec($ch);
//$c_info = curl_getinfo($ch);
//print_r($c_info);
curl_close($ch);
preg_match(”/charset=([^\"]+)\”/i”,$output, $matches);
//print_r($matches);
$code = $matches[1];
echo ‘<p>编码:’.$code.’</p>’;
preg_match(”/<title>([^<]+)</i”,$output, $matches);
//print_r($matches);
$title = mb_convert_encoding($matches[1],’utf-8′,$code);
echo ‘<p>标题:’.$title.’</p>’;
//$output=str_replace(”\”",”\n”,$output);
//$output=str_replace(”\’”,”\n”,$output);
//preg_match_all(”/src=[\"|']{0,1}(.*\.(gif|jpg|jpeg|png))/i”,$output, $imgs);
//preg_match_all(”/src=[\"|']{0,1}(([^\.]+)\.(gif|jpg|jpeg|png))/i”,$output, $imgs);
//preg_match_all(’/<img.*?(?: |\\t|\\r|\\n)?src=[\'"]?(.+?)[\'"]?(?:(?: |\\t|\\r|\\n)+.*?)/sim’, $output, $imgs, PREG_PATTERN_ORDER);
//preg_match_all(”/<img.*src\s*=\s*[\"|\']?\s*([^>\"\'\s]*)/i”,$output,$imgs);
//preg_match_all(’/<img.+src=\”?(.+\.(jpg|gif|bmp|bnp|png))\”?.+>/i’,$output,$imgs);
preg_match_all(’/src=[\"\']?([%+\*\w\/:\._-]+(?:jpg|gif|bmp|jpeg|png))/ism’, $output,$imgs);
if(is_array($imgs)){
$tmp = explode(’/',$url);
$http = $tmp[0].’//’.$tmp[2];
$tpath = $tmp[0].’//’;
for($i=2;$i<count($tmp)-1;$i++){
$tpath.=$tmp[$i].’/';
}
foreach ($imgs[1] as $i){
echo ‘<img src=”‘.parseImg($i,$url,$http,$tpath).’”/>’;
//echo ”.parseImg($i,$url,$http,$tpath).’<br/>’.”\n”;
}
}
}
function parseImg($img,$page,$http,$tpath){
#直接有http
if(preg_match (’/^http/i’, $img) ){
return $img;
}
#根路径
if(preg_match (’/^\//i’, $img)){
return $http.$img;
}
#本路径
if(preg_match (’/^[^\/]/i’, $img)){
if(preg_match(’/\/$/i’,$page)){
return $page.$img;
}
if($http.’/'==$page || $http==$page){
return $http.’/’.$img;
}else{
return $tpath.$img;
}
}
}

<?php

set_time_limit(0);

$url = trim($_REQUEST['url']);

if($url){

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $url);

curl_setopt($ch, CURLOPT_HEADER, 0);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

$output = curl_exec($ch);

curl_close($ch);

preg_match(”/charset=([^\"]+)\”/i”,$output, $matches);

$code = $matches[1];

echo ‘<p>编码:’.$code.’</p>’;

preg_match(”/<title>([^<]+)</i”,$output, $matches);

$title = mb_convert_encoding($matches[1],’utf-8′,$code);

echo ‘<p>标题:’.$title.’</p>’;

preg_match_all(’/src=[\"\']?([%+\*\w\/:\._-]+(?:jpg|gif|bmp|jpeg|png))/ism’, $output,$imgs);

if(is_array($imgs)){

$tmp = explode(’/',$url);

$http = $tmp[0].’//’.$tmp[2];

$tpath = $tmp[0].’//’;

for($i=2;$i<count($tmp)-1;$i++){

$tpath.=$tmp[$i].’/';

}

foreach ($imgs[1] as $i){

echo ‘<img src=”‘.parseImg($i,$url,$http,$tpath).’”/>’;

}

}

}

function parseImg($img,$page,$http,$tpath){

#直接有http

if(preg_match (’/^http/i’, $img) ){

return $img;

}

#根路径

if(preg_match (’/^\//i’, $img)){

return $http.$img;

}

#本路径

if(preg_match (’/^[^\/]/i’, $img)){

if(preg_match(’/\/$/i’,$page)){

return $page.$img;

}

if($http.’/'==$page || $http==$page){

return $http.’/’.$img;

}else{

return $tpath.$img;

}

}

}

稍加改动就可以使用了。

《了凡四训》电影版

A面:

B面:

也谈facebook的bigPipe

最近在做技术研究的时候,遇到了bigPipe。

关于bigPipe的官方文章在这里 http://www.facebook.com/note.php?note_id=389414033919 (天朝得翻墙)。

有位叫 limu的仁兄发表了 http://limu.javaeye.com/blog/765173 这篇文章。 我表示一般赞成的。

但是,可能是这仁兄facebook用的少吧~那并不是bigPipe的全部。

limu仁兄说到,先点菜,然后各个大厨一起做菜,然后给用户端上来,举个反证:

http://www.facebook.com/pages/ka-ti-nuo-wang-guo-CK101lun-tan/107749042613155 (AD一下CK的粉丝页)

用户每次点菜(打开新页面)时,先载入框架,再ajax调用内容填充上去。但是,针对这一次载入,反而给服务器多填了几个请求不是么?

不理解?我们分析看看,比方说一个页面有8个框框要填东西,如果用传统的方式,这8个框框本来可以随着主框架一次载入进来,如果某个框框需要更新,那么我们就ajax再载入和更新对应的位置。这样一来,第一次的成本就只有1次服务器开销。而facebook也同样可以实现高速的载入,肯定不会像limu仁兄说的,超过500ms。

不管数据来自哪里,服务端怎么缓冲,这8个框框的内容肯定都会被用户载入到浏览器的。

那么每次多8个请求,有何意义呢?

让我们来正确的分析一下吧:

http://www.facebook.com/pages/ka-ti-nuo-wang-guo-CK101lun-tan/107749042613155

一个该页面的请求,如果浏览器支持js,那么html部分只有框架,其后跟着大量的js的json对象,跟limu兄说的一样。

这时候,左侧喜欢他的网友框里面显示:

aa

以上图片的红框“芮世軒”这个网友,链接为 http://www.facebook.com/profile.php?id=100000868569268

ok,当我们在页面上点击该链接,不出意外,浏览器的地址栏会是这个链接地址吧?

但是…当你点击该链接并且载入该网友信息后,链接地址却是:

http://www.facebook.com/pages/ka-ti-nuo-wang-guo-CK101lun-tan/107749042613155#!/profile.php?id=100000868569268

哦?一个锚链!!而页面上的东西已经全变成这个网友的个人主页了~

bigpipe拦截了我的a标签的click动作,又通过ajax方式调用了该网友的信息,在当前这个ck粉丝页上,能用的动态框框就复用,不能用的就隐藏,没有的就添加,制造了一个网友的个人首页出来。

而他又给该粉丝页增加了一个锚链,既可以个goback创造空间,又让网友可以通过这个加了锚链的地址直接访问这个网友的页面。

事实上,ck的粉丝页,并不含有一个#!/profile.php?id=100000868569268锚链,而这个锚链是告诉服务器,该页的实际位置的。

那么至此,大家应该明白,第一次还要分8块载入的原因了吧?就算请求某个实际页面,最终呈现成什么样子或者分成几块,也不取决于框架。

这样一来:

如果访问http://www.facebook.com/pages/ka-ti-nuo-wang-guo-CK101lun-tan/107749042613155#!/profile.php?id=100000868569268

跟ck的粉丝页,基本上没有关系了,出来的结果是那个网友的个人主页。

另外,还有一些弹出窗口也设计成这样:

比方说“分享”按钮,其实href是http://www.facebook.com/ajax/share_dialog.php?s=99&appid=2309869772&p[]=1149318559&p[]=129942140395896&action_link=share

但实际上,页面不动,而facebook截取了click时间把它转换成了弹出窗口。

apache的常用module配置

用来做gzip压缩的deflate模块:

DeflateCompressionLevel  压缩等级,取值范围1–9,越高cpu的load越重。

大致的配置(得先SetOutputFilter再AddOutputFilter):

<IfModule mod_deflate.c>
DeflateCompressionLevel 3
SetOutputFilter DEFLATE
#AddOutputFilterByType DEFLATE php
AddOutputFilter DEFLATE php html htm js css xml
</IfModule>

用apxs灵活编译更多的apache模块

在apache安装的时候,可以选择–enable-so这一项,那么就可以通过apxs这个文件来扩展更多的apache 模块了。

不懂安装的请看我的“apache在linux上的编译安装”一文。

查看当前的apache是否支持so:

#/path/to/apache/bin/apachectl -l |grep mod_so

如果列表中有mod_so.c这一项,说明你目前的apache是支持,另外,你的/path/to/apache/bin/下面有没有apxs这个文件。

apxs的部分参数说明:
http://www.linux.gov.cn/netweb/mat/ApacheMenu_zh_CN/dso.html

-n modname
它明确设置了-i(install)和-g (template generation)选项的模块名称。 对-g选项,它是必须的; 对-i选项,apxs工具会按文件名判断至少是推测出这个模块名称。
-q
查询某种apxs设置的信息。 query参数可以是下列一个或多个字串:CC, CFLAGS, CFLAGS_SHLIB, INCLUDEDIR, LD_SHLIB, LDFLAGS_SHLIB, LIBEXECDIR, LIBS_SHLIB, SBINDIR, SYSCONFDIR, TARGET.这个参数用于手动查询某些设置。比如,要手动处理Apache的C头文件,可以在Makefile中使用
-g
此选项生成一个名为name的子目录(见选项-n)和其中的两个文件: 一个是名为mod_name.c的样板模块源程序, 可以用作建立你自己的模块的模板,或是学习使用apxs机制的良好开端; 另一个则是对应的Makefile,用于编译和安装此模块。
-c
此选项表示需要执行编译操作。 它首先会编译C源程序(.c)files为对应的目标代码文件(.o), 然后,连接这些目标代码和files中其余的目标代码文件(.o and .a), 以生成动态共享对象dsofile。如果没有指定-o选项, 则此输出文件名由files中的第一个文件名推测得到, 所以,缺省时,它一般会是mod_name.so
-i
此选项表示需要执行安装操作, 以安装一个或多个动态共享对象到服务器的modules目录中。
-a
此选项自动在httpd.conf文件中增加一个LoadModule行,以激活此模块,或者,如果此行已经存在,则启用之。
-A
与-a选项类似,但是它增加的LoadModule指令由一个井号前缀(#), 即,此模块已经准备就绪,但尚处于禁用状态。
-e
此选项表示需要执行编辑操作,它可以与-a和-A选项配合使用, 与-i操作类似,修改Apache的httpd.conf配置文件,但是并不安装此模块。

apxs的运作原理

一般来说,每个module都对应一个.c文件,放在你apache的源文件目录里面,让apache的这个apxs程序去编译对应的module.c的源文件,会在apache安装目录的modules/文件夹中生成对应的.so文件,再在httpd.conf里面添加LoadModule 指令,那么,每次启动apache 就会把对应的这个module载进来。

这写module的源文件有些有相互依存关系,安装的时候需要注意一下顺序和前后摆放。

通过apxs采用DSO方式安装mod_headers和mod_deflate两个模块:

# cd /path/to/apache/bin/

# ./apxs -i -a -c /path/to/source/modules/filters/mod_deflate.c
# ./apxs –i –a –c /path/to/source/modules/filters/mod_headers.c

去httpd.conf里面看看,两个LoadModule 都放在那里了。

apache在linux上的编译安装

http://www.linux.gov.cn/netweb/mat/ApacheMenu_zh_CN/programs/configure.html

apache拥有4层结构,从核心到外层的module。而外层的module可以用通过静态和动态两种方式与apache共同工作。这也就引入下文的“动态”和“静态”两种编译安装方式:

静态编译:

编译的时候,所有的模块自己编译进httpd 这个文件中 ,启动apache的时候这些模块就已经加载进来了,可以直接来使用,而不用再httpd.conf中在LoadModule来加载,只要在 <ifmodule></ifmodule> 中来配置就可以了。

动态编译:

编译的时候,使用enable-module=shared 或者enable-modules-shared=module来动态编译。 动态显然就不编译到httpd里面去了,启动的时候根本不会加载这个模块, 而是给你一个module.so 文件。你想用,就在httpd.conf中使用 loadmodule 这个语法来加载,这个模块才有效。

区别是:

静态的模块通常在http.conf中用<ifmodule></ifmodule> 来配置,动态的要先loadmoule来加载,然后再<ifmodule></ifmodule>配置。
官方说静态的比动态的在性能方面多5%左右。

相对来说,静态的效率高些,而动态方式配置方面灵活。想想如果编译进去的C这个module你想升级或者去掉,静态方式的就只能重新编译apache了。

下面这句在apache源文件夹下运行,可以查看默认情况下apache都给你装了那些module进去:

./configure –help | grep disable

让apache日后可以动态编译和加载模块:

如果想让apache日后可以支持动态编译(DSO)更多的module,需要在初次安装时把so这个模编译到核心。

如果编译中包含任何DSO模块,则mod_so会被自动包含进核心。如果希望核心能够装载DSO,但不实际编译任何DSO模块,则需明确指定:

针对apache1.x:    –enable-module=so

针对apache2.x: –enable-so=static

apache模块的类型:

基本(B)模块默认包含,必须明确禁用;

扩展(E)/实验(X)模块默认不包含,必须明确启用。

那么,针对以上这些类型的模块,有以下几种操作方式:

–disable-MODULE
禁用MODULE模块(仅用于基本模块)
–enable-MODULE=shared
将MODULE编译为DSO(可用于所有模块)
–enable-MODULE=static
将MODULE静态连接进核心(仅用于扩展和实验模块)
–enable-mods-shared=MODULE-LIST
将MODULE-LIST中的所有模块都编译成DSO(可用于所有模块)
–enable-modules=MODULE-LIST
将MODULE-LIST静态连接进核心(可用于所有模块)

针对–enable-modules和–enable-module-shared有两个懒办法就是 most参数和all参数,分别表示“很多的”和“所有”。

例如:

mod_alias是个基本模块,不想安装的话就: –disable-alias

mod_rewrite是个扩展模块,想动态加载它:–enable-rewrite=shared,想静态加载就是:–enable-rewrite=static

想静态编译mod_alias和mod_rewrite:–enable-modules=’alias rewrite’

想动态编译mod_alias和mod_rewrite:–enable-modules-shared=’alias rewrite’

针对apache2.2.x的一些例子:

最大化静态安装apache:

./configure –prefix=/path/to/local –enable-modules=all

最大化动态安装apache:

./configure –prefix=/path/to/local –enable-mod-shared=all

静态安装rewrite、动态安装deflate以及headers

./configure –prefix=/path/to/local –enable-rewrite=static –enable-deflate=shared –enable-headers=shared

不安装基本的alais,保留以后的扩展DSO能力:

./configure –prefix=/path/to/local –enable-so=static –disable-alias

linux分区点滴

1,必要分开的几个区

/swap     交换分区,大小是物理内存的2倍而不大于4G

/boot     引导区,100-200M够了

/      根分区

2,针对服务器的不同用途

针对服务器的不同用途,来划分其他分区,比如把应用和数据分开多个区放。

未完待续..

关于VMwave workstation

想要学习linux,最简单的办法就是在自己的windows系统下装VM了,有了VM,就能在你的系统中虚拟出多个操作系统,他们只占你的CPU和硬盘,对你windows系统本身没有任何破坏。

1,什么是VMwave?

官方网站:www.vmware.com

简单的解释就是:用这个软件可以在你的windows/linux/mac系统中模拟出最多4个虚拟的操作系统,你可以在这个软件基础上装多个虚拟的操作系统,功能基本都能实现,但是效率我就不敢说了。

2,安装

一般我用VM都是用它来虚拟出linux,学习和测试用。

win下安装比较简单,直接下一步,我现在再用的还是5.5版本的workstation,够用就行。

之后序列号网上随便搜一个就OK。

3,wrokstation和player的区别

workstation版本可以建立新的虚拟操作系统,而player只能用来跑别人建立好的虚拟系统。

4,配置

没啥多讲的,新建虚拟机的时候,要用custom方式,然后“I/O adapater types”选“Buslogic”,还有“Virtual Disk Type”选“IDE”。

5,安装linux

找张linux安装盘或者下载的iso文件(iso文件方式需要配置一下),然后“Start this virtual Machine”就等安装画面吧。

6,关于64位和32位的VM

目前有两种说法:

A,在64位的宿主机上虚拟64位操作系统是没问题的。

B,如果你的硬件是64位,而装的是32位的操作系统,那么如果你的CPU支持Virtualization Technology的话,也可以在32位的宿主上运行64位的VM。

至少,32位的硬件是肯定VM不出64位的虚拟机的。