给wikipedia和gnu捐了点钱

前两年每到年末的时候就会看到wikipedia的网站上号召大家捐款,当时一没有 paypal,二没有钱,所以都没有捐。今天终于如愿了,还顺带给FSF也捐了。想 想我最喜欢的几个公司:google用不着我捐钱,apple我已经“捐”了不少了:)。 So… paypal-record

Posted in 互联网周边 | Tagged , , | Leave a comment

配置openvpn

自从google频繁被墙之后,生活太难受了,没有google就没有知识了啊,别的搜 索引擎的结果真是没法看,什么bing, yahoo, duckduckgo都试过了,没有一个 满意的,我想我已经太依赖google了。还好后来搞了一个EC2的免费一年的主机, 装上了pptpd,用上vpn之后生活好太多了,开着vpn的时候,想着整个Internet 任我浏览感觉太爽了。但是我的pptp经常连接不上或者连接一会儿之后就自动断 开了,不知道是什么原因。

将就了一段时间,正好这个周末没什么事,就研究了一下如何用openvpn。搞了两 个多小时,终于完事了。这个过程不是那么顺畅,我想自从我 搞定了我们寝室的路由器之后,我很久没有钻进去折腾了。导致 我决定要布署openvpn的时候竟然不知道从哪里开始,我先google了下”ubuntu setup openvpn”,然后到了ubuntu社区的文档,讲得好复杂,什么PKI证书什么的, 看得眼花,主要是我对网络安全这一块没有什么理解,只是当时学这个课的时候 看过一点书。然后我又点开了一个链接,是一个人做的一个比较详细的pdf讲解如 何在ubuntu上布署openvpn,我下来一看,发现还是太难看懂了。然后我就有些不 知所措了,心里有些失落:难道我的hack能力已经如此不堪了吗?还好后来我被 一个链接带到了openvpn的网站自己的documentation上,一看明 了多了。现在回过来看,还是因为我太急躁了:这种情况下官网还是要更权威一 些的, 凡事都想通过google直接出来结果是不太可靠的。记得曾经看过文章说搞技术的 有两种人:一种是很能搜,到处找找,乱七八糟搞一搞就完事了;另一种是很能想, 甚至闭着眼睛就能把事情演绎出来。我觉得搜和想还是要平衡一下:想是内功, 想得越多懂得就越多,但是搜体现了一个人活跃程度,一个不活跃不太能折腾的 人是搞不成技术的。所以我认为:既然想,就深想,再多搜

废话了这么多,说说怎么布署openvpn:

服务器端

  1. 安装openvpn和bridge-utils

    sudo apt-get install openvpn bridge-utils
    
  2. 生成一个static key:

    openvpn --genkey --secret static.key
    
  3. 写配置文件,vi /etc/openvpn/server.conf,写入以下内容:

    dev tun
    ifconfig 192.168.0.1 192.168.0.100
    secret path/to/static.key
    
  4. 可以启动openvpn server了:

    sudo /etc/init.d/openvpn start
    

客户端

  1. 安装openvpn的客户端,其实openvpn同时包含了server和client:

    brew install openvpn
    
  2. 安装tuntap,去其主页下载,解压安装就行了。

  3. 从服务器把static.key拷到客户端。
  4. 写配置文件,vi client.conf,写入以下内容:

    remote server.addr
    dev tun0
    ifconfig 192.168.0.100 192.168.0.1
    secret /path/to/static.key
    
  5. 运行客户端:

    sudo openvpn client.conf
    

在客户端通过ping 192.168.0.1测试vpn连接是否建立成功。注意EC2的话要 去打开1194端口。测试能ping通之后,还是不能上网,因为这相当于在客户端 和服务器分别新增了一个网卡,而这两个网卡是连通的。如果要访问互联网,需 要将客户端的网关设置成服务器,并且在服务器上增加转发规则

设置客户端的网关

修改系统的路由表就行了:

  1. 单独增加服务器的路由项,因为如果没有这个,客户端到服务器的路就彻底 断了。

    sudo route add server.addr original.gateway
    
  2. 删除原来的default路由项:

    sudo route delete default
    
  3. 增加新的default路由项:

    sudo route add default 192.168.0.1
    
  4. 在网络偏好设置里修改DNS为8.8.8.8,不修改DNS会导致twitter和facebook 上不去。

设置服务器转发

增加一条NAT规则,要确保ip forwarding已经打开。

sudo iptables -t nat -A POSTROUTING -s 192.168.0.100 -j MASQUERADE

这样就已经设置好了。

Posted in 互联网周边 | Tagged , , | 1 Comment

第一次elance工作经验

我从很早就开始想在elance上找个工作,赚点钱。因为我觉得靠写代码赚钱总比 做助教,家教好一些。但我一直觉得不太靠谱,因为每次看到招标的项目,下面 都一堆方案,有的是个人,有的是有组织的,reputation都挺高,似乎都很厉害, 作为一个新人似乎没什么机会。但是暑假的两件事情促使了这一进程的加快:

  1. 我学习了ruby和ruby on rails,ruby是一门很有意思的语言,后来我学了 emacs lisp才知道,原来跟跟lisp是如此的像,而ruby的作者Matz也说过他是如 何受了emacs的启发的。学了之后让人跃跃欲试。
  2. 我的笔记本电脑在火车上被偷了,我向同学借钱买了Macbook Air,负债不小, 所以我想挣点钱争取早日还他们。

过程

  • 然后我登陆了我很久以前注册的elance账号,填写了一些基本的信息。然后做了 两个技术测试,一个是C语言,一个是ruby。C语言我做得不错,95%;而ruby就 很一般了,毕竟不熟,很多基本的库用法都不了解。得了62%。然后就一直没去 管它,因为正逢找工作的时候,忙着准备面试什么的。
  • 过了一段时间,我收到一个来自elance的邮件,说我被邀请去申请一个工作。注 意这不是那种几乎每天都有的”Latest Job Recommendations”。我 点击那个链接直接就到了那个职位的页面,然后我填了一下Proposal,没填什么 东西,就是说明一下我对编程很感兴趣。
  • 过了几天有人给我发邮件说要进行一个面试,直接约了第二天早上8点的时候。 是个菲律宾的HR,没谈技术,就是问一下我的基本情况,比如是学生还是已经毕 业,比如有没有ruby的编程经验等。还好我有之前 面facebook的口语经验,我没有畏畏缩缩,而是有点自信地告 诉他虽然我没有相关的工作经验,但是我曾按照《Agile Web Development with Rails》上的例子写过一个完整的网站。然后他说好,过段时间会给我发 一个”Trial Assignment”,如果通过的话会得到300$并且受雇于DevFactory。 最后问他他们是不是只招有实际工作经验的人,他说不是,但是你必须要会用 ruby开发,他说我在你这里看到了激情,所以我打算给你一个机会。现在 回想起来这真的很重要,如果我不够自信而吞吞吐吐的,那么我连这个试一下 的机会都没有了。
  • 之后就有个人(另外一个,不是HR)给我发了一个邮件,布置了一个为期一个 星期的任务。用一个docx发过来的(居然不是pdf),说得挺详细的,包括你 可能会需要去了解的知识,都给出了链接。任务是为em-ftpd写一 个backend,将数据存储在Amazon S3上面。任务的要求有几点:
    • 实现ftp的基本功能,包括文件的上传和下载
    • 实现安全的用户认证
    • 实现安全的文件传输
    • 自动化的测试,包括RSpec和cucumber
    这些对我来说都是新东西,但是好在我之前对ftp还是有过 一定的了解,所以慢慢地了解之后发现并不难:对S3的操作有现 成的gem,实现安全连接有他提示的start_tls,rspec和cucumber大致了解一 下就能写。
  • 花了三四天的时间,写得差不多了,就给他发了过去,等大概有5、6天他才回 邮件,说了一个我实现上的问题,最后一句话是:

    Other than that, not bad. So I’m about to accept it:)

    揣摩了多次觉得他的意思应该是已经接受我了。但是针对他提出的问题, 我发邮件问他需不需要改一下再发给他,他说不用,这个作业已经完成了,不 用再动它了,你很快会有exciting的任务。后来我还问他”When should I get paid”,他说2-3天就会收到。

  • 果然,过了2天,我的elance账户里收到了270多美元(elance需要扣一定的费 用)
  • 又过了几天,他加了我的skype,为我创建了DevFactory的账号,这就算正式 加入DevFactory了。

最后不得不说一下钱的事

因为在中国,要把这笔钱变成可花的人民币还是要费一些劲的。我认为最好的办 法就是去开一个paypal账号,然后elance可以免费地把钱转到paypal里,从 paypal里可以把钱转到国内的银行,但是每一笔需要35$,所以好的做法应该是 等钱攒到一定程度的时候再转回来。

其实elance提供了直接转到国内银行账户的途径,叫bank transfer,如果直接转 美元需要25$的手续费,但是如果转欧元或者其他的就可以每个月免费转一次。但是因为最后 要转回人民币,所以这中间会有一些损失。我计算了一下,1000$的时候转美元和转欧元大概 都要损失150¥,小于1000欧元划算,大于1000美元划算。

Posted in ruby, 互联网周边 | Tagged , | 5 Comments

从开放源码获益

这两天把系统从Lion升级到了Mountain Lion,过程很顺利,对新系统很满意。 但是也有几个小问题:

  1. /usr/bin下之前被我删掉的几个程序升级系统后又出现了,比如gdb, emacs等,因为我用homebrew安装了更新的版本。
  2. 旧版本的Xcode不能用了,需要安装Xcode4.5,没有Xcode意味着没有开发工 具和命令行工具,比如gcc等。
  3. 之前安装的texlive没有被加在PATH里,需要手动再添加一下。

除此之外,我之前的所有配置都保留得很好。这真的是一个“让人省心的系统”。 新系统在UI方面有一些小的改进,一个是用Preview看pdf的做标记的时候,黄色 的线条不再是平平整整,而是拟真地有些起伏状,像手工画的一样,不过分,很 优雅(见下图);二是整个系统特别是桌面背景的配色让人觉得很优雅,我女朋友 第一眼看到的时候就说了一句“好漂亮”。

mark in preview

上面说到的一些小问题都很好解决,但是我安装gdb的时候却出现了一些问题, gdb-7.5在Lion下完全没有问题,但是在Mountain Lion下却出现类似下面的警告, 无论是我自己编译的还是通过brew安装都是一样,google了一番也没有找到解决 的办法,应该是苹果对Mach内核作了一些改动,而gdb的源码还没有更新以适应 这一改动。

BFD: /Users/rockuw/freeman/cpp/a.out: unknown load command 0x2a
BFD: /Users/rockuw/freeman/cpp/a.out: unknown load command 0x28
BFD: /Users/rockuw/freeman/cpp/a.out: unknown load command 0x29
BFD: /Users/rockuw/freeman/cpp/a.out: unknown load command 0x2b
BFD: /Users/rockuw/freeman/cpp/a.out: unknown load command 0x2a
BFD: /Users/rockuw/freeman/cpp/a.out: unknown load command 0x28

继续执行是没有问题的,只是这些警告很烦人,在emacs里进行gdb的时候这些警 告更会使整个buffer都凌乱了。我开始想没办法了,只能等gdb出新的版本。但 是因为最近在看《The C++ Programming Language》,我想可能会用到emacs里 的gdb,所以又回来看能不能把这个问题解决。最初还是google,但是没有效果。 我又编译了一下gdb-7.3,也不行。最后突然想到:我不是有gdb的源码吗?只 要把代码打印这个警告信息的代码去掉就可以了。于是欣喜万分。直接行动: 先找到打印这些信息的代码:

grep 'unknown load command' . -R

发现是在bfd/mach-o.c里的第20063852行:

case BFD_MACH_O_LC_PREBOUND_DYLIB:
case BFD_MACH_O_LC_ROUTINES:
case BFD_MACH_O_LC_SUB_FRAMEWORK:
    break;
default:
    (*_bfd_error_handler) (_("unable to write unknown load
command 0x%lx"),
        (unsigned long) cur->type);
    return FALSE;
}

正确的做法应该是理解这些case,然后进行修改,但我采用的是偷懒的办法, 直接把error_handler这行给删掉了。删掉后进行configure, make,再试 果然没有问题了。通过修改软件的源代码来解决问题确实非常爽。这不禁让我想 起了之前看过的Coding Horror上的一篇文章, 讲拥有源代码的必要性:

I encourage developers to git clone anything and everything they depend on.

open source真的意义非凡,很有魅力。

[注意]自己编译的gdb要经过签名才能正常使用,具体请参考 这里

Posted in emacs, Mac, 默认分类 | Tagged , , , | 4 Comments

用emacs写博客

我之前一直是vim的忠实用户,vim自称是“世界第二的编辑器”,我们都知道第一 的是emacs。我之前也大概体验了一下emacs,但是没有认真去学它,因为刚接触 编辑器觉得vim就够用了,后来零零星星地学了很多vim技巧,自己的.vim文件夹 也逐渐丰富起来,但是一直都有一种“不爽”的感觉,这些感觉来自于我需要不 断地去键盘上找ESC来切换mode,需要不断地按Shift来把中文输入法切换到英文 模式,需要不断地navigate来打开不同的文件…等等。今年十一的时候正好没什 么事,于是开始想学学emacs这个至高圣器,先看了emacs自带的tutorial,然后 上网搜索,企图找到比较完整的一个教程,结果是找到了一本书:《Learning GNU Emacs》,在寝室窝了几天,把这本书看了个大概,基本达到了可以感受 emacs的威力的境界。

我这里不想介绍emacs的特性或者技巧,因为这些在网上已经够多了。(以 “emacs tutorial”,“emacs cheat sheet”为关键字就能搜到一大把优质内容。) 上一篇博客是用emacs写的,感觉非常良好,所以我想介绍一下用emacs写 markdown的一个过程:

  1. 首先,你要了解markdown的语法。这个还是比较简单的,一学 就会。
  2. 然后你要为emacs安装markdown-mode,安装的方法也比较 简单,跟着链接里的方法走就是了。
  3. 写作的过程就是用markdown语法typing的过程,非常舒服,整个过程如行云 流水一般,你可以听到连续的敲键盘的声音。markdown-mode下语法会有高亮显 示。
  4. 非常值得一提的是check reference的功能,你在文章里可能会引用到别 的内容,这时你不需要停下来去把引用补全,而是作个标记,等文章写完之后, 用C-c C-c c这个命令检查引用,它会把引用都列出来,等你挨个处理。见下 面的截图。 markdown-text check reference
  5. 引用也处理完了之后,就可以生成HTML了,用C-c C-c m命令,把生成的 HTML文件拷贝,然后贴到wordpress的编辑器里就可以了。你甚至可以用C-c C-c p命令在浏览器里进行预览。
Posted in emacs, Mac, 默认分类 | Tagged , , | 3 Comments

找工作

昨天晚上和今天早上的两封拒信,标志着从9月初开始的找工作进程基本结束。一 路走来,把各大公司都摸了个遍,到最后收获的却还是最初的两个公司:阿里和 亚马逊中国。既然已经不沾此事了,就可以把它们都拿出来说一说,以过去为镜, 总能看到一些东西。

按时间顺序,我面的公司有:

  1. 豆瓣,笔试被拒
  2. 阿里巴巴集团,offer,杭州
  3. 亚马逊中国,offer,北京
  4. 百度,笔试被拒
  5. 搜狗,笔试被拒
  6. Google中国,笔试被拒
  7. 腾讯,一面被拒
  8. 微软,面试被拒
  9. Facebook,面试被拒

豆瓣

豆瓣是找同学内推的,最最开始,大家都还没什么动静,我突然被豆瓣的文艺气 质吸引,想去试试。很快就收到了笔试的通知,是通过邮件发过来一套题,要求 在一小时内做完用邮件发回去。我觉得答得还可以,两个代码题我都编译运行过, 虽然后来想想还是有一些问题,但是也不至于直接被拒啊。不太明白…过了一段 时间我发邮件问HR是什么情况,他给了一个相当于没说的回复:有消息我会尽快 通知你。呃…我觉得这个着实是不厚道,豆瓣招的人也不太多吧,为什么不能认 真地对待每个应聘者。我想,相对于死无消息,大家都更喜欢收拒信吧:)

阿里

接下来是声势浩大的阿里的招聘。阿里在来之前就接受了无数的内推,几乎我们 学院每个同学都是被内推的,在它来之前已经确定了面试的时间。由于 志龙哥在推荐的时候把我的手机号写成了那个被偷的移动号,我没 有收到面试通知短信,没有这个短信连宣讲会的门都进不去…还好当时 振兴哥挽着我的手直接跟HRMM推荐了我,她才让我进去。宣讲会 完了还进行了一个笔试,就两道题。我答得还算不错,第一题代码写成,第二题 给出了一个并不是最优的办法。当天晚上收到了面试的短信。

面试是在一天全部结束,由于面试的人太多,面试那天我观察了一下,每个同学 的平均等待时间是2个小时,我还算幸运,只等了大概一个半小时。两面,一面是 个支付宝的工程师,开始拿着简历挑他感兴趣的问,根据相关的背景出些难题。 我被问到的包括:个性化推荐技术,服务器集群,cache,大数据处理等。重点问 的是如何实现一个哈希表,如何让它线程安全,如何避免用锁。这个我之前在腾 讯实习的时候了解过相关的技术,算是答得还不错。后来他暗示我等二面。二面 是三个人,一个HR,一个是支付宝的技术经理,一个是阿里的老员工(第58号员 工),二面也问一些技术,但是更重要的是聊人生理想:)比如,你的偶像是谁? 你有没有特别铁的哥们?能体现你的执行的一件事情是什么?阿里和腾讯你会选 哪个?你在你们实验室排行第几?我说这个也没人排过,他说江湖嘛,是江湖就 一定有排行…我不是很谦虚地说数一数二吧:)阿里的人确实有些江湖气息,这个 从他们每个人的“花名”也可以看得出来。有些人说是“邪气”,我倒觉得挺好的。 二面聊得挺欢的,说到宝哥借钱给我买电脑的事情,我还有些自我感动…

当天晚上就收到电话了,第二天去酒店开个会,签了一个录用意向书。到了那里 才知道,哈尔滨就招了5个人,4个研究生和一个本科生。那天终面的面试官和HR 们都在,跟我们聊了聊阿里巴巴集团的现状,隐农的一句话让我印 象深刻,他说:决定去哪个公司,我就考虑两点,一是给多少钱,二是进去之 后会不会把我做废了。我常用第二句话作为不去国企和研究所的坚实借口:)后 来我跟来自阿里云的面试官深入交流了一下,因为正好在此之前我在看redhat的 openshift,对云计算比较感兴趣。当时签的意向书是阿里云。前 天收到阿里云的HR电话,说了一下待遇和福利,加上我对杭州这个城市还是很有 好感的,已经有了一半的心思想云阿里了。

亚马逊中国

亚马逊中国一直是我最想去的公司,一是因为它是外企,有机会可以移民;二是因 为它不向微软那样,一定是用Windows;三是因为陈皓。亚马逊的笔 试是在线编程测试,我开始没在意,以为还会有现场的笔试,所以在线测评做得 不好,没有收到面试通知。我一下就着急了:这可是我的第一志愿啊。于是毅然 决定去霸面。霸面没有直接被拒之门外,也没有很顺利。他把我们(我和 小刚)的简历收了,然后说有面试安排会通知我们。

下午我在去华为面试的路上收到亚马逊的电话,于是直接弃了华为去了亚马逊面 试。两面:一面是HR加一个技术经理,也是先问了问简历,然后让在他的笔记本 上写代码,求一个链表的长度,我一开始说就是从头开始扫瞄到尾然后统计长度。 他说你还要考虑其他的情况,我反应过来,说可能有环是吧?他表示对的。现在 回过来看,跟微软和FB相比起来,这种面试真是太轻松了:允许你试错。后来我 比较快地把代码写了出来,他看了觉得挺满意的。接下来问了一个设计题,说亚 马逊的一些商品经常会打折,有的是直接打8折,有的是买3件以上打7折,等等。 要求设计一下这个系统应该怎么设计,把相关的类定义写出来。我想了想,应该 有订单类,物品类,折扣规则类,然后派生出具体的折扣规则类。订单在结算的 时候把所有折扣规则应用到订单里。他看了觉得还行。我继续说明如果折扣的规 则比较复杂的话,可以定义一门规则描述语言(DSL),像SQL那样,这样的话它 的描述能力就会更强。他也表示赞许。之后就是聊了些关于亚马逊的东西。有趣 的是,他们后来也问了一个跟阿里问的一样的问题:如果我们和腾讯都给你 offer,你会选择哪一家?我说“亚马逊是我的第一志愿”,这在当时来看是真心话。

二面主要是coding。一个较年轻的面试官,上来先客气了几句,然后就说了一个 题目,要求写代码编译调试。二面的题目是在线测试时的第二题。(十一的时候 我学了emacs和lisp才知道其实就是elisp里的表达式求值)我当时就没有做出来, 直接是0分。我也跟他说明了情况,他说那我们就换一个题,不会两次用同一个题 难住你的。我说不不,我的意思是我对这个题已经有足够的信心了。他说那好, 就这个题吧。我去霸面之前写了一个递归的版本,放在gist上,他表示 不看那个,现在要我写一个非递归的。我开始构思用栈写一下,开始遇到一些问 题,后来我用了三个栈,硬是把程序写了再来,debug了一会儿之后大体是正确 了。他也觉得还算可以吧。我自己倒感觉不好,因为开始的问题耽误了一些时间, 开始有些紧张。变量名都想不出来,好几个temp。后来要走的时候我问他会不 会再去看我的代码,他说“肯定会的呀,我们来招聘一趟不容易,我们会考察每 一个合适的人”,然后我向他说明了变量名起得不好,他表示可以理解。

总体感觉亚马逊是个很节俭的公司,不像微软那样财大气粗。过了几天收到了亚 马逊的电话,这给了我莫大的安慰。因为那时正逢百度和搜狗双双在笔试阶段就 把我拒了,有些失落。还有是因为想起跟国宝说过的话,微软和亚马 逊各有一半的把握,他笑着说那不是稳了吗?两个都去不成的概率只有1/4。而 今终于等到了亚马逊。

百度、搜狗、google中国

这三个都是笔试未过,百度我一直不太喜欢,所以也没有去霸面,而搜狗我觉得 是个小公司,不是很想去,加上今年他招的人也确实太少了。google中国,确实 是我水平不够,准确地说,是ACM水平不够。

腾讯

我对腾讯一直很有好感,因为之前在那里实习的时候,觉得公司和人都还不错。 abel,我当时实习的导师,曾经给了我莫大的鼓励。这次没有去腾讯一 是因为腾讯来得太晚了,二是因为我之前一直想的是去亚马逊。所以没有考虑去 腾讯了,但是腾讯的笔试和面试我还是去参加了,就像会一个老朋友一样。一面 是个soso的人,他看了看我的简历和我的笔试试卷(我看到是80分,算挺高的 了),大致问了问,了解到我曾去即通实习过。然后他直接就说:你知道我是哪 个部门的吗?我说不知道。他说:我是soso的,怎么样,感不感兴趣?我当时感 觉是不太喜欢去soso或者说不太想去他的部门的,于是我没有说肯定的话,而是 问了一下他的部门具体是做什么的,他大致说了一下,又问:怎么样,感不感兴 趣?还要不要继续下去?。我说这个我要考虑一下。然后气氛就有些尴尬了。最 后我说:这个现在就要回答吗?他说:那好吧,我们继续。然后问了三个题。我 答得一般,不是很好,但也不差。后来走的时候我因为感觉不是很好,特意主动 和他握了手…

出来之后我就已经感觉到不会有二面了,但是也不是特别失望,因为这个面试官 和soso对我并没有很大的吸引力。不过后来想想也确实是我的问题,既然我决定 去面试了,就要主动去争取这个职位,否则这对面试官也是一种不尊重。如果我 对这个部门不感兴趣,那也可以要求转到别的人那儿去面试。虽然对我来说去面 着玩玩并没有什么,但是这对面试官来说就不是什么好事儿了。

微软

这是我第一次面微软,本科的时候参加过一次笔试,但是没有得到面试通知。今 年实习生招聘的时候我没有网申,所以没机会参加笔试。这次我也确实是懈怠了, 准备得不够,导致面得不是很好。两面,一面先问了问一些基础知识和小题,然 后是写一个代码。小题有一个没答上来,代码是N个数中找中位数,用partition 的方法,我写得很利索,也没有问题。一面结束后到我问问题的时候,我问了面 试官在微软是不是大家都用Windows,他回答得很肯定:为什么不用Windows?有 什么事它干不了的吗?我有些较真,又问了句“是要求的吗”…

二面的气氛就有些紧张,刚开始的时候面试官让我用C++写一个上三角矩阵的类。 C++的语法我不太熟,导致我写的代码漏洞百出。后来又让写拷贝构造函数和运算 符重载,我也没完全写对。再后来要我说如何存储一个稀疏矩阵,我从naive的方 法说起,一直到后来的用哈希表存储,总算是说对了。但是这个过程却不是那么 舒服,微软的面试官跟别的不一样,他并不欣赏你能从naive慢慢地领悟到最优 的答案的过程,而是希望你think through之后再对他说。因此我有些受挫,因 为很多时候我把第一想法说出来之后他立马就不是很高兴地说“不对”。两面都感 觉出来,微软的面试官有些傲慢,他们似乎觉得自己高人一等,而希望面试者以 一种低微的姿态出现,比如当我说到我用ruby的时候他们就立马跳过。

回来之后我还是抱有挺大希望的,结果晚上12点左右收到了拒信,是HR发的邮件。 略有失望,尽管我一直不想去微软工作,但是拿到微软offer这样一件事情还是 挺值得吹牛的。收到拒信之后想想,其实还是自己做得不对,自己也不是多牛逼 的人,犯不上处处露锋芒,根本就不应该表现出对soso不感兴趣,不应该现在出 对Windows不爽。面试的时候当然面试者姿态要低一些,难道还要面试官求你去?

facebook

因为今年有个学弟非常牛逼,拿到了去FB总部实习的offer,他去了 之后,就推荐了一些校友,我也去凑了一下热闹,结果还真收到FB的面试了。一 共面了三次,一面是HR,先来跟我聊聊基本情况,告诉我整个招聘的过程,告诉 我要注意的一些事项等等。对我来说,这也是为我的口语进行了一下热身。

一面是一个工程师,居然是中国人。问了我一道题:简单的正则表达式匹配。只 有.*两种特殊符号,比如ab*a能匹配aa, aba, abbba等。我想了 想不知道该怎么做,后来他说我们先不考虑*,如果只有.的话该怎么做,并 让我把代码写出来。我写完之后他说你能写一个递归的版本吗?我用递归写了一 个。后来他说我们现在来考虑有*的情况,当遇到*时,分两种情况,一种是 消耗掉一个b,一种是不消耗。我恍然大悟,告诉他我知道了,然后他让我写 代码,我写的时候边界情况考虑得太复杂了,最后也没完全写对。面试结束的时 候用中文聊了聊,感觉他人还是很友好的,还给我留了邮箱,说有什么问题可以 找他。

本来我想可能已经没有下一面了,但是过了一周多收到邮件。这次还是个中国人, 但是应该是级别更高的人,因为他从头到尾都没有说过中文。这次做了两个题, 感觉比上次更好一些。第一个题是一个有序的数组被shift了,找出shift的那个 点。我其实是听说过有O(log n)的解法的,但是不知道具体怎么做,于是说了 一个O(n)的做法,写出代码之后,有些情况考虑得还是不够,但是大体是对的。 然后是第二题,一个大文件里存了一些整数,统计不同的整数的个数。我想到的 是用bitmap的方法,记录每个整数是否出现过,最后再统计不同整数出现的个数。 这个题答得很好。答完之后,面试官好像发现上个题里我的代码的问题,又回到 上一个题,挑出几个毛病。我改了改之后他说OK。面试结束时也聊了聊…

我感觉二面比一面好,满心期待会有on-site的面试,结果今天早上收到拒信。 唉…其实一面真的是面得不好,没有想到递归,经提示后写的代码也不是干净利 索。二面总体感觉好一些,但是第一题没有勇敢地去尝试O(log n)的解法。所 以失败也是意料之中。

面试总结

都面完了之后,发现一个另人不安的真相:我拿到的offer就是一开始的那两个, 后来就没有收获了。回想这段时间里的心态,就是懈怠+自大,对于大部分 面试是持一种“不过也无所谓”的态度,而对facebook是一种“我不可能通得过”的 态度。太消极了…面微软败在C++语法下真是太狗了!

去向

只能从亚马逊中国和阿里云里面挑一个了,阿里给的待遇非常不错,而且杭州也 是我喜欢的城市,所以不出意外的话,我可能是要去杭州了。想起之前信誓旦旦 地说要去亚马逊然后移民,真是羞愧难当。因为发现自己竟是那样的不堪,犹犹 豫豫的人。

Posted in 互联网周边, 意见/挑剔, 默认分类 | Tagged , , | 7 Comments

程序员必须要懂数学

程序员必须要懂数学,要不然太容易被鄙视了!!!,就算:

  • 你会架apache, nginx, mysql, oracle,会写网页……
  • 你会诊断网络,会iptables, 会tcpdump,懂IPv6……
  • 你精通C语言,写得一手好汇编,精确知道一个程序的内存布局……
  • 你会vim,会emacs,脚本写得溜……
  • ……

你还是得懂数学,要不然,真的很容易被鄙视的。今天在HOJ上碰到一个题:将N划分成若干个正整数,使它们的乘积最大。我想了一会儿,觉得应该是分成若干个2相乘吧,结果信心满满地交了,WA了。后来在google一顿找,好不容易找到了这里,原来答案是尽可能地分成多个3相乘……更令我震惊的是,那个网站居然是收集各种整数序列的,而这个题的答案恰巧是其中一个序列,它们有什么联系?为什么是3?感觉自己像个白痴一样……还有之前做了没过的几个题,都是这个鸟样子,什么Pollard’s rho整数分解网络流……今天做豆瓣的笔试题时,最后一个我看到“高地”,“水流”这些字眼,生怕是道网络流的问题……还好不是……

感觉不会点数学太容易被各种鄙视了,面试的时候人家不会问你apache怎么配置啊,vim怎么用啊,网络出问题怎么诊断啊……而是把你当数学家来面。一不小心就会被当成“低等码农”,这种感觉,真是……忍辱负重啊。虽然我一直觉得折腾一些好玩的东西比学算法有趣,虽然Paul Gramham说程序员不必有math envy,但是从今天开始,本  神  也要进军数学了,每天学一点点,希望多年以后不会再被他们鄙视了……

Posted in algorithm, 意见/挑剔 | Tagged , , | 7 Comments

正式投入ruby怀抱

很久以前就纠结过到底是python还是ruby?当时经过粗浅的调查选择了python,但是发现做完了它的tutorial,学了学django之后就不知道该如何前进了。因此搁浅了好一段时间,后来不甘寂寞,再次去学ruby,发现真的很有意思,正好放暑假了,就下了两本书回家看。一本是《The Ruby Programming Language》,另一本是《Agile Web Development with Rails》。在家看书记录不良的我,居然把这两本书都看完了!然后决定以后一心向ruby……

ruby给我印象深刻的有这么几点:

  1. 文档真的非常多非常好。你去ruby-lang.org上看它的文档,真的是很多很好。Try Ruby!是一个网页版的交互教程,给人耳目一新的感觉。然后有好玩的RubyMonk,奇怪的Why’s(Poignant) Guide to Ruby,也有很正式的Ruby User’s Guide。ruby给人一种“好玩”的感觉。正像作者所说的,他发明这门语言是为了让程序员体会到“幸福”。

  2. 函数调用可以不加括号。这使得有时候代码看起来更舒服。比如下面的代码:

    puts rand 100
    
    class A
      private
      def sayhello
        puts "hello"
      end
    end
    

    上面的private其实是一个函数调用,它没有带参数。

  3. block的使用。ruby中每个函数都默认接受一个block,在函数中使用yield来调用block的代码。比如下面的代码,是最有ruby特色的:

    5.times do 
      puts "hello"
    end
    
    1.upto(100) do |i|
      puts i
    end
    
    
  4. reflection。第一交接触reflection是学java的时候,学得不明不白。这次看ruby的reflection,觉得豁然开朗。在ruby里,每个类都是Class类的一个实例。比如下面的代码:

    class A
    end
    

    我们可以理解成它定义了一个类,名字为A。但是实际上A是一个常量(ruby中大写字母开头的变量是常量),A是Class类的一个实例。另外,ruby不仅可以为一个类添加方法,还可以为特定的一个对象添加方法。比如所有的String对象都有upcase这个方法,你还可以为单独一个String对象添加方法:

    a = "hello"
    class << a
      def sayhello
        puts "hello"
      end
    end
    

    这样你就可以在a上调用sayhello: a.sayhello,而其他的String对象却不具有这个方法。比较奇妙的是,类的静态方法,也可以按这种机制来理解,比如下面:

    class A
      def self.sayhello
        puts "hello"
      end
    end
    
    class A
      class << self
        def sayhello
          puts "hello"
        end
      end
    end
    

    因为A其实是一个变量,所以A的静态方法其实是变量A的方法。这就使得概念统一了起来。

  5. rails。很多人是因为rails才顺便学的ruby。rails真的是我见过的最好的框架,它几乎将Web开发的各个方面都考虑到了,而且很周全,包括数据库、缓存、Ajax、REST、i18n等等。而《Agile Web Development with Rails》这本书,也是写得最好的书之一,先是一步一步地构建一个完整的网站,然后再详细介绍rails的框架,看完之后收获良多。之前感觉做一个网站虽然不难,但是毕竟是件挺费劲的事,有了rails,你就能快速地开发出一个好的网站。

Hackers and Painters的作者曾说过,一个hacker所用的语言,应该是一门脚本语言,因为它不不需要编码-编译-运行-修改-编译-运行这样繁琐的步骤,它可以让你像雕塑家一样,一边创作一边修改。我相信我已经找到了我的语言。

Posted in ruby | Tagged , , | 4 Comments

openwrt+buffalo G300N V2路由攻略

寝室用的是校园网,要用锐捷进行拨号。锐捷对共享上网作了一些限制,比如拨号的机器不能有两个网卡,所以一般都是每人一个锐捷账号。而一般的路由器都只支持PPPoE的拨号方式,所以也不能通过路由器来进行锐捷拨号。为了能够共用一个上网账号,节省网费开支,网络上有很多“破解”的方法:

  • 有人破解了锐捷的客户端,让它允许客户端有多个网卡
  • 有人干脆就破解了锐捷的协议,写了一个拨号软件
  • 有人为路由器重新定制了一个操作系统,予之无尽的可能性

其中的mentohustopenwrt,堪称神器。mentohust几乎是全平台支持(Windows, linux, Mac OS, 嵌入式linux),而openwrt也支持了很多的路由器。

我之前在Mac OS下用pfctl实现网络共享中写过如何利用mentohust和NAT来进行共享上网,这种方法的缺点就是拨号的机器必须一直开着,因为它是网关。我的笔记本要是一直开着,既不环保又影响机器寿命。所以我一直在寻求一个capable的低功耗设备来做网关,由于对路由器知之甚少,我原以为它的交换和转发功能都是直接由硬件来实现的,我甚至想过搞个ARM开发板,因为上面运行着linux啊。直到后来了解了dd-wrtopen-wrt,才知道原来路由器可以干这么多事。

下面是我们寝室的软硬件和网络环境:

网络结构

  • 路由器:Buffalo WHR-G300N V2 亚马逊链接
  • 路由器固件:openwrt trunk

注:固件是自己编译的trunk版本,openwrt官方没有这个路由器的固件,但是可以采用openwrt-ar71xx-generic-whr-g301n的版本,因为硬件是一样的。也可以去下载别人已经编译好的固件

下载固件刷到路由器之后(方法在这里,推荐用tftp的方法),经过简单几步就可以让客户端上网了。我刷的是没有网页界面的自己编译的简洁版,因此下面的方法都是修改配置文件来进行的,有界面的可以在界面上进行相应的设置,当然也可以修改配置文件。

  1. 第一次登录需要用telnet来设置初始密码:telnet root@192.168.1.1,设置完成之后,就可以用ssh登录了:ssh root@192.168.1.1
  2. 默认无线没有打开,需要修改/etc/config/wireless,在wifi-device radio0的设置中,把最后一行option disabled 1删掉。
  3. 锐捷绑定了网卡的MAC地址,因此需要将路由器的外网网卡的MAC地址改成你的机器的MAC地址。修改/etc/config/network,在wan的配置后面加上这么一行option macaddr xx:xx:xx:xx:xx:xx,其中xx:xx:xx:xx:xx:xx是你的机器的网卡的MAC地址。
  4. 完成上面两步修改后,重启网络:/etc/init.d/network restart
  5. 将mentohust拷贝到路由器上:scp mentohust root@192.168.1.1:~,这会将mentohust拷贝到/root下,这个目录是持久存储的,路由重启也不会丢失。
  6. 运行mentohust进行拨号:./mentohust -uUSERNAME -pPASS -neth1 -b1 -l0-b1这个参数很重要,它让mentohust在后台运行。
  7. 如果mentohust认证成功,客户端应该就可以上网了,因为从lan口到wan的转发和NAT系统都已经默认配置好了。
  8. 如果追求完美,可以在/etc/rc.local末尾加上一行/root/mentohust -uUSERNAME -pPASS -neth1 -b1 -l0,这样可以让路由器重启之后直接进行拨号。

IPv4由于NAT的存在,共享上网非常简单,但是IPv6没有NAT(虽然有些第三方实现的NAT,但是没有标准的NAT),我一直以为是IPv6还没有成熟的表现,但是最近发现其实IPv6有更好的解决办法:Proxy Neighbour Discovery Protocol,简称proxy_ndp。具体的解释可以参考wikipedia,简单说来就是:假设你有一个global的IPv6地址,那么通过包的转发(forwarding)内网中的客户端可以向外网发送数据,但是它却无法接受到外网返回的数据,因为内网中的地址并不是一个可路由的地址。NAT的做法就是把内网客户端的地址伪装成global的地址,这样返回的数据会到达具有这个global地址的机器,再让此机器把数据包转发给客户端机器。由于IPv6的地址空间非常大,所以没有必要做地址的伪装,而可以让每个内网的客户机都具有一个global形式的地址,但是这个地址依然是不可路由的,这时就需要让具有global地址的机器帮忙告诉它的上层路由,具有这个地址的机器在它的内网中。如下图所示:

ipv6示意图

这种方式的牛逼之处在于,它让Internet又回到了早期的“平的结构”,任意两个机器都可以直接进行通信了,因为它们都具有global的IPv6地址,这对P2P的应用真是莫大的好处:再也不用想尽办法去穿透NAT了。但是我一直觉得这种proxy会有问题:如果同一局域网中的两个机器都建立自己的内网,并且把内网的IPv6地址代理出来,那么,如果这两个内网中有相同的IPv6地址,就会产生冲突,这类似于同一局域网中两个机器设置了一样的MAC地址,结果是两个机器都不能正常上网。

先不管这么多,假设路由器的外网网卡是eth1, 内网网卡是br-lan,在openwrt中实现NDP Proxy的步骤如下:

  1. 确保eth1具有global的IPv6地址,可以通过ifconfig eth1查看;
    root@OpenWrt:~# ifconfig eth1
    eth1      Link encap:Ethernet
        inet6 addr: 2001:da8:b800:1a11:226:22ff:fe8a:fb8f/64 Scope:Global
    
  2. 给内网网卡br-lan设置与eth1的地址前64位相同但是后64位不同的IPv6地址,设置时前缀长度要大于64:
    ip -6 addr add 2001:da8:b800:1a11:1::1/80 dev br-lan
    
  3. 安装ndppd:
    opkg update && opkg install ndppd
    
  4. 修改/etc/ndppd.conf,将其中的rule设置成你的内网网段:

    proxy eth1{
    router yes
    timeout 500
    ttl 30000
    
    
    rule 2001:da8:b800:1a11:1::/80 {
        auto
    }
    }
    
  5. 运行ndppd:/etc/init.d/ndppd start
  6. 完成,这时内网的机器只需要将其IPv6地址设置成2001:da8:b800:1a11:1::/80的形式,网关设置成2001:da8:b800:1a11:1::1,就可以了。

linux号称本身就支持proxy_ndp,可以通过ip -6 neigh add proxy [IPv6-ADDR] dev [IF]来设置,但是我试过N遍都不成功。还是要通过硬方式——用一个守护进程ndppd来监听Neighbour Solicitation请求并给予正确的应答才可以。不知道是不是linux内核的bug。

下一步打算研究一下IPv6地址的自动分配,应该用radvd就可以搞定。这样就算完美了:)


晚上研究了下地址的自动分配问题,发现只用radvd是不可以搞定的,因为radvd的分配方式只能是前缀为64,并且后64位是根据网卡的MAC地址来计算出来的,不能手动指定。我尝试在radvd的配置文件里写prefix为80的地址,但是这样设置之后客户端根本就获取不到IPv6的地址。所以还得加上DHCPv6 server才可以。具体方法是:

  1. 首先安装radvd和dhcpv6 server:
    opkg update
    opkg install radvd
    opkg install wide-dhcpv6-server
    
  2. 修改/etc/config/radvd,首先将前两个配置的option ignore一行注释掉或者删掉,然后修改第一个配置的内容为:
    config interface
    option interface        'lan'
    option AdvSendAdvert    1
    option AdvManagedFlag   1
    option AdvOtherConfigFlag 1
    list client             ''
    
    其中AdvManagedFlag和AdvOtherConfigFlag是告诉客户端使用DHCPv6来进行地址分配。
  3. 修改/etc/config/dhcp6s,将其中的enabled置为1,然后再修改/etc/dhcp6s.conf,将domain-name-servers和host name都设置都注释掉或者删掉。其他设置如下:
    interface br-lan {
    address-pool pool1 86400;
    };
    pool pool1 {
    range 2001:da8:b800:1a11:1::100 to 2001:da8:b800:1a11:1::200 ;
    };
    
  4. 分别启动radvd和dhcpv6 server:
    /etc/init.d/radvd start
    /etc/init.d/dhcp6s start
    
  5. 完成。我有Lion有线网卡重启一下才能获取到IPv6地址,不知道为啥,无线重连就可以了。
Posted in 互联网周边 | Tagged , , | 122 Comments

说说最近

距离我的上一篇博客已经一个多月了,真是惭愧。我时不时就会想起来:哎呀,博客好久没有更新了。似乎这预示着这段时间比较空虚,心里不禁发虚。今天终于坐下来写,说说最近的生活。

百度

还得从上几篇博客说起,那时正值百度来我校进行实习生招聘,所以几天内写了几篇关于算法的博客。我本来是不想去面试实习的,因为实验室老师肯定是不让走的,所以之前的微软的实习生招聘我就没有去网申,结果笔试不让进考场。后来为什么又想去了呢?因为听到学院有几个同学已经收到微软的实习offer了,我心里一紧:微软呀,好机会呀……可是都已经过去了。于是,当百度来进行宣讲时,我决定去面一面。当时也没抱定想要去实习的想法,只是想去面一面,看看自己多少斤两。但是面到后来,我竟突然很想出去,倒不是因为觉得百度有多好,而是实在不想待在实验室了。

百度的面试经历,总结起来就是:笔试还好,一面一般,二面很好,三面发现自己还很水。果然,三面结束后一个月内都没有收到offer。可是没想到在6月10多号一个大雨的下午,突然收到HR的电话,问我什么时候能入职,能实习多长时间。这应该算是offer了吧?我只能说得跟导师商量一下。我还特意问了为什么这么久才给通知,她支支吾吾说“优先考虑实习时间长的同学”。我想我应该是被当做备胎了吧……

实习

怀着一些希望,我去找我的老师说我想去百度实习。他的回答比较短,说就他所知,我们实验室从来没有出去实习的。而且他也没有权限答应我,让我去找我们实验室的BOSS。我去找了,BOSS并没有我想像的严厉,只是说不太好。跟我绕了一会儿让我再去跟我的导师商量商量。其中我记得有一段对话我记得特别清楚:我说“其实我挺想去实习锻炼锻炼的”,他说“我也想去这儿去那儿啊……哪有这么多自由啊”。我当时心里一百个问句:为什么就没有自由了?后来我再去找我的导师,他跟我说:如果我真要去,可以,不过要我延期两个月答辩。让我好好考虑。我想这应该是BOSS教他说的。我倒真是想过延期就延期吧,但是终究是不敢,想起abel说的“你要衡量你自己的得失,注意不要搞太猛”,我想我还是不要搞太猛了吧。

院长

实习没去成,心里积了不少怨气,结果我一怒之下就找院长实验室的同学要来了他的邮箱,给院长写了一封题为《关于学生实习的问题——一名学生的观点》的邮件。大概的意思是:咱们学院这么多实验室不让学生出去实习,私心太重了,不利于学生的发展,希望学院能从学生的利益出发,适当干预一下。没想到过了两天,院长居然回了邮件,说谢谢我的建议,让我有时间去他的办公室找他。过了两天,我去找他,被他上了一堂思想教育课。他说的内容有两个:一是研究生的管理,就是导师说了算,全世界都是这样,我抱怨也没有用;二是实习并不见得有多好,关键是看你做了什么事。如果我能把实验室老师交给我的事情做好,疯狂地用功,专心研究,做出成果,没有哪个公司会不欣赏我。他的第二点着实打动了我,以至于我都没有去反对他的第一点。可是我回来一想顿时觉得悲哀:我折腾这么一圈,其实是回到了我刚开始对实验室不满的时候,其实所有这些事情,原因就只是一个:我的老师太次了,他既没有能力指导我做学术,也没有能力带领一个团队做项目。只是在院长面前我不好意思说这种话。

其他

在这一个多月里,我还折腾了这么一些东西:

  • 学了学python,由于没有实际的项目,只是把tutorial从头到尾看了一遍,写了两个小程序,一个是增量拷贝目录,就是根据文件最后修改日期,只拷贝覆盖更新的文件;另一个是将一个文本文件格式化成80个字符一行的格式,其中汉字占两个字符,英文占一个字符。
  • 寝室在我的强烈要求下,换了个路由器,用上了开源的固件。刚开始用的dd-wrt,效果还不错,缺点是不支持ipv6,而且要每天定时重启。后来换了openwrt,内网的ipv6支持只莫名其妙地成功过两次,不过它似乎是不用重启的。
  • 完善了一下用vim和ant开发java程序的工具链,把实验室的项目中我负责的两个程序(java web application)整理了一下。
  • 看完了张爱玲的《半生缘》,之后看了黎明和梅艳芳演的同名电影。
  • 打了很多dota……
  • 最近在学习openshift,想给公寓中心搭个自己的app服务器,省去布署的麻烦。
Posted in 意见/挑剔, 默认分类 | Tagged , , , | 5 Comments