2016年6月2日星期四

诡异的文件sum不符问题

一个代码文件,我想用sha256sum对比下线上的文件和Git仓库的是否一致。结果发现它们的sum不同。可是如果我把线上的代码复制粘贴到本地计算,或者把本地的代码复制粘贴到服务器上去计算,结果却是一样的。

开始我还以为Mac和Linux的shasum和sha256sum的计算方法不一样,但并没有这样的问题。后来我怀疑是不是换行的问题。在服务器上用Vim打开代码文件,底下的状态栏显示[dos]。之后用cat -ev file就可以让回车换行等无形的字符原形毕露了。

2016年3月19日星期六

Python中.的意义

记得三年前前有同事一起讨论过一个问题,为什么在Python里import boto后不能访问boto.ec2,但是却可以import boto.ec2,或者from boto.ec2 import xxx

其实这个问题的本质是:Python语法里面点操作符"."在不同语境下的不同含义。访问boto.ec2的时候,是从boto获取ec2属性;而在import语句里面,boto.ec2只是一个module或者package的名字,只不过Python碰巧用和前述语境下同样的操作符.来分割package和sub-package。而在文件系统上,package和sub-package是用/来区分的。如果Python也用/,那么文章开头的语句就变成了import boto/ec2,和from boto/ec2 import xxx。这样也就不会有开头的困惑了。

另外,import ec2只是执行了ec2/__init__.py文件,因为这个文件里面没有引入或者定义ec2这个名字,所以访问boto.ec2会出错。

2016年2月25日星期四

一个诡异的HTTP错误

最近一个Django项目,在通过内部一个代理设备访问后,某个表单提交后,就出现了如下的错误:
Bad Request
Your browser sent a request that this server could not understand. Error code: 63
后续的访问也一直出错。通过浏览器调试工具,发现是400错误。把站点的cookie清了就好了。进一步看是一个叫message的cookie项引起的问题,只需删掉这个cookie就好了。

排除了服务后端的故障,然后通过Nginx作反向代理,并为出线上述错误。于是让我们的运维检查这台设备。

这是Array Networks的一个负载均衡设备。开始时候认为是cookie太长,后来发现并不是。这条cookie当我用curl请求时,把这条叫message的cookie内容改成普通字符后,错误消失了。对了,原来的内容是:
messages="835c9e7a8999c8d105885625317e3ffeda5cca89$[[\"__json_message\"\0540\05425\054\"The user \\\"tux\\\" was changed successfully. You may edit it again below.\"]]"
所以我把问题定位为这个设备的bug。

在这之前我都没听过这个公司,原来大家说的"Arrary"不是什么阵列,而是一个网络设备商的名字。考虑到用Google全文搜索开头的出错,只有两条结果且都在国内;考虑到Array Networks市场份额的43%在中国,我更加确定是这个设备的问题了。

根据StackOverflow上这个帖子,得知RFC 6265里面推荐了cookie的值只能是某些普通的ASCII字符,要填这个坑的话就需要去给Django提交建议了。

PS:这个问题解决过程,搜出了“复员军人不接受强拆就是网上通缉犯吗”的帖子,真是醉了……在这个帖子后面有这样的回帖:
昨天早晨,我点击凤凰网论坛、博客、微博,就跳出以下提示:
Bad Request
Your browser sent a request that this server could not understand. Error code: 63 Parser Error: [Cookie: ALLYESID4=0498B7D443AD806F; userid=1344328900625_6468; samemappingcookie=m; _plst[_plid_]=3072171655; py_map=1; vjuids=7d7548b9c.138233b91db.0.3f080ee819d02c; vjlast=1340620903.1345658526.11; ua_map=adchina; pgv_pvi=6917995520; pgv_si=s5491098624; Q37_cookietime=0; prov=cn0851; city=0851; weather_city=gz_gy; olyput=1344836990481%7C1345737966421; if_play_u=bjflGMzpVfSI9V9oT3waAJR4kF4; __gads=ID=fb631e879772a279=1344995081:S=ALNI_Mb4jCw0mDn_bkcI1AY8Mx1giTljlg; reborn=A%2BQLyQi6VeoFsFfOBeoFqlHK; sid=3B0D495188FDFE2858508FF9ECFC3322%E7%99%BD%E4%B9%9F%E8%AF%97; Q37_auth=1jFM%2Bm%2FG0coIROhfIQJMjrX7h2ZRfily6XYD; Q37_sid=iUIeZf; IfengArp_2725=1; IfengArp_2726=0; ifengRotator_ArpAdPro_2013=1; b_his="[{\"b]
我用360度急救后,才又能进入。我请求懂軟件的朋友看看,这提示是否表示我的电脑受到了来自贵州某地的木马攻击!
这位仁兄也遇到了和我一样的错误,不过他的出错信息更详细,给出的错误原因是cookie解析出错,这里显示的cookie也包含某些特殊字符,例如冒号。

PS2:一开始上面这个回帖,我说这哥们是迫害妄想症吧,一看他的ID正好是paranoia,逗坏我了:

2015年12月22日星期二

不玩Docker了

最近在开发环境用Docker,总是感觉各种不方便。特别是作为Ansible管理的机器,一些系统配置都不能改,比如不能替换/etc/resolv.conf,iptables有问题,SELinux有问题。而且修改了容器状态,还得保存了才能持久。后来看了这个网站,还有和几个朋友的交流,决定在开发环境不用Docker了,重新用起Vagrant。

2015年11月20日星期五

几个监控系统选型

如果要选择几个监控系统,可选项有Nagios, Cacti, Ganglia, Zabbix和Zennos,应该选哪个呢?我除了用过Zabbix外,其它几个没有经验。如果是技术选型,我觉得未来技术的发展方向和趋势很重要,这样可以放心在上面进行长期和深入的投入。

通过Google Trends,发现Nagios,Cacti和Ganglia的关注度都在降低,而Zabbix在稳步提升,Zennos始终没有得到太多的关注。Google甚至给出了预测,在2016年11月Zabbix的关注度将超过Nagios跃为第一。

如果在“计算机和电子”类别里面比较,Zabbix的增长看起来更明显。不过我还没搞懂下图的含义。

这个结论让我消除了对统一监控系统到Zabbix上的做法的顾虑,可以有信心地长期投入。

2014年12月18日星期四

放弃Linux,投奔OS X

今年我有两大改变,或者说是“回归”或“回退”,其中之一就是在用了10年多的Linux后,开始用苹果的系统了。

从2012年拿到公司的苹果电脑后,我很快就装上了用了多年的Ubuntu,一直用到今年初。一月底时候,因为在家用经常要挪动、扣上、再打开,而Ubuntu有时会死掉,就用了几天OS X。因为不会死机,用起来很方便,就这样很快转到了完全用Apple系统工作和生活。

那我之前为什么要在苹果电脑上跑Linux,而不是苹果的系统呢?因为在我看来Ubuntu有很多优点。首先,因为我一直是自由软件的支持者,所以用一个自由的操作系统是很光荣的事情。此外,我觉得Ubuntu的Unity是设计最好的桌面环境,用户和桌面的交互只有Dock, Dash和右上角的菜单,这个设计的简洁性和易用性超过了Mac OS X。最后,我桌面上直接配置开发环境,还可以方便地查阅Linux的manpage。

不过,Ubuntu的致命的问题是软件质量太差。总体上,Ubuntu对苹果电脑的硬件支持要比PC差。在Ubuntu上,因为驱动的问题,无线网会经常断,需要写个脚本不时重启无线网。双显示器在切换时候会常常花屏,此时唯一的办法就是强制重启。待机后偶尔无法正常恢复,也只能强制重启。触控板能凑合用,但是触感严重有问题,网上有调整驱动配置的方法,我也懒得折腾。耗电厉害,发热厉害,后来用电池的时候只能撑一个小时。

此外,Ubuntu系统本身的质量也远低于OS X。软件崩溃是常有的事情。每次发布新版升级完就一堆问题,如果能进去桌面实在算是幸运了。我那时候闲的,在Launchpad上给Ubuntu提交了不少bug,基本没有人关注;而我给Debian提的bug,得到解决的比率感觉要比Ubuntu高。Ubuntu每六个月发布一个版本,除了LTS外,很难保证各个版本的质量。

用了OS X后,终于可以享受用电脑的过程了。喜欢苹果强大的触控板和便利的窗口管理功能(我第一次看到同事不用鼠标只用触控板时还很诧异),可以使用丰富的快捷键。最重要的是,电脑没有那么多的问题了,不用整天想着修复电脑问题了,可以更高效地做有产出的事情了。

当时用了linux.fatduck.org这个域名,想的是我应该会一直把Linux用下去的,没想到竟然背叛了这个多年的爱好。说到背叛,我还有另外一则故事,以后会发到另一个博客上。

2013年11月24日星期日

LightDM不能启动

开了20多天的Ubuntu 12.04,重启后LightDM不能开机自动启动了。决定查个究竟。

根据开机后的画面显示,目测是LightDM的Upstart脚本没有执行。看了看/etc/init/lightdm.conf,里面有相关的依赖服务,但我不知道是哪一步出问题了。折腾了几下,包括检查plymouth, dbus服务,删除和重装lightdm包后,lightdm服务竟然手动启动都会失败了。

还好LightDM在/var/log/lightdm/lightdm.log记录了日志,里面有/usr/share/xgreeters/default.desktop文件找不到的错误。在/usr/share/xgreeters/只有unity-greeter.desktop文件。之前正常工作的时候,/etc/lightdm/lightdm.conf里面指定了unity-greeter的,现在没有lightdm.conf这个文件,所以就出了上述的错误。我就做了一个符号链接,再次sudo start lightdm,结果还是没有起来,不过lightdm.log里面有记录启动greeter出错了,并友好地提示greeter的日志记在/var/log/lightdm/x-0-greeter.log里面。在这个文件里面看到具体的错误是没有权限打开/var/lib/lightdm/.Xauthority文件。我记得之前用Apt删除lightdm的时候,显示/var/lib/lightdm目录未能删除,现在我就把/var/lib/lightdm里面的所有文件都删除了,之后lightdm服务就能成功启动了。

从这个故事我得到的体会是,应用设计里面重要的一点,就是要有关键的日志记录,特别是错误记录,这样在事后分析的时候容易找到问题产生的原因。LightDM的日志文件就是比较清楚的,特别是在lightdm.log里面,写入其它日志文件x-0-greeter.log时,也会记下这条,这样看日志的人立刻就知道还有别的日志文件;如果安静地写到另一个日志文件里面而不提示,就会增加用户检索的成本。