PHP 的 GC(垃圾回收) 机制

众所周知, PHP 引擎本身是用 C 写的,提到 C 不能不提的就是 GC(垃圾回收).通过 PHP 手册 我们了解到, PHP 引擎会自动进行 GC 动作.那么我们不禁要问,到底它是怎么回收的, & 引用操作是不是指针, unset() 了一个变量时它是不是真的被回收了呢?这些看似手册有提及的问题,如果仔细分析会发现,远没有那么简单泛泛.也许有人会跳出来说:看 PHP 源码不就知道了.是的,等你通读了 PHP 源码后这个问题肯定不在话下了,然本篇要仅从 PHP 本身来分析这些看似平常却被忽视的小细节,当然了,其中难免水平所限,有所疏漏,热烈欢迎广大 phper 来共同讨论.

Example 1
首先咱先看到例子,最简单不过的执行流程了:

error_reporting(E_ALL);
$a = 'I am test.';
$b = &$a;
echo $b ."\n";

不用说 php -f gc.php 输出结果非常明了:  I am test.

分析 GC 与引用:
所有例子中,创建了一个变量,这个过程通俗一点讲:是在内存中开辟了一块空间,在里面存放了一个字符串 I am test. . PHP 内部有个符号表,用来记录各块内存引用计数,那么此时会将这块内存的引用计数 加 1,并且用一个名为 $a 的标签(变量)指向这块内存,方便依标签名来操作内存.

Example 2:

error_reporting(E_ALL);
$a = 'I am test.';
$b = & $a; 
 
$b = 'I will change?';                                                           
 
echo $a ."\n";
echo $b ."\n";

执行结果依然很明显:
php -f gc.php
I will change?
I will change?

分析 GC 与引用:
变量 $a 进行 & 操作,我的理解是找到 $a 所指向的内存,并为 $b 建立同样的一引用指向,并将存放字符串 I am test. 的内存块在符号表中引用计数 加 1.换言之,我们的脚本执行到这一行的时候,存放字符串 I am test. 的那块内存被引用了两次.这里要强调的是, & 操作是建立了引用指向,而不是指针, PHP 没有指针的概念!同时有人提出说类似于 UNIX 的文件软链接.可以在一定程度上这么理解: 存放字符 I am test. 的那块内存是我们的一个真实的文件,而变量 $a 与 $b 是针对真实文件建立的软链接,但它们指向的是同一个真实文件. So, 我们看到,在 Example 2 中给 $b 赋值的同时, $a 的值也跟着变化了.与通过某一软链操作了文件类似.

Example 3:

error_reporting(E_ALL);
$a = 'I am test.';
$b = & $a;  
 
unset($a); 
 
echo $a ."\n";
echo $b ."\n";

执行结果:

php -f gc.php
Notice: Undefined variable: a in /usr/local/www/apache22/data/test/gc.php on line 8
I am test.
有点犯迷糊了吗?

Example 4:

error_reporting(E_ALL);
$a = 'I am test.';
$b = & $a; 
 
unset($b);                                                                       
 
echo $a ."\n";
echo $b ."\n";

执行结果:

php -f gc.php
I am test.
Notice: Undefined variable: b in /usr/local/www/apache22/data/test/gc.php on line 9

分析 GC 与引用:
在 Example 3 与 4 中,进行了 unset() 操作.根据实际的执行结果,可以看出: unset() 只是断开这个变量对它原先指向的内存的引用,使变量本身成为没有定义过空引用,所在调用时发出了 Notice ,并且使那块内存在符号表中引用计数 减 1,并没有影响到其他指向这块内存的变量.换言之,只有当一块内存在符号表中的引用计数为 0 时, PHP 引擎才会将这块内存回收.

Example 5:

error_reporting(E_ALL);
$a = 'I am test.';
$b = & $a; 
 
$a = null; 
 
echo '$a = '. $a ."\n";
echo '$b = '. $b ."\n";

执行结果:

php -f gc.php
$a =
$b =

Example 6:

error_reporting(E_ALL);
$a = 'I am test.';
$b = & $a; 
 
$b = null; 
 
echo '$a = '. $a ."\n";
echo '$b = '. $b ."\n";

执行结果:

php -f gc.php
Notice: Undefined variable: a in /usr/local/www/apache22/data/test/gc.php on line 8
I am test.
有点犯迷糊了吗?

分析 GC 与引用:
通过 Example 5 & 6 可以明确无误得出: 赋值 null 操作是相当猛的,它会直接将变量所指向的内存在符号号中的引用计数置 0, 那这块内存自然被引擎回收了,至于何时被再次利用不得而知,有可能马上被用作存储别的信息,也许再也没有使用过.但是无论如何,原来所有指向那块内存变量都将无法再操作被回收的内存了,任何试图调用它的变量都将返回 null.

综上所述,充分说明了为什么我们在看开源产品源码的时候,常看到一些比较大的临时变量,或使用完不再调用的重用信息都会被集中或显示的赋值为 null 了.它相当于 UNIX 中直接将真实文件干掉了,所有指向它的软链接自然成了空链了.之前在讨论到这些细节点时有很多想当然的念头,在实际的执行了测试代码后才发现: 哦,原来如此!

(注 $a = null; 只是强行地把$a 所指向的内存区域进行内存区域的引用记数强制变为0  但是并没有得到立即的释放 依然会有 内存占用, 所以想强行将 $a所指的内存块进行释放 应该 $a=null;unset($a); )


Ubuntu 11.10 Mysql+Nginx+Apache+PHP 安装指南(1) —– Mysql

前言:本文是根据blog.s135.com [搭建胜过Apache十倍的Web服务器] 为基础,主要讲解如何在最新版本Ubuntu 11.10下部署 PHP + Mysql + Apache + Nginx 环境的搭建。全文分文三篇 mysql , php , nginx. 这是第一篇主要讲如何部署安装mysql。

本系列所要用到的软件下载

wget http://blog.s135.com/soft/linux/nginx_php/mysql/mysql-5.5.3-m3.tar.gz
wget http://mirror.bjtu.edu.cn/apache//httpd/httpd-2.2.21.tar.gz
wget http://cn2.php.net/distributions/php-5.2.17.tar.gz
wget http://www.nginx.org/download/nginx-1.0.11.tar.gz
wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz
wget http://blog.s135.com/soft/linux/nginx_php/mcrypt/libmcrypt-2.5.8.tar.gz
wget http://blog.s135.com/soft/linux/nginx_php/mcrypt/mcrypt-2.6.8.tar.gz
wget http://blog.s135.com/soft/linux/nginx_php/mhash/mhash-0.9.9.9.tar.gz
wget http://blog.s135.com/soft/linux/nginx_php/eaccelerator/eaccelerator-0.9.6.1.tar.bz2
wget http://blog.s135.com/soft/linux/nginx_php/pdo/PDO_MYSQL-1.0.2.tgz

1. 源更新

#编辑源

sudo vim etc/apt/source.list

deb http://mirrors.163.com/ubuntu/ oneiric main universe restricted multiverse
deb-src http://mirrors.163.com/ubuntu/ oneiric main universe restricted multiverse
deb http://mirrors.163.com/ubuntu/ oneiric-security universe main multiverse restricted
deb-src http://mirrors.163.com/ubuntu/ oneiric-security universe main multiverse restricted
deb http://mirrors.163.com/ubuntu/ oneiric-updates universe main multiverse restricted
deb http://mirrors.163.com/ubuntu/ oneiric-proposed universe main multiverse restricted
deb-src http://mirrors.163.com/ubuntu/ oneiric-proposed universe main multiverse restricted
deb http://mirrors.163.com/ubuntu/ oneiric-backports universe main multiverse restricted
deb-src http://mirrors.163.com/ubuntu/ oneiric-backports universe main multiverse restricted
deb-src http://mirrors.163.com/ubuntu/ oneiric-updates universe main multiverse restricted

#对源进行更新
sudo apt-get update

2. mysql 的编译与安装

#下边是俩个需要用到的lib

sudo apt-get install make
sudo apt-get install libncurses5-dev
sudo apt-get install g++

tar xzvf mysql-5.5.3-m3.tar.gz

./configure --prefix=/usr/local/mysql/ --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client --with-big-tables --with-readline --with-ssl --with-embedded-server --enable-local-infile --with-plugins=partition,innobase,myisammrg

 (notice: 在使用gcc4.5版本遇到一个bug error do_abi_check 需要手动修改 makefile 里边注释掉 do_abi_check 后的内容。)

make
sudo make install

#创建mysql用户
sudo groupadd mysql
sudo useradd -g mysql mysql

#创建log和data文件夹
sudo mkdir /var/mysql

sudo mkdir /var/log/mysql/
sudo mkdir /var/log/mysql//binlog
sudo mkdir /var/log/mysql//relaylog
sudo chown -R mysql:mysql /var/mysql/

#初始化数据表

sudo /usr/local/mysql/bin/mysql_install_db --basedir=/usr/local/mysql --datadir=/var/mysql/ --user=mysql

#编码mysql配置 以下配置可以根据自己服务器环境进行配置调优

sudo vim /usr/local/mysql/my.cnf

[client]
character-set-server = utf8
port    = 3306
socket  = /tmp/mysql.sock
[mysqld]
character-set-server = utf8
replicate-ignore-db = mysql
replicate-ignore-db = test
replicate-ignore-db = information_schema
user    = mysql
port    = 3306
socket  = /tmp/mysql.sock
basedir = /usr/local/mysql
datadir = /var/mysql/
log-error = /var/log/mysql/mysql_error.log
pid-file =  /usr/local/mysql/mysql.pid
open_files_limit    = 2000
back_log = 600
max_connections = 1000
max_connect_errors = 2000
table_cache = 100
external-locking = FALSE
max_allowed_packet = 16M
sort_buffer_size = 1M
join_buffer_size = 1M
thread_cache_size = 20
#thread_concurrency = 8
query_cache_size = 128M
query_cache_limit = 1M
query_cache_min_res_unit = 2k
default-storage-engine = MyISAM
thread_stack = 192K
transaction_isolation = READ-UNCOMMITTED
tmp_table_size = 32M
max_heap_table_size = 64M
long_query_time = 2
log-slave-updates
log-bin = /var/log/mysql/binlog
binlog_cache_size = 2M
binlog_format = MIXED
max_binlog_cache_size = 4M
max_binlog_size = 512M
relay-log-index = /var/log/mysql/relaylog
relay-log-info-file = /var/log/mysql/relaylog
relay-log = /var/log/mysql/relaylog
expire_logs_days = 30
key_buffer_size = 32M
read_buffer_size = 1M
read_rnd_buffer_size = 2M
bulk_insert_buffer_size = 16M
myisam_sort_buffer_size = 32M
myisam_max_sort_file_size = 1G
myisam_repair_threads = 1
myisam_recover
interactive_timeout = 120
wait_timeout = 120
skip-name-resolve
slave-skip-errors = 1032,1062,126,1114,1146,1048,1396
server-id = 1
[mysqldump]
quick
max_allowed_packet = 32M

 

3. 启动mysql

 

sudo vim /etc/init.d/mysql

#!/bin/sh
mysql_port=3306
mysql_username="root"
mysql_password="root"
function_start_mysql()
{
    printf "Starting MySQL...\n"
    sudo /usr/local/mysql/bin/mysqld_safe --defaults-file=/usr/local/mysql/my.cnf 2>&1 > /dev/null &
}
function_stop_mysql()
{
    printf "Stoping MySQL...\n"
    sudo /usr/local/mysql/bin/mysqladmin -u${mysql_username} -p${mysql_password} -S /tmp/mysql.sock shutdown
}
function_restart_mysql()
{
    printf "Restarting MySQL...\n"
    function_stop_mysql
    sleep 5
    function_start_mysql
}
if [ "$1" = "start" ]; then
    function_start_mysql
elif [ "$1" = "stop" ]; then
    function_stop_mysql
elif [ "$1" = "restart" ]; then
    function_restart_mysql
elif [ "$1" = "kill" ]; then
    function_stop_mysql
else
    printf "Usage: mysql-server {start|stop|restart|kill}\n"
fi

 

#启动mysql
sudo chmod +x /etc/init.d/mysql
sudo /etc/init.d/mysql start

4. 为mysql root 用户建立密码

 

sudo /usr/local/mysql/bin/mysqladmin -u root password 'root'

PHP过滤用户提交信息(防SQL注入)

请求层面的过滤

在 request 层面 我们可能要做的是如何防止非法html 的标签的提交, 例如<script><iframe><html>等。在这里 我们可以用一个php 函数 htmlspecialchars  (http://www.php.net/manual/en/function.htmlspecialchars.php) 这样的话前台提交的所有内容 如果包含html 标签的话 就会被转义,并且在输出的时候  这些标签会直接显示在浏览器里边 而不会被当做script被浏览器所执行。

SQL层面的控制

–什么是SQL注入

如果用户传入的参数 需要用于构造sql 语句的话 那么我们就需要对输入的参数进行再一次过滤, 来达到防止sql注入的目的。首先让我们来看看什么叫做sql注入,下边有这么一个例子:

在php 中我们往往会这样去构造一个sql语句
$sql = “select * from user where name = ‘” + $_GET['name']  + “‘”;
在浏览器的url里, 我们会这样去传入这个name值:

1.HTTP://xxx.xxx.xxx/abc.php?name=rocky
第一种情况貌似一切正常, 我们成功获取了名字为rocky的用户。

2.HTTP://xxx.xxx.xxx/abc.php?name=rocky’%20or%201=’1   (%20 表示空格)
这时候php 中得 $sql变量取值就成了:
select * from user where name = ‘rocky’ or 1=’1′
我们再来看看搜索出来结果, 全部的用户都被返回了, 这当然不是我们所预期的, 也就是说 我们通过传入参数来达到了改变sql语句的目的

3.HTTP://xxx.xxx.xxx/abc.php?name=rocky’;delete from user where 1=’1   (%20 表示空格)
这种情况貌似更糟糕,这时候的$sql变量成了:
select * from user where name = ‘rocky’;delete from user where 1=’1′
所有的用户都被删除了。

–如何防范SQL注入

那么我们要如何来防止这样的情况呢, 下边我以zend framework防注入的原理来谈一种解决方案:

1. 首先我们需要对用于实现sql注入的关键字进行一次过滤, 这里的关键字有’ ” 和 ; 在这些符号前加上/, zend 的实现是这样的 addcslashes($value, “\000\n\r\\’\”\032″);

2. 其次, 在用户传入的参数到达sql之前, 我们需要明白我们期待的用户传入是个什么类型的值, 字符串or整数or浮点
如果是字符串的话 我们就在首位加上’ 符号  例如 ‘$var’.
如果是整形数字的话, 我们则  intval( $var );
如果是浮点型的话, 我们则    sprintf(‘%F’, $var);
这样的话我们就可以过滤用户的一些非法输入

具体实现:

function quote( $value , $type ){
	if( $type == "integer" ){
		return intval( $value );
	}elseif( $type == "float" ){
		return sprintf('%F', $value );
	}else{
		return "'" . addcslashes($value, "\000\n\r\\'\"\032") ."'"
	}
 
}
 
$sql = "select * from user where name = ?";
str_replace( "?" , quote( $value , "String" ) , $sql );

Apache Solr 安装与使用指南 (一)

Apache Solr是一种开放源码的、基于 Lucene Java 的搜索服务器,易于加入到 Web 应用程序中。Solr 提供了层面搜索、命中醒目显示并且支持多种输出格式(包括 XML/XSLT 和 JSON 格式)。它易于安装和配置,而且附带了一个基于 HTTP 的管理界面。您可以坚持使用 Solr 的表现优异的基本搜索功能,也可以对它进行扩展从而满足企业的需要。Solr 还拥有一个活跃的开发者群体,如有需要,您可以随时向他们寻求帮助

Read more »


眨眼过去的半年

可能上半年最遗憾的一件事情就是好朋友 zach 的离开, 非常感觉这位 american guy. 让我充分接触到了一个美国人的世界观, 和 a lot of fun. 也同时让我看到了 人本应有的性格, 开朗, 乐观。 zach是我们很好的English teacher, 而且在这一年里, 这位美国boy 给我和sheldon 补上了不少的英文课程, 当然 a plenty of bad words 也是从他那里学来的. 惊奇地发现只要是美剧里出现的bad word, 无一不认识 :) 。 就像电影里说的那样 life is in session, 地球不会因为少了某个东西而不转一样。 以后的工作可能更多地需要自己去学会独挡一面, 英语的学习也是没有放弃。 祝福Zach 能回国后过得更好。

接替Zach的是Hakim 一个 French guy, very humble and peaceful. 虽然少了zach 的激情 不过更多的感觉到的是一份沉稳。 工作中更多的交流方式都是以邮件进行了, hakim 并没有像zach 那样会给我们很详细地讲客户需求, 而是得自己去直接读 客户的邮件, 虽然不像以前那样的便利, 但也是个不错的练习英语的机会, 很多文档也需要自己开手写了, 慢慢地发现最快乐的时候 就是打开google 文档 开始馒头苦写 程序架构和api 文档之类的东西。自己的角色更多转变成了一个项目的推动者,而不是被动地听取他人意见。 Hakim 同样也成了我的英语老师, 而且这次一个大转变, 直接从美式到英式 少了几份 fantastic , 多了不少 excellent. 呵呵 非常幸运能碰见这些老师, 而且从他们身上我都看出了 对待事情的耐心。

公司运转当然也不是那么一切顺利, 依然面临着招人难的状况, sheldon 离开确实给公司带来了一大窟窿, 这时才感觉到 一个公司最重要的不是钱 而是人。 确实 做公司很难, 特别是startup company 的这种, 当然也想起以前的记忆日, 如果当时我们坚持下去会怎么样呢, 因为昨天的金刚经课上 第16品讲的就是 小公司成长记最重要的一点“坚持”。 往往很多成功的公司都是顶住了最困难的时刻坚持过来的。 老板也不在国内,这次回国时长可能有5个星期, 更多希望是做好荷兰市场, 公司更多就是 Miss Ding 和 我 来处理了。

其实这半年来的还有一个意外收获, 那就是金刚经, 可能很多人会误解这部经典, 感觉是佛家学说 就是准备出家什么的, 其实并不是这样的。其实很多佛学像金刚经这样就是讲的一个 吾人生之道。 文言文我是读不懂, 每次去都是听黄山老师的讲解, 去结合实际情况去体会一些道理, 宗旨就在于吾人生自己的一条道,而且要活在当下, 因为我们都不想等老了才恍然大悟起什么来。 当然在课堂上也认识了不少朋友 而且发现大家的共同变化就是会比以前开朗,快乐不少。 很多喜欢这方面的朋友都开始 向我推荐很多其他很好的 著作, 自己也买了一些白话书 没事也来读读 , 一朋友推荐的 <参禅步道> 便是不错的一本, 文字很少, 不过却值得寻味。


2010 let’s hear it for ChengDu

2010 年 又回到了四川   其实自己意识到 早晚会回来 但没想到会那么快  总之 离开还是有不少遗憾    20-30 可以说是决定一个人未来的方向。  自己也一直在犹豫是不是该再多闯几年 虽然只是短短的一年 但已经发现自己有了 significant improvement, 期待着会不会有更多的惊喜发生。  但北方的干燥的气候 着实让人受不了 。  家里人也天天惦记  自己无意间也得到了成都一家小外企的offer,  自己的property 也快okay了 一切一切的因素促使了我提前的回来。

新公司的感受  —  自信 自强

呵呵 ,说实话, 2010这一年来 我还是那个我 外表看上去 依然书生气, 以至于大街上遇到 阿姨朋友什么的 还在问  你读大几呢 甚至 高中也有的。 行为上还是那样 喜欢调皮捣蛋 开玩笑, 呵呵性格就这样 也不想去刻意改变什么。

来到了一家新公司  才发现现实情况和上一个老板的教导是不蒙而合。  “人没有智商高低之分  只在于是否懂得做人”。  其实 做工作也是做人的过程。 如果自己决定选择这样一份工作, 不管活再多 千万别抱怨, 因为这就是生活, 既然你选择了它 就应该去适应它 而不是去逃避。 对于在成都的第一份新工作 在如何与人沟通  如何去适应一个新的环境, 如何安排自己的 学习工作进程,这些方面 自己已经能够很好的把握。 对这方面认识自己也有了更深一步的认识 再也不是 初出茅庐的 傻小子了。 非常感谢以前老板的教导,也慢慢感觉到了自己的自信。

公司的纯english 环境可能是自己的一大 challenge.  自从考过4级后 就再也没有关注过英语,  因为念书的时候 就不知道 读出来到底会有什么用 难道自己真的会天天跟着一堆外国人说话?   呵呵 生活是奇妙的  往往认为不可能的事情  瞬间就可能变成了现实。  而是一来还是2个 老外。  一个欧式英语 一个美式标准腔。  不过 恒心是可以战胜一切的。  可以说到现在吧 每天学习一点 english  就像是 一日3餐  必须得来点 要是不来的话 心就会感觉空空的。  当真正地进入这个阶段学习  才突然认识到 什么叫做 tough process.  tougher, tougher than you can imagine.  最痛苦的就是 前几天背的好好的东西  到了第三第四天基本就是忘光光,  再过1个星期左右 就感觉又是一个新单词。  不过找到原因之所在就是不要死记硬背,  正好自己有一个环境 干脆就来个生活中学英语吧  这样才感觉能够把 很多东西记得牢牢地。  再想想 最近还看见什么广告 30日 流利英语   完全就是在 take a dump(shit 我的chinglish了 ).

公司的一个中大型项目  是在8月中旬开始的吧  (www.magzine.nu)  这正好是一次证明自己的机会。  所以自己也在这个项目上 投入了不少精力, 项目是和另外一个 “old” guy 进行的。  那个old guy 呢 possess some conservative idea. so the first thing i need to do is to let him follow the new work flow we will adopt.  项目经理是 zach 他就主要和客户进行沟通吧。  期间面临了不少挑战 比如说 如何同步文件到 amazone S3 服务,  构建自己的 RESTFul APi 系统 因为还有另外一个 ipad application 会和我们主网站进行回话沟通。 项目也顺利提前完成了。  也很顺利的进入到稳定期间。  得到了老板的信任 自己也有更多机会 参与到公司其他工作中来了  比如说招聘 面试 当翻译什么的  呵呵 蛮有趣的 。

至于下一阶段 当然希望自己有 更广阔的 视野可以发展 mobile 平台也是一个比较好看的市场 只是 apple 卡的太严  那玩意产品价格都高的无比。 期待着 3月份 即将到来的 27  寸的 iMac 吧  哈哈~~  到时候 终于可以体验到什么事 超宽频的 屏幕享受了~~~

生活   —  kind of mess.  seeking for inspiration

其实生活上 依然是之前无聊的状态  突然不用加班 周6也可以轻轻松松呆在家里 着实让自己很不习惯  当然 自己心里也有不少期望  所以也就加紧english 的学习

难得有个这么好的环境,  公司 zach jordy 都是非常 kind 的 foreigner 。 让自己和他们之间的交流 感觉没有了 隔障。

至于感情 我也不想回避什么了   其实自己心态一直都没有调整过来 , 可能也没遇到特别能够谈得来的   朋友给介绍了几个 基本也就只是 见了个面  彼此也就没有太深入得 了解下去。  确实自己也不会什么 花言巧语   喜欢来的真是 是就是 不是就不是  没必要自己去 fake。  没关系 一切顺气自然吧 不要太强求 呵呵~~

最后给自己的 blog 打一个小广告哈  www.rocknoon.com  懂技术的朋友可以随时和我沟通 gtalk: luoqi.rocky@gmail.com


在Linux – Ubuntu 环境下Apache 以FastCGI 方式运行PHP 安装配置详解

(确保已经 以 fpm 方式安装了 php 如果没有安装 可以查看这篇文章 : )
http://www.rocknoon.com/ubuntu-lnmp-fastcgi-php/

#下载安装apache

下载 apache httpd 可以从 http://httpd.apache.org/download.cgi 进行下载
apache 会自动 选取最快的镜像进行下载

tar xzvf httpd-2.2.16.tar.gz
cd httpd-2.2.16
./configure –prefix=/usr/local/apache –with-mysql=/usr/local/mysql –enable-mods-shared=most –enable-ssl
sudo make && make install

#下载安装 mod_fcgi 扩展模块

wget http://www.fastcgi.com/dist/mod_fastcgi-SNAP-0910052141.tar.gz
tar xzvf mod_fastcgi-SNAP-0910052141.tar.gz

接下来就是要进行 mod_fcgi 扩展模块的安装 这里我们需要 修改一下 MakeFile 文件 来指定我们 apache 的路径
1. cp Makefile.AP2 Makefile
2. vim MakeFile 进行修改 top_dir = /usr/local/apache(apache 按转路径)
3. sudo make && make install

okay 如果成功 mod_fcgi.so 就被成功安装到了 apache/modules 下边了

#进行 httpd Server 的配置

接下来我们要做的 就是对 apache 进行配置
vim /usr/local/apache/conf/httpd.conf

在模块加载块 添加这条语句 LoadModule fastcgi_module modules/mod_fastcgi.so


<ifModule fastcgi_module>
ScriptAlias /cgi-bin/ "/usr/local/php/bin/"

FastCgiExternalServer /usr/local/php/bin/php-cgi -host 127.0.0.1:9000 -idle-timeout 300

AddType application/x-httpd-php .php

AddHandler php5-fastcgi .php
<Directory "/usr/local/php/bin">
Options -Indexes FollowSymLinks +ExecCGI

Order allow,deny

Allow from all

</Directory>
</ifModule>

加入 fastcgi 配置段

然后在需要 进行php 处理的 Directory 里边加入 如下配置

Action php5-fastcgi /cgi-bin/php-cgi

okay 重启 apache
然后在此访问 .php 的文件后 就可以看见 php cgi 处理之后的 页面了


回忆(二) 苏州街

09年春节后的大年(也正好是 cctv 国贸楼失火的那天), 我和胖爷再次约会在了知春路肯德基, 犹豫好久没见面了, 从寝室聊到代码。 胖爷开始向我讲解,各种各样的编程技巧, 还有闲暇之余 他leader 的授课内容。 当时我就被小胖各种讲解内容所吸引住了, 也很期望自己能够有这么一次机会参与其中。

没过多久犹豫胖爷公司刚招聘的一个程序员的离奇离职, 给了我这样一次面试的机会(呵呵 说来也真得感谢一下那个人)。 胖爷公司的大楼名叫立方庭,就在苏州街旁 之前其实来过一次,还是被各种小奢华所震撼, 立方体的装修, 一切都是金碧辉煌。 唯独倒霉的电梯, 还必须刷卡才能上去。 当然正题还是面试, 胖爷先把我领进一间小屋, 之后传说中的leader 进来了 。 第一印象是 不高的个头 丰满的大脑(哈哈),和蔼的笑容 给人第一感觉就是 已经小有成就 而且是个很有学问的人。 人称 柱爷。 面试是柱爷和小胖进行的( 小胖当时一直在打酱油 )。 当然之前柱爷对我的情况有个大致了解, 也没有去专门问我一些很专业的问题 只是问了我 以前是如何进行的项目 , 自己对程序这块的理解是怎么样。 面试没有进行多长 不过还是很愉快地结束了。 晚上时候胖爷给我通了电话 , 说实话 当时还是蛮紧张的 不知道自己能不能有这么一次机会, 当然回复还是令人delight的 一个礼拜后我便顺利到了新公司上班。

犹豫新公司用的是PHP 所以这块自己也得从头学起, 并且还得熟悉当前程序结构,尽快融入到新的开发中去, 不过这一次 明显比第一次工作有了经验, 因为有小胖的帮助, 让我有了更多的机会进行学习()。 项目的程序开发是由我们三人进行的, 柱爷带领着我们一起讨论, 一起想解决方案, 为什么要这样做 而不应该那样做。 就在这样的氛围中, 我和胖爷 在对程序的把握上 有了很大的进步 , thanks 柱爷。 当然 对于还处于初级阶段的我 很多情况下 很多东西都不理解。 也经常跟不上他们的节奏, 那时候真的有种感觉 是不是自己智商有问题 , 怎么老是 跟不上他们的想法。 在柱爷的推荐下 买了本设计模式开始专业, 才发现 原来 程序代码也是一门艺术 不是简单实现功能 就okay 的 还可以 组织出来如此优美的结构出来。

接下来就要说说新公司的另一大特色, 咱们的每日活动。 犹豫我们2楼 全是male. 而且大家都特别喜欢玩游戏。 一天大家发现胡爷在玩一个很有意思的游戏 dota, 大家都看稀奇地凑了过来, 看着各种各样的英雄和技能。 当时胡爷还在炫耀他的宙斯是多么的牛b , 当时我就在旁边偷笑 跟电脑ai玩有个什么前途。 当然我先不透深色地和他们玩了几局, 慢慢地大家也发现我技术水平特别高, 也就开始向我 讨教各种各样的操作技巧。 慢慢地我们也组织上了5人团队, 简单电脑 中等电脑 疯狂电脑。 每天中午吃完饭 大家便期待地 进行着 这项活动。 之后也开始上vs 玩, 不过一般 玩之前和之后 人都是俩种状态, 犹豫一般都是惨败, 人的心情都是由高兴变为失落。 这时胖爷淫荡的笑容便开始发挥作用 开始走街窜房地安慰着大家 “没有关系嘛 。 你们要是不开始 可以和我玩嘛 (因为当时他的水平很菜 可以随便虐哈) 。” 经过每天定时间的训练, 作为 dota 教主的我 常常带领着大家走向胜利。 还记得 rocky 大神各种超神吗 犀利的剑圣走位 各种暴走 double kill 吗 O(∩_∩)O哈哈~ 。 在之后胡爷的纪录片里 还可以看见大家各种胜利之后的高兴, 柱爷表演着骷髅王 甩着 他的大匕首 准备扔锤子 结果是没视野没扔出去。 胖爷各种迷离的眼神, dra 爷吃着他的 肉夹馍 还有一份凉皮看着dota视频。

当然 既然是公司 就不能只是玩游戏去啦。 因为平时游戏时间占去不少 所以大家的工作也就经常性地搞成夜间加班。 项目每一个阶段 3个leader 都会制定出一个方案 然后就是我们大家动员去实现它。 每一次上线之前 我们经常性地都是 通宵加班。然后 晚上大家一起去吃 西门烤翅 麦当劳什么的 。 第二天 人也是精疲力尽。 当时周末自然而然地也就显得异常珍贵, 不知道为什么要制定周6也需要上班, 周日经常就干脆索性地睡一整天。 彻彻底底的宅男 (其实现在也差不多)。 8月份也有了第一次公司第一次旅游, 一大家子 开车去 干脆直接开到了辽宁 锦州某个 沙滩 小村边。

有些时候工作像是拍一部电影, 总是要到谢幕的时候, 犹豫公司的收益情况不佳 很多人离去 那时我确实非常伤心, 伤心是因为 这样一个集体的解散。 在之后2名leader也相继离去, 不过我还是信任我们柱爷的 柱爷 胖爷 还有我 一直坚持着这个公司, 换了一个便宜不少的家宅当办公室。 也从苏州街 一下到了西土城 然后又到了牡丹园。 也慢慢 远离了中关村这一带。 犹豫对北京气候不适宜 还有自己也有回家的想法。 在第二年 春节后 我与 柱爷还有胖爷 胡爷 只能告别了。

离开的那天早晨, 是在胖爷亲自配送下上的飞机 那天真的 和自己的好朋友告别是一件很 难过很难过的事情。 不过我相信 我们不久之后还是会再次见面的。 而且 以后见面将不会变成是一件很困难的事情… 就这样 我坐着南航的飞机 离开了北京 …


使用git和github 进行代码的版本控制

1. 为什么要使用

可能在国内,有很大一批程序员还有团队都喜爱用subversion。 其实我也一直在使用, 但是随着项目到了后期, 需要不断对分支进行工作 。 而subversion扯分支与合并分支显得过于繁琐。 相反git的优势就在于方便的扯分支与合并分支等操作。 git同时采用了本地化的版本控制,这意味着不需要远程服务器也可以进行代码的 commit和add等操作。github 提供了一个免费的 git remote 平台。 github.com

2. git的工作原理

git 和 subversion 最大的不同就是 仓库管理是本地化的 不像subversion所有版本库的管理都是通过一个中央服务svnserve来完成. 这意味着 我们不需要有远程的服务器就可以在本地进行 git commit/add/branch 等操作。 而远程服务 (github) 扮演的角色只是当前版本库的一个远程存储。 通过github 来共享你的代码,实现团队的合作。

3. git & github 的安装和注册

(a) github 的注册

https://github.com/signup/free

(b) git 的下载安装
如果是ubuntu 用户应该可以很方便地安装  直接运行 apt-get install git 就可以了
如果是CentOS 用户可以按照以下步骤进行git的安装
1. yum install gettext-devel expat-devel curl-devel zlib-devel openssl-devel (安装必要的库)
2. wget http://kernel.org/pub/software/scm/git/git-1.7.0.1.tar.gz
3. tar xvfz git-1.7.0.1.tar.gz
4. cd git-1.7.0.1
make prefix=/usr/local all
make prefix=/usr/local install

(c) ssh key 的生成

http://help.github.com/msysgit-key-setup/

可能在进行git remote 操作的时候 需要进行加密通信, 所以就有了这一步去生成key 的操作吧( 对于加密方面我也不是太懂             )
ssh-keygen -t rsa -C “tekkub@gmail.com”

粘贴pub-key 到 https://github.com/account

4. git 命令简介

(a) git clone
举例 git clone git://github.com/schacon/grit.git
从远程 克隆一个

(b) git status
查看当前版本库的状态

(c) git add
添加到版本库
例如:git add folder

(d) .gitignore
添加 .gitignore 文件到版本库根目录下 然后编辑文件可以 设置需要被忽视的文件和文件夹 举例如下
# a comment – this is ignored
*.a # no .a files
!lib.a # but do track lib.a, even though you’re ignoring .a files above
/TODO # only ignore the root TODO file, not subdir/TODO
build/ # ignore all files in the build/ directory
doc/*.txt # ignore doc/notes.txt, but not doc/server/arch.txt

(e) git commit
进行一次提交
git commit -m “first commit”

(f) git pull [remote-name]
从远程 获取版本库 默认的 remote-name 都是 origin

(f) git push [remote-name] [branch]
将本地push 到远程 可以选择push 的分支是哪个分支

http://progit.org/book/ch3-1.html
英文好的朋友可以认真读一下这一节 这里详细介绍了 git 分支工作原理

(g) git branch [branch-name]
创建一个分支

(h) git checkout [branch-name]
将当前工作环境 移到指定分支上

(i) git mergy [branch-name]
把指定分支合并到当前分支上来

5. (推荐)BASH脚本

1. ship

#!/bin/sh -x
# Git workflow ship script from: http://reinh.com/blog/2008/08/27/hack-and-and-ship.html
# git name-rev is fail
ref=$(git symbolic-ref HEAD 2> /dev/null) || exit 0
CURRENT=”${ref#refs/heads/}”
git checkout master
git merge ${CURRENT}
git push origin master
git checkout ${CURRENT}
把代码保存成 vim ship 并且 chmod +x ship
这段shell 的意思就是 自动切换到主线 并且把分支合并到主线 并且push 到远程上 再切换到分支状态。  方便地用户分支提交代码
2.hack
#!/bin/sh -x
# hack: Merge the latest changes from the master branch into your current branch
ref=$(git symbolic-ref HEAD 2> /dev/null) || exit 0
CURRENT=”${ref#refs/heads/}”
git checkout master
git pull origin master
git checkout ${CURRENT}
git rebase master
这段shell 的意思就是 自动切换到主线 并且从远程更新到最新状态  然后切换到分支 把主线合并到分支上   方便用户及时把当前工作分支更新到最新状态

6. 参考文献

http://progit.org/book/

http://www.how-to-linux.com/2009/01/install-git-161-on-centos-52/


回忆(一) 知春路

今天中午同事们一起吃饭,无意间聊到了找工作的话题上 ,貌似关于这个话题 大家有扯不完的见解。 当然也让我不禁想到了自己刚开始找工作的前前后后。

掐指算下来在外学习工作已经有5年的时间了.  这些年可能体会最大的就是 命运是由自己把握的。可能打小就喜欢计算机, 大学期间 也就很情理的把自己的专攻路线定位了IT这个方向。当然感谢 胖爷师傅 这位好室友 把我引上了这条路。 记得刚开始学Java是大三的暑假,也正好是北京奥运期间, 从那时起才领悟到学习是为了自己( 要是高考能有这觉悟估计清华北大也不是没可能 哈哈 )。 也是从那段期间 开始了第一次租房经历, 也庆幸有俩位非常好的朋友和我一起学习度过那个暑假。  刚开始接触Java是很枯燥的。因为天天都是学一些很基础的东西。硬是坚持把1本书 给完完整整的 啃了下来。 然后又配合视频学了2个月左右。 下学期开始后也制作了自己的一份简历。 投简历的过程是痛苦的, 因为千万份简历投出去 就像一块巨石投到水里 连个泡都不冒下的那种感觉。 有时人也变得非常沮丧,不过机会总是有的, 终于在那个十一接到了人生的第一次面试通知。面试我的是一个年龄也不大的研究生,  因为是一家创业性质的公司,所以很幸运,以当时的技术也勉强被应聘上了。

第一份工作可以说是我有史以来感觉压力最大的一份工作 因为什么都不会, 再加上 小Leader 也有点小急性子, 搞得我天天 神经紧绷, 那时候的生活描述可以说是非常简单  睡觉 公交 工作(每天5个小时在地铁和公交上真不知道怎么熬过那段时间的)。 感觉之外的事情很难能够挤入我的 时间里边来。 也记不清楚 自己第一个项目是怎么,最后倒腾出来了, 不够最后还是顺利上线了, 这时候以为能够歇一口气了, 不过没完, 接着无数的bug被发现,改吧,于是又埋头苦干地扎进代码里。 这才体会出 从事IT 行业 就会让你觉得睡觉 是人生最幸福的一件事情。 清晰的记得第一次领工资的情景, 那天特别开心,和俩猪头一起 空着肚皮 然后撑着腰地走出了好伦哥, 当时的情景就是连笑一下 都觉得肚子离得鸡翅就要飞出来似的。 随后公司也在开始慢慢成长 也来了不少新同事。 还记得我们那时候的 小 四人组 ciny neo iori 还有我 rocky.(i miss you so much.)  当然还有型男 james 你那炯炯有声的大眼 很难让人忘却。那时候 我 neo iori 各负责一个 游戏项目 然后 ciny 负责做 美工。大家都是80后,沟通无阻 一起吃一起玩。  估计知春路那附近所有的 小餐馆 都已经被我们吃了个遍当然在这里我非常怀恋 扁豆焖面  大拇指。(可惜成都压根就没听说过)。 不过这样的日子没持续太久, 由于在工作中的问题 neo 离开了公司, 其实那是我第一次见到 员工的辞职, 心理 其实有一种 很惋惜的感觉, 没想到 刚成为好朋友的大家 又要彼此 各奔东西。 之后公司新项目要用到新的技术 , 所以我们也继又开始学习, IT 行业就是这样 不断的学习, 不断的GOOGLE. 可以没有书 但不能没有GOOGLE( 说到google就会想到天朝 ). 我也有了新的leader(是一个中科院博士哦 :) ).  公司规模不断扩大, 也开始尝试做一些更大的项目。 我和iori 在那段时间也搬家到了公司附近住, 所以也就有了更多的 休息和学习时间。 没事也会去去旁边的 北航玩玩。 转眼间春节到了。 还趁着当时自己学生的身份 很幸运的买到了一张坐票。 北京的春运 真可谓一票难求。 短暂的春节后, 又开始了自己第二年的征程…