七八月份有几件事情想做:
这一年
一年前的大概这个时候,我正好从超图离职,加入创新工场二期助跑团队——邻伴。在半个月之前我的女儿刚好出生,紧接着@焕德 给我打电话邀请我加入他们。那一刻,我的人生仿佛展开了一条崭新的道路,我梦寐以求的道路。
时间再回到去年的3月份,那是我最困惑的时候,项目已做到让我厌倦,想走,却又没想好要做什么。当时恰好部门内要做LBS平台,最开始由我负责技术这块。这个时候,我又重新燃起了热情,一想到自己所学的东西终于能在大众领域里有所应用,那是无比的兴奋。但是好景不长,经过几个月之后,我发现事情并不能如我所愿的进行下去,总有处理不完的其它的琐事,部门也不能投入很多资源来做这个事情,况且我的热情也快消失殆尽了,于是萌发了出去做LBS的念头。于是便进入邻伴。
以上是背景,在崭新的道路面前,有几点让我特别兴奋,
- 接触,学习创业。
- 能做自己喜欢做的LBS的事情。
- 加入创新工场。
而这些兴奋就是我在邻伴时候的鸡血。
在邻伴的日子是令人怀念的,在那里我完整地经历了一个产品的生命周期,完整地经历了创业的失败,也完整地经历了创始人的人间蒸发。在邻伴,我通宵的时间比之前三年都多,那是一段打满了鸡血的日子,我喜欢那样的日子,那仿佛是我青春的尾巴。而我之所以从超图离开,也正是因为我想找到这样的日子。在邻伴,我欣赏@焕德 的镇定,他让我看到了一个leader该有的气度,我也喜欢他不在的时候,我做了我和他两人份的开发的工作,那让我看到我自身的能量。
虽然很遗憾,不管什么原因,邻伴最终失败。但不能否认的是我们的确是一个不错的团队。有两个人说过喜欢我们邻伴的团队,一个是@白斗斗 , 另一个是我老婆。生命中的诸多细节总是充满了暗示的意味,我相信我们那个时候的日子会是一如那个初次聚会的咖啡馆的名字——那是最好的时光。
过了十一,我加入了计划FM团队。加入计划FM主要是因为@李天放 ,毫无疑问,天放是一位极优秀的工程师,我希望从他身上学到一些东西,提高自己开发的水平。事实也是如此,从天放身上我学会了(或者说天放教会了我)诸多东西,而这些东西开发进阶的必经之路。而之前长时间的瓶颈,也正是因为缺乏这些东西。可以这么说,如果不是天放,我的程序观,价值观会大不相同。
天放教会我的第一件事情,便是命名。由于我的英语水平并不好,命名的时候名词动词不分,单数复数不分,所以最开始code review的时候,天放总要帮我改参数、函数的命名。后来在蔡学墉的微博中,我才发现有命名肌这一说法,而命名肌也是每个开发的人必须锻炼的一块肌肉。
命名是第一步,做好命名的目的是提高代码的可读性。代码即注释。这也解决我长期以来的一个困惑,对于一些复杂的逻辑的部分,哪怕我写了非常详细的注释,还是要花很长的时间才能理解代码,而将复杂的逻辑分离,再辅以良好的命名之后,代码立马变得清晰起来。
第三,保持简单,无论是代码还是逻辑都是一样。天放极度推崇简单,推崇甚至有些洁癖的地步。大部分时候,天放是有道理的,因为如果你的逻辑都很难理解,那自然用户也就会很难理解这些东西,而这样做出来的东西多半是不对的,很多时候需要重新去想一条更合适的路出来。
第四,保持简单的一个最佳检验办法就是写单元测试,如果一段代码很难写出覆盖全部case的测试,那么这段代码很可能是有问题的,要么代码太多复杂,要么这个类有问题。这种时候我们就需要重新考虑这些代码了。
恰好这几天,我正在看@焕德 留给我的《重构》这本书,看了书我才发现重构的许多基本思想,我已在天放的潜移默化中学会,掌握,并践行着。天放对我的影响绝不仅限于开发这方面,他让我深刻体会到“你要跟优秀的人一起工作”这话的正确性,也深受其益。
这一年以来对我影响最大的是无疑是对我价值观的修正。在超图的那段时间,我几乎每隔一段时间就要去想,我是要成为项目经理,还是一个优秀的工程师。我可以成为项目经理,事实上我的头衔也是项目经理。但我本能地反抗,因为那不是我加入超图的目的,那不是我的梦想。但一个残酷的事实便是你只能成为一个项目经理,因为那才是工程师在超图的唯一进化方向。我现在可以很清晰地说出那时困惑的原因,那是价值观的冲突。但那时的困惑难以解答,因为我不知道是否存在我所推崇的价值观的公司,仿佛工程师文化的公司只存在于国外。而这一年以来的经历让我相信工程师文化是合理并大有裨益的。而和一群观念相同的人工作,那是一件多么让人愉悦的事情。而每天处于冲突之中,只会耗尽你的潜力。
这一年以来我的第二个收获便是自我管理能力的提升,工作效率的大幅提高。在这之前,我的人生似乎总存在着一个悖论,像我这样的人究竟能不能做出一些成就。因为我可以吃苦,可以非常勤奋,但这一切的基础便是我一定要有极大的热情,如果我没有热情,那么我的工作很可能是工作效率及其低下的。在邻伴也是这样的轨迹,我可以像打了鸡血一般疯狂工作,但鸡血毕竟有限,你不可能永远保持这样的状态,所以在邻伴的最后一个月,无论我的状态还是效率都已经非常糟糕。我总是跳不出这样的怪圈,所以之前我只能是不停地寻找我的兴趣点,然后靠着这兴趣提高我的工作效率。所以我的工作状态总是一阵一阵的,挺不稳定的。
但这种状态在今年改善不少。很多时候我更加了解自己的状态,我可以也调整自己的状态,甚至有些时候我还能强迫自己进入状态。所有这一切归功于天放给我介绍的番茄工作法,那真是算自我管理的神器了吧。
如上所述,这一年以来我的改变不少,也对自己今后要走的路更加清晰,少了份困惑,多了些信心。别人说25岁是个尴尬的年龄,我同意这个观点,不过我很快就不尴尬了:)
博客@工具
马尼拉终于可以放到网上了
节约时间就是在浪费生命?!
想到这个命题,挺奇怪的。生命的意义究竟是什么?从微小的受精卵,到懵懂的孩童时期,再到化为尘土。人终究是在这个世界上留不下什么东西的。所有最后成空,那普世的价值观又有什么意义呢?那既然如此,人为什么要去节约时间?
我想这一定有一个悖论,人应该去做自己想做的事情,而节不节约时间是自己的决定,这不是价值标准。就像马斯洛的人的5个阶段,我想那也是在普世的价值观下的金科玉律,跳出这个价值体系,那唯一存在的就是存在本身吧。
很有意思,存在本身也是多少小说家,哲学家热议的东西,或许存在对于每个人的意义就像诗歌一般,每个人都是自己的诗人。
与存在对应的就是救赎与信仰,存在如同一道难题,而解开这道难题的,很多时候人们用的就是信仰。我不排斥信仰,但我还没建立起自己的信仰,所以我才那般害怕,那般恐惧。
存在对于存在本身,或许这才是我们要用一生去解答的终极难题。
戒Dota两周
戒Dota、微博、口袋妖怪两周,空闲时间看看书,看看王小波。
Ejabberd使用ruby做用户验证(extauth_program)
背景
使用ejabberd做聊天服务,最大的问题是怎么跟现有的系统对接,其中最重要的就是用户系统如何对接。而这一点,ejabberd已经为我们考虑到了,为了方便不会使用erlang的开发者使用自己的用户系统,ejabberd提供了extauth_program这个配置,从而可以使用任何可执行的脚本作为用户系统的接口。其中perl语言的demo在ejabberd srouce的example里就有。而更多的配置可以参考Authentication Scripts,你可以使用非常多的语言和数据库,包括perl,python,甚至php,c#。其实你用任何语言都没有关系,因为毕竟只有短短几十行代码,你唯一要做的就是设置好你的数据库参数。
我的尝试步骤
但是不幸的是官方给的参考里是没有ruby脚本的(有脚本,但是页面已经失效),于是乎我在网上狂搜extauth ruby的实现,还好找到一个据说有点问题的ruby代码ejabberd not exec my script ,那人就是因为执行不了所以才发帖求助的。于是
- 我copy了他的代码,然后稍作了修改,配置好extauth。果然执行不了,没有任何反应,连我设置的log都没有输出来。而ejabberd的log是extauth 脚本意外终止,原因是normal
- 于是我做了个测试,将所有的代码都删掉,只保留log的部分,结果还是没有log,而我用ruby执行是有log
- 这让我一度怀疑ejabberd不支持ruby,于是我换用ejabberd source里的perl脚本,结果一切工作正常。
- 我误认为ejabberd不支持ruby,于是我放弃ruby的方式,在网上down了Authenticate Against MySQL with Perl,修改后run,结果发现跟1的结果是一样,无法运行。
- 既然有一个正确的,一个错误的相同语言的脚本,那我就可以比对哪里导致运行失败了。比对的结果是4下载的sql没有执行权限,于是我chmod a+x,4运行正常了,但我仍然不能正确登录。
- 在perl console环境中一步步执行4的脚本,发现原因是我缺少sql lib的支持。于是准备换用python脚本。
- 在修改python脚本支持的时候,我意外发现所有的文件开头都有一行#!/usr/bin/perl这样的注释,我突然明白为什么我的ruby脚本不能执行了,因为它不知道怎么去执行,于是在ruby文件开头加上了#!/usr/bin/env ruby,这个世界顿时清净了。后来想起我好像在鸟哥的私房菜里边见过这些东西,后悔看得太草了。
要点
- 你的script本身要能正确执行,即有执行权限,而且是可执行的(第一行有类似#!/usr/bin/env ruby的注释)
- 正确配置extauth。如下: {auth_method, external}.%%这是要点 {extauth_program, “/var/lib/ejabberd/db_auth.rb”}.
- 没有第三了。
下载
a ejabberd extauth script write by ruby
参考资料
下个月的打算
从三月开始,到现在两个月的时间。期间想做太多的事情,很多事情起了个头,就放在那里了,所以决定从5月开始收一收了。做完手头上想做的事情。这些事情分别是:
- 12306 自动登录【闲置】
- 英语阅读工具【放弃】
- 妈妈说——为我弟做的语音记录提醒Android软件,5月6号之前完成【done】
- 马尼拉——html5游戏【done,完成基本版本】
- 图图的blog【闲置】
- 在家里——给老婆做的东西,还没开始做,6月份再做吧。【看情况】
Ejabberd部署
我们选用ejabberd作为我们聊天的Server,原因是可以1、erlang性能高2、用得人多。 经过两天的折腾,我终于在三台不同的系统上都装上了ejabberd,分别讲讲这三个平台的安装经历。
Mac
ejabberd有Mac下的dmg安装包,有可以通过source安装。
- 我的第一次尝试是直接使用了ejabberd的dmg安装包,结果执行postinstall脚本的时候出错,服务起不来。没有具体的错误提示。
- 所以换用source安装的方式。先装的erlang 15B01,然后安装ejabberd 2.1.10版本。结果使用/sbin/ejabberdctl start 没有任何反应。通过netstat看发现没有5280端口。于是换ejabberdctl live命令,发现提示是端口冲突。后来想起来我装过openfire,于是卸载掉,重新启动,还是出错。
- 后来发现erlang 15B01出的比ejabberd2.1.10还晚,怀疑是版本问题。于是卸载erlang 15B01,换用erlang 15B。
- 装好之后,重新安装ejabberd,好像就没什么大问题了。
- 启动访问http://localhost:5280/admin%E3%80%82%E6%98%AF%E5%90%A6%E8%83%BD%E5%87%BA%E6%9D%A5%E9%A1%B5%E9%9D%A2%E3%80%82
Cent OS
直接用source安装的,安装完之后没什么问题,有问题可以参考下面的资料。
Ubuntu 10.10
- 我首先是直接用apt-get安装的erlang,结果一看,版本是5.9.1就是15B01,所以就卸载掉了。
- 后来手动安装erlang失败,发现缺少依赖库
- 所以必须先安装下面的东西
- sudoapt-get -yinstall\ build-essential m4 libncurses5-dev \ libssh-dev unixodbc-dev libgmp3-dev \ libwxgtk2.8-dev libglu1-mesa-dev \ fop xsltproc default-jdk
- 安装完erlang后,又手动安装了ejabberd,结果启动总是不成功。
- 后又换apt-get安装ejabberd,启动时提示几个文件有权限问题,我直接chmod 777就搞定了。
- ubuntu中启动ejabberd是这样启动的,/etc/init.d/ejabberd start。不要用ejabberdctl,会失败。
排错指南
- 在start之前检查下epmd, beam, beam.smp等是否启动了,如果启动着,先把他们杀掉,他们是erlang相关的东西。
- 检查是否有应用占用了5222,5223,5280等端口,5222端口是xmpp协议本身规定的,所以默认是用此端口。如果之前装过其他的XMPP server请停止或卸载,比如OpenFire
- ejabberd有很重的erlang依赖关系,所以一定要对好版本,参考下面的资料。
- 如果不需要配置,也是可以启动服务的,所以无法启动不是配置的问题。
- 如果start没什么错误提示,可以改用status或者live方式启动,这样错误会明显一点,如果还是没有错误提示,只能到/var/log/ejabberd底下去看了。
参考资料
- ejabberd 简明配置
- ejabberd 简明配置2
- ejabberd清理
- ejabberd清理2
- Installing Erlang/OTP R14B04 on Ubuntu 11.10 from source tarball
- E: Sub-process /usr/bin/dpkg returned an error code 解决办法
- odbc : ODBC library – link check failed
- Debian package difference
- installing-erlang-on-mac-os-x
- ejabberd与erlang版本对应关系(重要)
- ejabberd安装配置指南(不太有用)
- Debugging ejabberd
漫漫破解路
前言
11年是个值得纪录的时刻,12306的推出改变了人们购买火车票的方式,以前是挤火车站,现在是挤12306。于是在这个中药的时刻,各路人马各显神通,自动登录,自动购票,自动刷票等应运而生。最著名的要数zzdhidden的项目,一时间不管IE,firefox,Chrome,只要是想要买火车票的,基本都装上了那个脚本,好不风光。
但好景不长,由于铁道部发现了验证码不刷新的漏洞之后,以上方法通通失效。但我还是不甘心,我还是希望能够有一个东西至少能实现自动登录。
思路
铁道部的验证码其实并不算复杂,我觉得只要能对它进行OCR,我应该就能实现自动登录。我特意在在线OCR的网站上进行了测试,结果还是比较理想的,自动登录的验证码是可以被识别的。于是就进行了漫漫破解路,我到目前为止还是不清楚,最终能不能成功。
难度
铁道部用了HTTPS的方式访问,连图片也是HTTPS的方式,而且在上回修复验证码不刷新的问题之后,验证码已经没有可能性越过,只能硬碰硬的方式进行破解了。
尝试
第一次
我的第一次尝试确定验证码跟的确定跟什么有关,cookie?page?js的隐藏的东西?还是说通通相关。我的做法是打开浏览器,打开登录页面,再打开另外一个页面,再输入验证码的地址。然后在之前打开的登录页面中输入后一个页面的验证码,结果登录成功。由此可以得出结论,cookie只跟session相关,跟page是无关的。
第二次
第二次尝试,是测试是否只跟session相关。我在Chrome中打开登陆界面,然后用ruby模拟同一个session去抓取验证码。结果却很让我失望,登录失败。所以,由这个试验可以得出的是因为是HTTPS的协议,在每次连接的时候就默认有个session的概念,所以用cookie的那个session是模拟不了的
接下来
在经历了前两次的试验之后,我觉得还剩下两条路:
- 获取cache中的图片,然后传给验证码破解服务网站,得到验证码之后,提交
- 做一个https代理,拦截验证码的请求,破解后传给用户。
从用户的角度来讲,我觉得用户很难相信一个代理,第二如果真以这种方式实现的话,我的服务器压力也受不了。所以我优先去尝试第一种方式。于是就有了我的第三次尝试。
第三次
用户缓存中的图片。通过搜索,发现在IE下可以用cache api,或者可以将图片拷贝到剪切板。Chrome下可以通过访问chrome://cache/。但怎么把这些图片传给我的服务器呢?我觉得无论是IE还是Chrome,肯定有权限的限制,于是没往这条路上深入。
第四次
还是想要在客户端传图片给我的解析服务。于是想到了HTML5的本地存储。于是在测试之后发现这个办法还是不可行。因为碰到了安全沙箱问题。在调用canvas.toDataURL()时会报SECURITY_ERR: DOM Exception 18错误。
1 2 3 4 5 6 7 |
|
第五次
但突然峰回路转,后来我分析了沙箱问题的原因是我在本地文件做的测试,而图片的域名是12306的,所以会造成跨域的问题。所以后来我小测试了一下,在Chrome的插件Script里执行上述代码,结果发现不再出现上述错误了。解决这最头疼的跨域问题以及图片获取问题之后,接下来的问题就是怎么把图片数据传到我的OCR服务器了。
于是我也是先做了个简单的试验,将获取到的base64数据post到我的OCR服务器,OCR服务base64解码,再存成文件。我一看是张完整的完整的图片,高兴坏了。
第六次
但当我把OCR的结果传回到客户端时,意外发生了,客户端怎么也没有收到。通过抓包显示,post请求被cancel掉了。后google之,发现正是js的跨域问题,即一个站点的js无法请求另一站点的js的数据。幸好这块都有成熟的解决办法,通过伪装成Script请求的方式进行数据提交。或者直接就用JSONP的方式。这个方式有一个问题,就是不能使用POST方式进行数据的提交了。但图片的大小(base64)有4K以上,怎么才能把图片完整地传到服务器端呢?(因为get有2K的大小限制)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
第七次
get方式提交我想了两个办法,一是多次分批提交数据,服务端再进行组合。而是利用多个cookie进行提交,这样只用一次请求就可以传完了(cookie的长度限制是4K)。但我在进行cookie测试的时候,失败了,原因是我在12306的域名下无法访问另外一个站点的cookie。所以只能采用第一个办法。
第八次
那下面就是苦力活了。只要传好数据,ORC之后回传给浏览器,再进行登录就好了。我在做这一步的时候碰到挺多问题的。
- 是jquery的getJSON方法总是无法触发callback方法,不知何故。没办法,我只能用complete方法代替callback方法进行触发。
- 由于是分批次的上传图片数据,要注意图片的顺序问题。所以应该是一个接一个地传。
- ruby的默认session同样有4K的大小限制,因此需要改成数据库的方式进行sesison的存储。http://www.cslog.cn/Content/ruby_on_rails_sessions/ https://github.com/nmerouze/mongo_session_store/issues/8
- 提交之前需要encodeURIComponent一下
结束
至此,破解12306从设想变成了现实。其实回过头来看看,其实也不是很难,但充满了惊险刺激。比大学时做ACM的题目更加兴奋。