记录过去的周末-2011.08.08

周六,是所谓的“七夕节”,其实很想给老婆过个浪漫的节日的,但是我的浪漫细胞实在是少的可怜,也弄不出什么花样来,加上老婆现在又挺着个大肚子,还是小心为妙,等生完在补上吧,周六早上起来后合计了一下,决定和老婆去运河文化广场边上逛逛,顺便呼吸下新鲜空气,河边的空气真的很不错,被包裹在一片青草味里面很是舒服,运河边上的木船居然开张了,算了下一天也有个7~8波客人,也不少赚钱呢。今天唯一比较失败的地方就是,美丽的LD被晒坏了肩膀,主要是太阳不是很强烈的缘故,没怎么在意,结果就大意了,以后还是多多注意点为妙。
周日,先把上周从IKEA买回来的桌子拼装起来,发现自己很适合搞这个,照着说明书组装东西的乐趣也蛮大的呢,LD主要休息,散漫到黑天,然后决定去买菜,包饺子,等吃上已经是快9点了,下次再有吃饺子的想法得早点动手,今天7点才开工时有点小失败,后半节就是饿着肚子包了,呵呵。
英语该按照计划来了,今天把Project计划打印出来,给自己施加点压力吧,努力过了就好了。
有时候还是不自觉的跟LP拌嘴,过去了总觉得很抱歉,可是又说不出来,希望以后逐步改掉吧。

周五工作总结

每周记录下零星的收获吧,无论对心情还是以后的技术或多或少有点益处的吧,大部分摘自weibo/twitter
先上技术类:
1. discuz论坛装插件,/forumdata/目录要有可读可写的权限,今天被坑了好长时间,直接从线上复制下来的程序,到本地解开后属性丢了,最后才想起来权限的问题。
2. Nginx+fastcgi报错502/504,解决方案已经写这儿了
3. Mysql权限开通: grant all privileges on game_stat.* to webgame@’10.3.16.26′ identified by ‘webgame’;flush priviledges;
现在插入生活:
1.在家抓紧时间看书-学习,这个摆在第一位。
2.照顾好LP和小宝。
3.地铁路上无聊看网络小说,不过好多没结局的,以后提前搜下,没结局的就不看了

discuz的那点事儿

背景介绍:目前的论坛是直接使用Discuz!搭建的,版本比较古老,一直没人动过,从我接收就一直感觉是个烫手的山药,不是说处理不了(凭我浸淫php多年的经验,想来这点毛毛论坛还是可以拿下的,只是前人改过不少代码,注释也没有,于是一直懒得动),但是最近产品部说要整改论坛了,只好捡起来从头开始研究,记录下点滴。
本文先说下跟人人网连接,直接使用connect那套系统就行了,简单的很。
1,引入一个JS,比如命名为connect.js

function addScript(src) {
   var scriptElement = document.createElement("script");
   scriptElement.type = "text/javascript";
   scriptElement.src = src;
   document.getElementsByTagName("HEAD")[0].appendChild(scriptElement);
}
function connectDyload() {
  addScript("http://static.connect.renren.com/js/v2.0/FeatureLoader.jsp?loaded=connectInit");
}
function connectInit() {
  XN_RequireFeatures(["Base"], function(){
    XN.Main.init("efc590d209f847c1ae0d830dcb99c972", "/xd_receiver.html", {"doNotUseCachedConnectState":true});
    XN.Connect.c(function() {
      document.location = "http://www.rrgbbs.com/toGamebbs.do?tid=&redirectUrl="+window.location.href;
    });
  });
}

其中,connect成功后的跳转地址,自己写了个java类,toGamebbs,这个类用来调用Discuz!的一系列验证方式,比如判断用户是不是登录过了cdb_session表,然后新用户的话,自动在后台帮助用户完成注册功能。
2.把模版中的header.html的登录块注释掉,换成connect的代码


登录
{lang logout}
3.修改全局变量template/default/templates.lang.php,把home_welcome_guest修改为上面类似的登录模块

人人网用户请直接点击登录,以浏览更多精彩内容,并随时发布观点,与大家交流。

4.需要在本地放一个跨域文件xd_receiver.html




    





更多renren connect的原理,可以参考官方网站 http://wiki.dev.renren.com/wiki/%E4%BA%BA%E4%BA%BAConnect

HttpClient模拟操作https网站

在日常工作中,我们常常需要抓取一些网站的信息为自己所用,比如自动抓取天气预报啊,抓取sina的股票数据,某些图片网站的美图等等,这就需要spider出场了,其实每种语言都有自己的写法,比如在Linux下,第一眼想到的就是wget,这是个强大的工具,可以递归地抓取网站,有windows下的版本,在本文章中还是说下Java的方式,那就是著名的开源软件HttpClient,在使用HttpClient的时候,我们需要知道网站的运行方式,可能在中间跳转了好几次,为了看到这些信息,我们还需要一点工具,Firefox的话直接中Httpfox就可以了,在IE下可以使用Httpwatch,官方下载地址是这个http://www.httpwatch.com,具体的使用很简单,不会的可以参考这个:http://www.cnblogs.com/mayingbao/archive/2007/11/30/978530.html
完事具备了,我们来看看怎么使用Httpclient

public static HttpMethod loginXN() throws IOException {
                PostMethod post = new PostMethod("http://passport.renren.com/PLogin.do");
		NameValuePair user = new NameValuePair("email",
				"zhangsan@hotmail.com");
		NameValuePair pwd = new NameValuePair("password", "12345");
		NameValuePair domain = new NameValuePair("domain", "renren.com");
		post.setRequestBody(new NameValuePair[] { user, pwd, domain});
		return post;
}

如果是https的请求,略微麻烦一点,需要使用SSLProtocolSocketFactory,在new HttpClient实例的时候,需要指定一下。

public static String httpGet(String url,Header header) {
        Protocol myhttps = new Protocol("https", new SSLProtocolSocketFactory(), 443);
        String result = "";
        HttpClient httpClient = new HttpClient();
        GetMethod getMethod = new GetMethod(url);
        getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
                new DefaultHttpMethodRetryHandler());
        int statusCode = 1000;//默认代码Connection refused
        try {
            httpClient.getHostConfiguration().setHost("passport.dudusp.com",443,myhttps);
            getMethod.addRequestHeader(header);            
            statusCode = httpClient.executeMethod(getMethod);//执行getMethod
            if (statusCode == HttpStatus.SC_OK) {
                result = getMethod.getResponseBodyAsString();
            }
        } catch (Exception e) {
            log.info(e.getMessage(), e);
        } finally {
            getMethod.releaseConnection(); //释放连接
        }
        return result;
    }

公司的passport验证原理

最近为了安全考虑,出了套验证机制。passport处理未登录用户的过程大致为:
1.用户访问应用服务器A
2.如果用户未登录A,自动重定向到passport服务器
3.passport验证登录成功后,返回验证票
4.应用服务器A使用验证票到passport服务器进行二次验证
5.passport二次验证成功后,返回用户名

根据上述处理过程,passport的使用方法为:
1.passport的请求地址为:passport.no.xxxx.com;
2.应用服务器请求passport页面时,需提供forward跳转参数;
3.passport接收请求,验证正确的情况下,返回验证票(ticket参数);
4.应用服务器二次验证的过程为:
1)构造HTTP REFERER请求头;
2)携带HTTP REFERER请求头,远程读取passport.no.xxxx.com/verify.php?t=$ticket(该$ticket为 passport返回的ticket)地址的内容;
3)如果passport验证成功,返回用户名,否则返回空串。

passport的使用示例如下(以MM系统为例http://mm.renren.com/index.php):
1.MM请求访问passport的地址:https://passport.no.xxxx.com/login.php?forward=http://mm.renren.com/index.php
2.passport验证成功后,将地址重定向到http://mm.renren.com/index.php/index.php?ticket=nscr3omh80rn367h5pu0dq76u0
3.MM系统处理passport验证票($ticket参数)的过程为:

   function auth_check_valid($ticket){
       if($ticket == "")
           return false;

       $opts=array(
           'http'=>array(
               'header'=>"Referer :".$_SERVER['REQUEST_URI']
           )
       );

       $context = stream_context_create($opts);//构造HTTP REFERER头   
       $url = "https://passport.no.xxxx.com/verify.php?t=".$ticket;
       $user_id = file_get_contents($url,false,$context);//二次验证,远程请求用户名       
       return $user_id;//返回登录用户名,需进行后续判断是否为空串
   }

在接下来的文章中,我们会进一步讲解如果使用程序模拟登录验证系统,该怎么处理。

linux shell program – for in 循环语句的用法

在写一个小脚本时,需要循环显示每月日期当参数,传递给请求的地址。大脑一拍,直接用for循环做了,如果python可以直接使用for xxx in range(0,32),那么Linux是不是也有类似的写法呢,答案是正确的,不过略微有点小改动。语法如下:
for 无$变量 in 字符串
do
$变量
done
利用for in格式对字符串按空格切份的功能,直接遍历,于是上面的字符串我们可以随便定义,只需空格隔开即可。

SERVICES="22 80 25 110 8000 23 20 21 3306 "
for x in $SERVICES
do
    iptables -A INPUT -p tcp --dport $x -m state --state NEW -j ACCEPT
done

for i in a b c 字符串列表A B C
字符串用空格分隔,没有括号,没有逗号, 然后循环将其依次赋给变量i.变量没有$
于是我们的日志处理脚本,可以这么写了

#!/bin/sh
DAYS="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31"
for dst in $DAYS
do
/usr/bin/wget "http://gamecenter.renren.com/weige.jsp?y=$1&m=$2&d=$dst" -O a.txt
done

Nginx出现502和504错误提示的解决方案

今天在测试机器上搞了个web论坛,discuz的,还算轻车熟路,直接用nginx+fast-cgi,搞了几下就运行一起来了,可是没多久就出现问题了,访问首页的时候,总是提示502或者504的,很是郁闷,潜意识里觉得是fast-cgi没搞正确,在度娘上搜了下果然如此,简单记录下吧。
Nginx 502 Bad Gateway的含义是请求的PHP-CGI已经执行,但是由于某种原因(一般是读取资源的问题)没有执行完毕而导致PHP-CGI进程终止。
Nginx 504 Gateway Time-out的含义是所请求的网关没有请求到,简单来说就是没有请求到可以执行的PHP-CGI。
一般来说Nginx 502 Bad Gateway和php-fpm.conf的设置有关,而Nginx 504 Gateway Time-out则是与nginx.conf的设置有关。
php-fpm.conf有两个至关重要的参数,一个是“max_children”,另一个是”request_terminate_timeout” ,但是这个值不是通用的,而是需要自己计算的。
解决办法如下:
1、调整php-fpm.conf的相关设置:

32
60s

2、调整nginx.conf的相关设置:

fastcgi_connect_timeout 600; #set timeout
fastcgi_send_timeout 600;
fastcgi_read_timeout 600;
fastcgi_buffer_size 256k;
fastcgi_buffers 16 256k;   # 16*256,可以继续调大
fastcgi_busy_buffers_size 512k;
fastcgi_temp_file_write_size 512k;

关于fastcgi buffer相关的日志,可以参考这篇
3、终级解决方案: More

性格测试MBTI

上周五参加公司的管理员工培训,没想到比较无聊乏味的讲座居然听得还不错,是讲解一个很牛逼的性格测试的,MBTI测试法,可能有的同学以前做过,不过本人还是第一次接触。
MBTI的基本就是把测试分成了四纬度,是有版权的,不好多加评论,感兴趣的同学,可以自行研究这篇文章-MBTI性格测试,精髓也算讲到了。
用字母代表如下:

精力支配:外向 E — 内向 I
认识世界:实感 S — 直觉 N
判断事物:思维 T — 情感 F
生活态度:判断 J — 知觉 P

其中两两组合,可以组合成16种人格类型。

本人的性格是ISTJ类型的,准确度自己感觉高达90%以上,LP大人和我正好互补,真是不错,据说同一类性格的人不适合在一起工作,比较乏味的说,用之生活亦是如此,嘿嘿。
—————
沉静,认真;贯彻始终、得人信赖而取得成功。讲求实际,注重事实和有责任感。能够合情合理地去决定应做的事情,而且坚定不移地把它完成,不会因外界事物而分散精神。以做事有次序、有条理为乐—不论在工作上, 家庭上或者生活上。重视传统和忠诚。

ISTJ型的人是严肃的、有责任心的和通情达理的社会坚定分子。他们值得信赖,他们重视承诺,对他们来说,言语就是庄严的宣誓。 ISTJ型的人工作缜密,讲求实际,很有头脑也很现实。他们具有很强的集中力、条理性和 准确性。无论他们做什么,都相当有条理和可靠。他们具有坚定不移、深思熟虑的思想,一旦他们着手自己相信是最好的行动方法时,就很难转变或变得沮丧。ISTJ型的人特别安静和勤奋,对于细节有很强的记忆和判断。 他们能够引证准确的事实支持自己的观点,把过去的经历运用到现在的决策中。他们重视和利用符合逻辑、客观的分析,以坚持不懈的态度准时地完成工作,并且总是安排有序,很有条理。他们重视必要的理论体系和传统 惯例,对于那些不是如此做事的人则很不耐烦。ISTJ型的人总是很传统、谨小甚微。他们聆听和喜欢确实、清晰地陈述事物。ISTJ型的人天生不喜欢显露,即使危机之时,也显得很平静。他们总是显得责无旁贷、坚定不变 、但是在他们冷静的外表之下,也许有强烈却很少表露的反应。

您适合的领域有:工商业领域、政府机构 金融银行业、政府机构、技术领域、医务领域

您适合的职业有:

· 审计师
· 会计
· 财务经理
· 办公室行政管理
· 后勤和供应管理
· 中层经理
· 公务(法律、税务)执行人员
· 银行信贷员
· 预算分析师
· 保险精算师
· 税务经纪人
· 税务检查员
· 机械、电气工程师
· 计算机程序员
· 数据库管理员
· 地质、气象学家
· 法律研究者
· 律师
· 外科医生
· 药剂师
· 实验室技术人员
· 牙科医生
· 医学研究员
· 信息总监
· 电脑编程员
· 证券经纪人
· 会计
· 文字处理专业人士

例行周末记录

经历的痛苦的几天煎熬,老婆大人的肚子终于在周末到来的时候好起来了,这是个好事情。总结原因,还是前几天午饭的时候冷热混着吃造成的,生冷冰凉的东东以后还是少碰了,算是为了宝宝着想吧。
周末的天气不错,温度也很宜人,下雨之后的感觉就是不错,可是好景不长,到周日晚上就感觉又开始闷了。
记忆有点空白,实在想不起来周六干什么了,似乎就在家里呆了一天,写了几段php代码,然后陪着老婆看了个《在云端》的小制作电影,感觉还不错。然后跟LD念叨了半天将来的规划,学习的任务依然很严重,移民越来越难,得加快步伐,需要定一个进度表了,依次来激励下自己。
周日去宜家买桌子,恰逢宜家搞活动,来的真不是时候,people moutain and people sea ,停车都花费了半天的功夫,此行的另外一个目的就是来吃传说中的牛肉丸,每次必点的啊,哈哈。
为了老婆,为了下一代,继续努力奋斗吧,再者,经历过了也是一种收获。
好多单词还是认识拼写不出来,郁闷。
Pronunciation and spelling is very very important .
The proliferation of the internet is increasingly playing a pivotal role in contemporary society (inour daily life). And whether going to english training school or learning it by the internet has sparked spiritual debates.

mysql bit field

在前面的文章中,我分享了目前在项目中使用的一个很好用的python脚本,《IP log analysize and record》,python脚本很简单,懂得python的朋友应该都很容易看懂,在本片文章中,重点讲述一下在mysql操作中的一点注意事项。
首先,我们来分析一个场景:用户访问一个站点的时候,我们把用户的访问行为记录了下来,这点无论是Apache还是Nginx都能很好得把access log记录下来,可能一个用户一天会访问好多次,但是我们的统计需求往往只会要求判断某个用户在一段时间内的登录情况,比如腾讯朋友空间的日活跃情况,细节只是定位到天,好了,我们的pv就变成了uv,但是uv的明细表依然很庞大,我们可以继续压缩,把每个用户每个月的访问情况,压缩成一条记录,这个时候,Mysql的一个特殊的字段类型 bit就出场了,一般情况下我们定义为 bit(31)即可,每个月一张表,用户的访问情况可以如下: More