Shell's Home

Jul 11, 2015 - 1 minute read - Comments

cache和buffer的区别

不废话,上干货。 根据引用1和2的说法,cache是用来缓存文件的,buffer是用来缓存块设备的。在2.4之前,这俩是独立的,所以很多文件缓存两遍。在2.4之后,两个联起来了,所以一个文件只缓存一遍,这个大小算cache的。 linux通过page cache做所有的文件IO。写的时候,只标记这个cache页面为dirty,一个周期循环的刷写系统会去把这个脏页面刷到磁盘上。而读的返回也在page cache里。如果没有命中,那么就先载入。page cache是一个长期存在的东西,是一个几乎只会增大的怪物。他的唯一回收理由就是系统耗尽内存,需要释放部分来用。 而buffer缓存的是块设备数据。正常来说,这些数据都应该和page cache一致。里面只有部分数据会不在page cache里,例如文件元数据。 http://www.quora.com/Linux-Kernel/What-is-the-major-difference-between-the-buffer-cache-and-the-page-cache http://www.quora.com/What-is-the-difference-between-Buffers-and-Cached-columns-in-proc-meminfo-output

Jul 7, 2015 - 1 minute read - Comments

flash禁用教程

最近flash一堆漏洞,大家禁用了吧。 firefox 附加组件 -> 插件 -> flash -> 禁用 chrome 浏览”chrome:plugins”页面。 找到flash,禁用。 safari Preferences Security Allow Plugins旁边的Website Settings Adobe Flash Player, disable 检测 http://www.bilibili.com/video/av2533651/ 来吐槽的说明你的设置有问题。 PS:注意,youtube已经不使用flash了。 参考 图文教程: http://www.redmondpie.com/disable-flash-in-chrome-firefox-safari-other-web-browsers-to-keep-your-pc-safe-from-vulnerabilities/ (全英文,但是可以看图)

Jun 30, 2015 - 1 minute read - Comments

hosts配错导致ldap安装问题一例

不废话了,要装ldap。 ubuntu下,最简单的方法是修改/etc/hosts,添加自己的域名,例如ldap.shell909090.org。然后安装包的时候,就会使用dc=shell909090,dc=org作为basedn。里面自动添加一个admin。 结果在某机器上,丫硬是一直管自己叫nodomain。 当然,内容可以后改。但是很麻烦。先要删除原始的,添加新的。还有一堆杂七杂八的问题。关键是,为啥TMD这么简单一个问题我居然搞不定。 方法1 绕过。 怎么绕? 经过检查发现,basedn这些东西,其实都是从debconf里读的,而不是直接来自系统。所以我可以重设debconf来修改配置。 echo slapd slapd/domain string shell909090.org | debconf-set-selections echo slapd shared/organization string shell909090.org | debconf-set-selections 然后再安装,就全部正确了。 方法2 为什么? 检查同样发现了本质的原因。如果debconf里没有配,则去读取hostname -d。在一台机器上,这个配置没事,另一台就不行。 经过我反复测试,发现原因是这样的。 hostname -d读取域名的时候,是寻找/etc/hostname对应的域名作为行尾的那行,而不是127.0.0.1所在的那行。。。 而出问题的那台机器,/etc/hosts配置和没问题的那台严格一致。包括机器编号! 谁TM抄卷子把名字也抄了?

Jun 29, 2015 - 1 minute read - Comments

婚姻平权——写在美高等法院裁定全美同性婚姻合法边上

论婚姻 从法律上说,婚姻是一种保证性和生育权的制度。他主要反映了统治阶级是如何看待性和生育权的。例如婚姻双方是否在性上面排他,或者是否对称的排他(女性出轨和男性出轨的后果不一样)。双方如何抚养后代(特别是离婚的情况下),如何界定后代继承权。 婚姻制度在开始的时候,出现的目地主要是两个。 规范性权力。 促进生育。 其实你仔细想,如果不是因为上两个因素,你爱找谁上床生育,关统治者什么事?最远古时期,一男一女两个生娃,恐怕也不会找民政局去登个记什么的吧。但是随着社会制度的形成,尤其是“私产”和“继承”制度的形成,你找谁上床就不是你一个人的事了。想象一下,如果每个地方的土皇帝都占有了所有的女性,那么其他人怎么办?会不会产生战争?如果一个女性和多个男性保持关系,那么谁(注意以前男性占有多数社会资源)应当抚养她的后代? 所以,世界各个地方开始不约而同的出现了婚姻制度。当然,随着各地情况不一样,婚姻制度也千差万别。例如中国允许一个男性占有多个女性,但是其中只有一个拥有完整的权利。其他女性的权利就会有缺损。伊斯兰教似乎也允许多个妻子(据我听说最多四个)。有些被占领区甚至有“初夜权”的说法(参见“勇敢的心”)。 进入近代,婚姻制度主要是双方具有极度亲密的关系,以及由此衍生的各种权利和限制。例如妻子通常是丈夫的保险受益人,而且拥有在丈夫失去意识时做出各种决定(例如医学决定)的权力。当然,如果你误信非人,这点也经常被用来骗取保险。当然,这种制度同样的,也鼓励生育。 然而这对同性爱人来说并不公平,因为生育要求的基础是一男一女。他们认为自己被歧视了,所以他们也希望在法律的架构下分享各种权利。在同性婚姻不合法的前提下,他们无法和他们爱的人共享各种权利,甚至无法参加告别仪式(因为实际拥有权利的人,例如父母,甚至妻子,可以禁止他们前来)。而且很多同性爱人,因为婚姻的理由被迫和异性结婚。这不但造成了同性爱人的悲剧,还会祸及和他们结婚的无辜者。 区分婚姻的定义 我认为应当将“亲密双方共享权利”和“性以及生育”分开,甚至性和生育都应当分开。某个权利或限制,到底是给予“亲密双方”还是“有性关系双方”,抑或是给予“一个孩子的父母”。在今天看来,三者不再完全的等同,而且分别越来越大。 性和生育的关系 今天,男女找谁上床不再和婚姻划上等号。你可以坚持婚前无性,但是你不能强迫所有人结婚后才发生关系。 当然,在很多地区,婚姻对性的纯洁性(尤其是女方纯洁性)的要求还是非常苛刻的。据我所知,很多地方,丈夫发现妻子不纯洁后,可以将她送回娘家。她的父亲或者兄弟为了洗刷耻辱,会将其生生打死。而丈夫发现偷情的妻子,可以私自处以投石的刑罚。国家并不会惩罚凶手。 但是在另一些地方,性已经和婚姻没有什么太大联系了。我的预计是这些地方会越来越多,逐渐扩大。 当然,有一些权利和限制是需要给予性的,例如儿童色情的禁止等。但是这事和婚姻关系不大。 生育和亲密关系的关系 如果你想清楚的话,其实两者没有关系。想的更开一点,你可以管“共同生育”的关系叫做“婚姻”,管“亲密关系”的关系叫做另一个名词。只要你彻底分开两者的权利细节,其实并没有特别的理由去阻碍同性爱人分享权利,承诺责任。 例如,为什么要阻止同性的爱人能够共享关系内财产呢? 又例如,为什么要阻止双方承诺扶养对方的义务呢? 将两者分开后,你会突然发现——为什么要阻止同性婚姻呢?完全没有道理么。非但不需要阻止同性婚姻,而且到底是“嫁”猫“嫁”狗都无所谓(实际上法律意义上说对象必须具有人格)。到底是“娶”男人“嫁”亲爹,其实完全没有必要阻止——这既不体现性,也不体现生育。 但是我比较倾向于认为,既然生育和亲密关系是两回事,那么很多为生育而制定的规定就不应当延续到亲密关系上。这种改变不是把结婚条款中的服务双方必须是一男一女改成可以同性就结束的。 例如有些国家为了鼓励生育,对夫妻婚后的财产税收缴纳有相当的优惠。我不清楚婚后纳税是否完全是为了鼓励生育,但如果有这种成分的话,那么把这种鼓励延续到同性关系上就是不正确的行为。 同性性关系 这节是最复杂和有争议的一节。 把生育和亲密关系分离,其实不是解决问题的终点,而是问题的开始。很多问题,是同性关系中特有的。你要把它在亲密关系中规范,那就对异性婚姻者不适用。所以同性婚姻的出现,必然开始很多对同性性关系的规范。当然,这些也不一定在婚姻法范畴内。 例如鸡奸罪。你不可能允许同性结婚,却宣布鸡奸有罪。我靠,这是在逗我玩么? 又例如强奸。很多国家强奸罪的客体,必须是一男一女,甚至必须是男性对女性。那问题来了。一对亲密关系中的双方,其中一方受到第三方(三者都是同性)的强奸。但是只能以故意伤害论处?或者更夸张的情况。一对男同性爱人结婚,婚后其中一人被一个女色魔强上(好可怕,这比中国的电视剧更荒谬)。对于这种情况,也不能算强奸? 如果不修正这点,恐怕也不是有点荒谬吧。 oh, BTW。美国法律已经规定强奸罪可以是任何性别对任何性别了,所以以上例子仅仅是例子,OK? 我在说什么 开始的时候,我们需要管理一些关于性,生育之类的问题。于是架构师发明了一个叫做“婚姻”的类,在上面附加了规则,事情就结束了。 后来发现,婚姻这东西其实没法满足需求。因为婚姻上的很多规则是生育的,但是有一些同性的couple需要用他。 怎么办呢?拆类呗? 这个重构工作居然持续了20-30年,你们还好意思说程序员慢?

Jun 24, 2015 - 1 minute read - Comments

一个有趣的python问题

quiz 今天在twitter上看到一个有趣的问题。 t = (1, 2, [30, 40]) t[2] += [50, 60] 结果是什么? t = (1, 2, [30, 40, 50, 60]) TypeError 都不是 1,2都发生 出乎意料的,结果是4。 为什么,我们来分析一下。 disassemble >>> t = (1, 2, [30, 40]) >>> def f(): t[2] += [50, 60] >>> import dis >>> dis.dis(f) 以下是结果。 LOAD_GLOBAL 0 (t) LOAD_CONST 1 (2) DUP_TOPX 2 BINARY_SUBSCR LOAD_CONST 2 (50) LOAD_CONST 3 (60) BUILD_LIST 2 INPLACE_ADD ROT_THREE STORE_SUBSCR LOAD_CONST 0 (None) RETURN_VALUE 我们来解读一下。dis的指令集可以看这里 。

Jun 17, 2015 - 1 minute read - Comments

list.append的性能分析

在python2.7.5的源码中,list的append操作最终调用的是Python-2.7.5/Objects/listobject.c:266这里的app1(请帮我复核一下,Python的源码有很多隐藏的手脚不容易看见)。 在app1里,使用了list_resize来进行resize,而list_resize间接用到了PyMem_RESIZE。按照我的阅读,这个应该是层层转到realloc上的。 下面就是查glibc源码的事了。我看到的应该是glibc-2.19/malloc/malloc.c:2951这里的__libc_realloc函数。这个函数很长,我大致读了一下。这里分了两个分支。一个是2992行的chunk_is_mmapped。如果我没理解错的话,我们的内存块不可能没有mapped。那么另一个就是2996行的HAVE_MREMAP,这个是编译时宏,我也不知道我的系统上是不是打开的。如果没打开的话,肯定是走alloc,copy,free的流程。 所以我就用strace跟踪了一下,结果确实调用了mremap。 这个函数在linux内核中。我使用的源码是linux-3.2,结果在linux-3.2/mm/mremap.c:535这里。 大致看了一下函数实现。首先试图处理缩小,如果不行的话试图在扩展到最大(vma_to_resize),如果这样还是不行,先试试看能不能追加映射(vma_expandable/vma_adjust)。如果都不行,他还是用的创建并移动的方法。(We weren’t able to just expand or shrink the area, we need to create a new one and move it..)。 所以,总体来说,list.append的复杂度还是O(n)级。但是由于remap的内核实现,因此比直接搬数据应该会快一些。具体表现可能要以测试为准了。 但是这里就有一个疑惑。难道python现在删除了复杂的内存层,将mm管理直接用系统的来支持么?我记忆中python源码解析里讲过python有一个巨复杂无比的内存控制系统。难道全用系统管理了么?对此我查了一下 2.6 / 2.7 的python mm文档。里面倒是明确提到不要同时使用系统api和python api来管理内存。但是并没有明确说明如何处理的实现。但是我在系统里并没有找到第二个实现(debug不算),唯一的实现在Python-2.7.5/Include/pymem.h:76,是直接转到realloc上去的。 貌似在新证据出现前,我得认为python使用的glibc api来处理的mm问题。

May 29, 2015 - 1 minute read - Comments

携程本次问题分析

携程这次的事情,实在没啥好多说的了。要骂的话,早就骂过了。我们就来说说携程这次事故中,我们能确定的事情吧。 小道消息 首先我要排除一切小道消息,包括数据库被“物理”删除了,前任总监报复,运营妹子和高管好上了什么的。昨天和朋友开玩笑,物理删除要怎么做呢?你要盯着硬盘,直到他羞愧到不能淡定,自己从服务器里裸奔出来,纵身从楼上跳下去。这才叫物理删除。第二天报纸准出新闻——硬盘们,不要着急,等待反弹。。。 至于前任总监报复,运营妹子和高管好上了。我越听越像电视剧,还是国产的。这些没影子的事情就不多说了,我们来说点有用的。 事实 首先,我们要搞清楚一个问题。携程自己说的话,是没用的。 是的,无论是故障时的混乱情况导致说错话,还是出于稳定情绪角度的说辞,都没太大价值。最多用来旁证分析。我们还是要追踪当时发生的,确定无疑的事件,以这个来佐证。 我们可以确定的事情有: 携程的系统挂了近12个小时。 挂掉的是应用层,而不是数据库层。 携程下午到晚上悬赏解决问题。 恢复后,历史数据存在,当然部分出问题时的数据丢失(这是必然)。 14是大家都看的到的。2是因为没有数据库连不上时的各种应用错误提示,干脆就是网页直接失踪。这说明问题不是光缆挖断,也不是数据库(至少不能直接佐证)。能够确认的是应用确实没了。3是来自道哥的消息,我觉得应该比较靠谱(毕竟涉及钱)。 分析 好,综合123,我有个推论。携程在出问题的时候,很快就知道了是应用的问题(至少确定应用有问题)。然后试着恢复,但是无效。原因携程自己都不知道。 这是自然。如果携程不知道应用层有问题,太业余。没试着恢复,太二。恢复了有效,不像。携程知道为什么,那还发布个毛悬赏?综合起来,那就是恢复了没见效,而且携程自己都不知道原因了。 同时这个结论也隐隐的排斥高管报复说,至少携程当时不能确认是高管报复,而是作为通用性技术问题来处理的。如果是高管报复,你找外人来管个毛用啊。再黑自己一遍? 当然,这个推论有个前提。携程的悬赏不是为了转移视线的烟幕弹。不过看当时的情况,我觉得这种可能不大。 那么问题的技术细节呢?不知道。携程自己找到没找到原因?不知道。我们知道点啥?数据库备份没事。 是的,我没法确认当天数据库没事(因为我没有当天订单)。不过看事后没人吐槽,估计是没事的。 事后 携程事后说是程序员错误的删除发布的应用,这个和上文“问题出在应用层”一致。在问题原因上,携程没多大掩饰的空间。但是“程序员误删除”这个说法是真是假就不好说了。实话说,这个说辞显得像是背黑锅,推责任。但无法排除,确实可能是事实的真相。 但是这个说法无法解释的是,为什么恢复时间那么长,而且还开出了悬赏。编译整个系统,然后重新发布确实很慢。但是一来时间不会如此长。二来更关键,程序员非常清楚问题在哪,要花多久。你找个技术专家来弄这个事情也未见得快。而且就算要找,也肯定限制在所用技术系统的编译和发布专家里找,不会满世界的开悬赏。如果真的是重发布时间过长,领导层又挂出了悬赏。这无疑是在瞎指挥。 最后就是“携程在系统上做了改进,规范并杜绝技术人员错误删除生产服务器上代码的操作”。这里明显漏了一个要点”加强部署和恢复演练和自动化推进“。 一般来说,在系统设计的时候,首先考虑的是“如果不小心被删除了怎么恢复”。而不是“如何防止错误的删除”。就像我和一位同事解释的,你可以将rm替换成别的程序,但是如果对方用的是dd呢?如果是chmod呢?如果下次,操作人员执行的不是删除,而是格式化呢?或者是更改ACL权限错误。这无疑要求限制所有操作人员能做的事情。 银行里就是采取的这种思路。每个运维能做的事都被严格限死,很难越雷池一步。但是同时要注意两点。首先,银行的业务相对固定,运维要干的事非常规范。携程的运维恐怕很难做到如此规范。其次,银行是有严密的恢复机制的,恢复机制(包括演练)也是运维的固定工作之一。 考虑一下。如果没有恢复演练。那么万一因为不可知因素,携程需要再度恢复(好倒霉。。。)的时候。运维有没有删除数据的权限呢?有没有修改权限的权限呢?携程的”杜绝技术人员误删除“的手段,还要不要坚持呢? 多说一句 网络上有个哥们猜测”可能是高管报复“的时候,推测是在编译环境里做手脚。这个和我当时的观点一致(不代表我认同他说的这个事实)——要让多个系统始终编译和发布了都不能工作,最有效的后门就在编译环境里。毕竟很少有代码能够跨越多个系统,但是几乎所有项目都会使用同样的编译环境。

May 27, 2015 - 1 minute read - Comments

程序的持续更新

今天有个朋友来问我sql2000的问题,数据库装好后各种,总之就是不能用。我说我已经很久不用sqlserver了,就算用,也绝对是用2008而不是2000。不过我还是给了一点小意见——重装整个系统再重装sqlserver呢?结果他和我说,就是重装惹的祸。 这是一个很老的业务系统,数据库只能用sql2000。整套系统运行了很久都没有维护了,基本就是硬盘坏了换硬盘,也没有多的烦恼,很轻松。但是最近CPU挂了,连带主板也有问题。这类的老主板+老CPU不好买,所以干脆用新件起系统。但是windows系统更换主板后无法直接识别,所以系统要重装,牵连sql server要重装。装完了远程就始终无法连接,要不然就是能连但是不能写。 我靠还有这种事?当年不是用一样的系统组合,一样的安装盘,一样的维护人员。为啥今天就出问题? 结论是不知道。但是这个事情不能因为不知道就不做,所以问我有啥想法没。 我问他能不能升级,告诉说没戏,应用绑死了。整个系统必须用sql 2000,而操作系统只能是winxp和win2003。好家伙,这三个都是超过维护期限的,连漏洞补丁都没了。那这个没救了。。。 想到帮另一个朋友维护的系统,也有类似烦恼。在老版本的php上写的系统,在新版本的php+mysql组合上就无法执行。所以必须安装老版本的CentOS。而老版本CentOS是有退役期限的——一个系统也不可能常年累月做下去吧。所以未来如何,一样很发愁。类似的事情数不胜数,甚至包括我自己写的某个系统,用了老版本的sqlalchemy导致升级不上去。 有一类系统,需求不经常变更,系统压力很小,使用场景很专一,结果就是代码几乎不需要维护的可以一直用下去。不得不说,这种系统比其他系统是简单多了也幸运多了。但是再耐用的代码,也是有服役期限限制的——一般和整台机器的寿命差不多,也就是7-10年。超过这个期限后,还要运行老系统,就要看负责是不是找的到人维护了。语言可能很少有人用,组件可能不能升级,牵连到系统都是老的,没有维护没有补丁。新设备上能不能装出来,有没有驱动都很难说。要照10年前的情况维护,还不如大量搜购老部件接着维护电脑比较痛快。 银行在上个世纪用COBOL写了大量代码,直到今天还在维护——但是代价也很大。银行不得不自己维持了COBOL的一整套生态系统,以至于我提到COBOL几乎就和银行话上等号。(当然,这也和COBOL本身和适合做这类工作有关) 如果没有银行那么大财力的话,要维护这种小系统,在短期内相当占便宜。但是如果在长期,万一出点问题,能不能搞定就有点存疑了。所以我建议维护这种系统的人,每五年做一次检讨,看看系统是不是重做一下,或者做一下兼容性升级,重写部分代码以便于在新系统上执行。这样也许不需要太大精力,就可以让整个系统顺利的再撑个5年。 无论如何,指望像房子一样,建好后就一直可以使用,不碰到灾害不碰到意外就可以用个几十年。这种事情对于程序来说几乎不可能了。程序更像是汽车,一旦过了20年,要找老部件就非常困难了。合理的选择还是弄个新的吧。

May 19, 2015 - 1 minute read - Comments

试题设计的原则

原则 其实主要就两点。 分辨率足够。 简单。 第一点很容易理解。你的题目必须能准确区分傻逼,普通人,和牛逼,因此最理想的状况是,傻逼考零分,牛逼满分,普通人在中间。所以你的题目应该简单。如果题目难到普通人和傻逼一起做不出,那就没有区分能力了。如果不是正好碰到一个牛人,你的考试只能让你啥都招不到。这会把你自己变成傻逼。 所以,你的题目应该有一半是普通人能够做出来的,而不是道道都是神一样的面试题。之所以你在网上经常看到神一样的面试题,那是因为。 大公司不缺应聘的人,所以他们的“牛人线”比较高。 你能看到的题目,都是最牛逼的。 当然,题目中确实应当有一些有难度的题目,用来区分真正的牛人。这部分人我们要特别料理他们。 复用题库 混合一个题库,每次面试抽取不同题目形成试卷,这是常识了。 主要是防止试题外泄,还有重复出题造成的疲劳。 当然,每个题目需要加不同的属性,用于后面的一些分析。在抽题的时候也需要参考属性,例如上面提到的难度。 经验题还是能力题 我把试题分为两个类型。一类是测试你是否用过某项技术,用多深。另一类则是你的智力如何,学习,沟通,理解能力如何。 可以预期的是,刚毕业的人,经验题得分会低一些。不过在实际生产中,这些人出活的能力一向不差。所以对于刚毕业的学生,可以在经验题得分上宽容一些。 区分领域 在试题设计中,经常需要测试多个领域。例如网络,系统底层,等等。 将多个领域的题目分开标注,有利于你最终评定这个人的技术范畴。例如系统底层出色,但是网络很糟糕,这显然就不适合扔去一个重网络开发的组。 限制总量 这点才是整个试题设计的核心难点。 长时间的笔试是很高成本的。对于被考试者不是什么很好的体验,对于考试者来说,要出题,要判卷。考试期间还要招待人家,进行计时。如同马拉松一样的考试没有任何好处——除非非常必要。 但是正常来说,技术面试应该要问系统原理,算法,网络,编程语言,智力题等等,至少这么五个方面。每个方面一道题区分普通人,一道题区分牛人。这就是10道题。再复合上经验和能力的区分,还有为了对抗偶然而要每个组合多几个题。综合起来可能多达20-30道。这样1小时的笔试时间,每道题上只有区区2-3分钟。这点时间根本不够考核一些深入的问题。 所以如何减少问题的数量,而非增加数量,才是核心难点。 我的想法是增加过程叙述题,让被试人对一些经典过程做描述,并规范他一定要描述到哪些方面。以此来分析他对一些领域的基础。但是这方法有个明显弱点——不好执行不好打分。 关于这方面大家有啥意见?

May 12, 2015 - 1 minute read - Comments

Sysctl Timestamp对速度的影响

不知道我是不是写过了。 sysctl中有一个内核设定: net.ipv4.tcp_timestamps = 1 这个值默认被设定为1,但是当这个设定被设定为0时,会导致tcp序列号高速绕回,从而导致传输速度上限。 tcp的最大报文生存时间(MSL)默认值为60s(这也是为何TIME_WAIT默认120s的原因)。而tcp序列号只有32位,未来区域只有2\^31。 **31 * 8 / 60.0 / 1024 / 1024 = 273Mbps 因此当关闭timestamp时,最大传输速率不超过273Mbps。 在公司内部曾出现过这个现象(由于某个理由,错误的关闭timestamp),在自建系统上的测试也验证了这点。 使用iperf对性能进行测试,最大速度为266Mbps。 但请注意,被设定后,需要长达10分钟以上的时间才会发生效果。因此需要在设定后半小时后,去用iperf检验设定是否生效。