Planet of Woodpecker.org.cn for CPUG

August 06, 2015

@shell909090

关于vpn的一些话

最近在弄一些关于vpn的事,又在quora上看到了好多关于vpn的问题。(不知为何quora总是推荐让我回答vpn的问题)其中很多问题极其傻,缺少基础性常识,一看就是外行问的。

其实也难怪,vpn的需求,并不只是专业人士有。有位朋友向我咨询vpn问题,他可既不是要翻墙,也不是专业人士。所以我打算把和vpn有关的一些常识写一下,以备咨询。

vpn能做什么?

vpn能做什么,取决于你想要他做什么。vpn其实就是一个虚拟的线,连通两个地点,就如同真的接了一根线一般。只不过这个虚拟的线,实际上是由你到对方地点的网络来提供的支持。通常情况下,这么传数据会使得你的数据暴露在网络上。但是vpn里传输的所有数据都经过了加密,你可以认为传输者看不见。

所以,vpn能做什么呢?

有些公司阻止了员工访问很多网络。借助vpn,你可以绕到第三方的网络里去访问哪些网站。其实gfw也是同类情况,只是这家公司更大而已。

有些网络会监听访问,用来做一些对用户不利的事情。例如在国外,使用bt下载很可能会招致版权组织的诉讼。这时可以借助vpn来下载。或者某些公司也会监听用户的数据,例如qq。对于这类情况,你也可以用vpn跳出公司的网络。当然,如果你对这些问题已经有了顾虑,那么就不应当使用国产路由器。大部分国产路由器都会有监控用户数据的行为,很多甚至会修改。

vpn不能做什么?

vpn的常规模型,是从用户实际上网的地点“逃逸”到vpn供应商那里。(我们不讨论一些特殊情况)所以,他解决不了一些问题。

例如你的网站没有加密,那么就无法期待vpn来帮你。除非你能让你的所有用户和网站全部连到同一个vpn上(所以访问你的网站前需要先拨vpn)。基于同一个理由,你无法用vpn对抗网站劫持。

同理,如果某个网站未加密,你也无法指望使用vpn保证安全。vpn只能保证守在你家门口的这些人(例如ISP)无法弄到数据。守在服务器门口的人(如果有的话)依然可以获得你和服务器的全部通讯。

vpn分为哪些种类,有什么特点?

一般来说,常见的vpn有这么几种。

  • pptp。最古典和最通用的vpn。windows里默认内置,搭建和使用都相当容易。但是由于特殊的网络设计,因此有些公司无法使用。而且有安全性隐患。对掌握极大资源的攻击者,内容基本透明。
  • ipsec+l2tp。windows里内置,大部分公司应当都可以连通(没有故意拦截的话)。对于除美国政府外的截听者,应该都比较安全。
  • openvpn。复杂和强大,模式多变。需要安装第三方程序,因此并不是很容易用。但是可以跨越大部分公司网络,不会有什么阻碍。安全性很高,也有一些算法可以用来对抗美国政府。由于中国政府的封锁,无法跨越国内外。
  • sstp。windows自己的协议。只需要一个ssl连接,因此跨越性比openvpn还好。新版windows里应该有内置。
  • AnyConnect。Cisco的协议,需要安装第三方程序。跨越性和安全性没有实用数据。

简单来说。如果你只是要用而已,并且没有被掌握极大资源的攻击者盯上,而且不是反美国政府。那么哪种方便用哪种。下面是一些系统的兼容性建议:

  • windows: pptp, ipsec+l2tp, sstp
  • linux: openvpn, pptp
  • android: pptp, ipsec+l2tp, openvpn
  • ios: pptp, ipsec+l2tp, anyconnect(似乎这是唯一一个能在ios上非越狱安装的vpn应用)

从上面我们可以看到,pptp其实是兼容性最好的,但是不是所有网络都支持。次之的是ipsec+l2tp。如果还有问题,openvpn应当能够解决你的问题。如果都不行,再考虑其他。sstp仅建议用于只有windows客户端的情况,anyconnect仅建议用于你钱足够多的情况。

所以大部分vpn供应商的协议选择都是pptp/ipsec+l2tp,或者多一个openvpn。这足以应付大部分情况。

这里是我看到的一个比较全面的,关于vpn之间比较的页面。

使用了vpn,我的网络安全了么?

不一定。如我上面所说,vpn只保证了你家门口的安全。守护在服务器前的人依然可以获得数据。甚至,如果vpn供应商怀有恶意的话,他们也能够获得数据。所以这是一个ISP和VPN供应商,谁更可信的问题。

而且实际情况往往更加复杂。很多数据的获取,并不来源于源IP地址,而是在浏览器里植入了身份相关信息。浏览器的身份相关信息相当敏感,没有他们,你就无法在网站上登录。也因此,这些数据一旦被恶意者获得,他们就能借助你在第三方网站上的身份信息,获得你是谁。

对于这些威胁,vpn都是无能为力的。

by shell909090 at August 06, 2015 07:44 AM

August 05, 2015

@shell909090

ipv6试用手记

ipv6地址

概要

挑简单的讲吧。

ipv6地址总计128位,分为8个段,每个段16位。hex表示的话,每段最多有四位。在写出ipv6地址的时候,用:分割。所以一个经典的地址写出来是这个样子的:

aaaa:bbbb:cccc:dddd:eeee:ffff:gggg:hhhh

这里有两个缩写。一,如果一个数字的开始有连续的0,可以忽略。好比0001和1是一样的。二,如果有多个连续的段是0,可以缩写为::,但是只能缩写一次(这样才能确定一个唯一的地址)。例如以下是一个缩写过的地址。

aaaa:b:c:d::1

这个地址等同于

aaaa:000b:000c:000d:0000:0000:0000:0001

ipv6地址分类

::/128 未定义 ::1/128 回环地址(127.0.0.1) fe80::/10 局部地址 ::ffff:0:0/96 ipv4映射地址 ff00::/8 广播地址(其实更小,不过我的路由表里就是这样写的,全保留给他了)

更多地址请去看wikipedia。

EUI-64地址

简单来说就是通过mac地址的48位,扩充到64位,作为ipv6地址的最后64位。

ipv6地址分配和基本网络设定

ipv6下有两种ip自动分配方案。通常都建议无状态的方案。

dhcp

一种还是经典的dhcp,这种方案分配出来的地址比较紧凑连续,空间利用率高。坏处是ip地址并不唯一固定。在多数情况下dhcp都会尽力分配和上次一样的ip下来。但是在地址池比较满和系统缓存被清理的情况下,并没有保证。

在interfaces里,dhcp的写法大致如下:

iface ethX inet6 dhcp

slaac

另一个是嫌地址太大的slacc。基本原理就是给一个组织(例如家里)分配一个/64的段,然后用EUI-64(似乎是)给里面的所有设备分ip。所以这样分出来的ip完全一致。

在interfaces里,slaac的写法大致如下:

iface ethX inet6 auto

dns

ipv6里进行配置还需要注意一点,你的DNS需要支持AAAA记录。不然拿着网址查出一个ipv4记录来就很尴尬,还得退化到ipv4去访问。这和直接使用ipv4没什么区别,反而更糟。

实际上,大部分DNS都支持AAAA记录,只是程序会不会默认去查而已。

另一个问题是,如果你的DNS服务器地址是ipv4的,也会使得你无法完全脱离ipv4网络。因此需要一个有ipv6地址的DNS。一般你的ipv6链路供应商会提供一个ipv6的DNS。

firewall

slaac使用icmpv6,所以需要在防火墙上打开icmpv6协议的进入。

tunnel breaker

he提供一个6to4的tunnel,但是需要你有静态ip地址。(其实凭心而论这真不是一个太高的要求,很多VPS供应商完全可以直接搞一个48的段给自己的机房分64的段)作为普通用户,没有静态地址怎么办?那就只有用vps先接到tunnel,然后再tunnel回家了。

tunnel to he

很容易,配一根6to4的tunnel就好。tunnel breaker的网站上还很贴心的提供了不同系统下的详细配置。

这里特别提一下。HE很贴心的提供了两段地址。一段ipv6是你和HE的隧道地址。另一段地址也会路由给你,这才是你内部应当使用的ip地址群。所以原则上说,你可以在隧道中使用(本来应当在)你和HE之间使用的地址的部分。

tunnel to yourself

先随便打一根二层的隧道。

二层的理由是,如果使用三层隧道,那么隧道本身就需要察知ip。于是ipv6的支持就变成隧道的事了。而二层的隧道并不需要知道上面跑什么协议。

最简单的当然是gre隧道。但是gre隧道需要在远端确定本地ip地址,这和直接打一根tunnel回家没什么区别。

我用的方法是用任何一种二层或三层vpn打到vps上,然后上面再跑gre。这样一举解决了加密和静态地址的问题,顺便还解决了ipv6兼容性的问题。当然,代价也很高。由于是在vpn里套gre,所以头部很大,mtu就要开的比较小。

另一个玩法是用ipsec的tunnel模式打通两个网段,于是gre也可以直接通到vps上(甚至可以直接打ipv6 tunnel)。然而ipsec的tunnel模式需要知道双端ip地址,所以其实还是没有什么用。

顺便吐槽一下routeros的ipsec,实在是太废物了。

当然,也可以用支持ipv6的三层隧道。PPTP都有ipv6支持。当然,我看了一眼,要把ipv6 tunnel回来还是有点问题的。

无论怎么配置,这根隧道要用你和HE之间tunnel的部分地址。例如你和HE的tunnel是这个样子:

a:b:c:d::1/64 -> a:b:c:d::2/64

那么你可以将原来的/64改为/112,然后配置这么个tunnel地址:

a:b:c:d::1:1/112 -> a:b:c:d::1:2/112

route

在vps上,需要将routed addresses指向内部的路由器。路由器需要将default路由指向vps。default指过去后其他细节就不用管了。

MTU

由于在两层隧道内跑的ipv6,因此mtu记得调整一下,否则有性能问题。

firewall

防火墙是个大头,所以要单独提出来说。

原则上说,ipv6的所有地址都是外部可达的。因此如果你将路由器上的forward关闭,那就没有使用ipv6的意义了。然而,如果forward打开的话,那么每一台都真实的暴露在公网上了。因此每台必须都配置防火墙,否则就可能有安全问题。

例如通常内网会打开ssh,并且不会打开防扫描,或者做安全加固。如果打开了ipv6,又没有在路由器上关闭forward,那么就会造成这个端口对全世界开放。虽然原则上说,没有人会扫描ipv6(因为一个家里的地址比全世界的ipv4还大)。但是这并不安全。因为会有人从你对外的访问地址看出你的内部机器ip。

所以我的建议是,关闭forward,只对特定地址打开。而这些地址上,都需要保证配置了ipv6防火墙。这样即使不慎接入了一个设备,没有开防火墙。也不会造成安全隐患。当然,缺陷就是,随着接入设备的增多,你的地址列表增加很快。

reference

by shell909090 at August 05, 2015 07:49 AM

July 28, 2015

@delphij

还是得提高知识水平

今天搞了一个 大新闻。如果你用BIND并且今天之前没打过补丁的话,请读到这里为止,立即去补吧。

我觉得还是得提高知识水平。做 freebsd-update 补丁的时候,赫然发现修改的文件中有一个不认识的:

world|base|/usr/bin/slogin|f|0|0|0555|0|3d4103fa290ca0dcd32fc1f9775e860a4bbf4af7e2be80e835217cd560cb100e|

当时就慌了!我明明没改啥库啊?ldd看一下:

/usr/bin/slogin:
	libprivatessh.so.5 => /usr/lib/libprivatessh.so.5 (0x800849000)
	libgssapi.so.10 => /usr/lib/libgssapi.so.10 (0x800ada000)
	libcrypto.so.7 => /lib/libcrypto.so.7 (0x800ce3000)
	libc.so.7 => /lib/libc.so.7 (0x8010da000)
	libprivateldns.so.5 => /usr/lib/libprivateldns.so.5 (0x801482000)
	libcrypt.so.5 => /lib/libcrypt.so.5 (0x8016de000)
	libz.so.6 => /lib/libz.so.6 (0x8018fe000)

还用了 Kerberos,等等,ssh?man slogin出来一个SSH的manpage,一个字没提slogin的事情。

ls -li一看才恍然大悟:

4574 -r-xr-xr-x  2 root  wheel  179000 Jul 19 00:19 /usr/bin/slogin
4574 -r-xr-xr-x  2 root  wheel  179000 Jul 19 00:19 /usr/bin/ssh

原来是马甲......

by Xin LI at July 28, 2015 10:15 PM

July 21, 2015

@shell909090

程序员交友选择题

问题

  1. 你用过lamp么?
  2. 你键盘最左边一列磨损最严重的键是?
  3. 你喜欢3p么?为什么?
  4. 如果你需要改一张图,电脑里又没有装有关软件,你会怎么做?

答案

  1. 没有的就算了吧。
  2. caps lock万岁,其他去死。
  3. python万岁,其他去死。
  4. 首先从可信源下载编译好的包,如果没有下载源码安装。
    • (去商店购买一份ps的去死)
    • (去下载盗版ps的立刻拨打110)

by shell909090 at July 21, 2015 10:38 AM

July 16, 2015

@shell909090

网络值机和无登机牌登记试用手记

最近要去北京,用的去哪儿订的票。他们(准确说是东航)提供了手机值机和无登机牌登机的功能,我就试了一下。

首先在起飞前会收到一个消息,回复姓名和座位偏好之后,就会自动办理登机手续,并发给一个短信。里面包含安检口,座位号和二维码。

看来这个流程只适用于没有行李的旅客。如果有行李的话,还是要去柜台一趟办理托运。当然,由于我都是随携,所以这部分没有测试。

然后短信会提示你到哪里过安检。我不知道是否是只有这几个安检口才支持,所以我还是老老实实的从指定的安检口(不是所有)过去了。拿手机(当然还要身份证)给他后,他会扫一下,给你一张安检条。

然后等飞机,等了好久,居然还延误了。

到登机的时候,还要在登机口和廊桥口两次检查。登机口是要安检条和手机(二维码),廊桥只要安检条。

其他和持登机牌登机没有区别。

下面感想。

手机值机还是挺方便的。可以预先挑好自己喜欢的座位,而且如果没有托运就不必在柜台愚蠢的排队,节约大家的时间。

安检条不知道是怎么回事,看来是没协调完的缘故。从技术上说,可以将安检信息放在二维码里,过登机口和廊桥的时候直接扫码搞定的。我估计是因为东航是东航,虹桥是虹桥。所以东航的系统打通的再好,虹桥的系统不跟着升级也没用,只能打张安检条来过关。

而且下发短信的信息也有点问题。虽然有使用指引,但是却没有登机口。我居然还要问安检。考虑一下登机牌上有什么信息,把他们都做进去好么?

总体来说还是挺满意的。方便,省事,而且不废纸。

by shell909090 at July 16, 2015 04:37 PM

July 11, 2015

@shell909090

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里,例如文件元数据。

  1. http://www.quora.com/Linux-Kernel/What-is-the-major-difference-between-the-buffer-cache-and-the-page-cache
  2. http://www.quora.com/What-is-the-difference-between-Buffers-and-Cached-columns-in-proc-meminfo-output

by shell909090 at July 11, 2015 04:04 AM

July 10, 2015

@delphij

FreeBSD基金会收到史上最大一笔捐款

WhatsApp CEO及创始人 Jan Koum 宣布捐出一百万美元给 FreeBSD基金会。这是 FreeBSD 基金会成立十五年以来收到的 最大一笔捐款

Jan Koum 在他的 Facebook 页面上写道:

Last week, I donated one million dollars to the FreeBSD Foundation, which supports the open source operating system that has helped millions of programmers pursue their passions and bring their ideas to life.

I'm actually one of those people. I started using FreeBSD in the late 90s, when I didn't have much money and was living in government housing. In a way, FreeBSD helped lift me out of poverty - one of the main reasons I got a job at Yahoo! is because they were using FreeBSD, and it was my operating system of choice. Years later, when Brian and I set out to build WhatsApp, we used FreeBSD to keep our servers running. We still do.

I'm announcing this donation to shine a light on the good work being done by the FreeBSD Foundation, with the hope that others will also help move this project forward. We'll all benefit if FreeBSD can continue to give people the same opportunity it gave me - if it can lift more immigrant kids out of poverty, and help more startups build something successful, and even transformative.

by Xin LI at July 10, 2015 01:16 AM

July 07, 2015

@shell909090

flash禁用教程

最近flash一堆漏洞,大家禁用了吧。

firefox

附加组件 -> 插件 -> flash -> 禁用

chrome

浏览”chrome:plugins”页面。
找到flash,禁用。

safari

  1. Preferences
  2. Security
  3. Allow Plugins旁边的Website Settings
  4. 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/

(全英文,但是可以看图)

by shell909090 at July 07, 2015 10:35 AM

July 06, 2015

@delphij

关于闰秒

phk 老大如此 吐槽

One week until the leap-second. If you haven't tested your IT-system already, it is too late now. Good luck if you're in California or Japan.

背景

关于时间,A core 几年前写过一个 时间是什么? 的系列: 序言 续一 续二 续三

为了兼顾天文观测获得的时间 UT1 (更符合普通人的需要)和由铯-133原子震荡获得的时间 TAI (更稳定),将两者综合一下就获得了协调世界时 UTC。UTC 和 UT1 之间的差距永远保持在 1 秒以内。UTC 中的一秒和 TAI 相同,但 UTC 和 UT1 保持最多一秒的差距,这是通过 IERS 在 UTC 事件中人为插入或减少闰秒这样的人为调整来实现的。从1972年这套系统投入运营到今天为止,总共插入了35个闰秒(2015年6月30日还将再插入一个闰秒)。

闰秒只在每年的6月30日和12月31日的UTC时间 23:59:59 之后插入,表示为当天的 23:59:60。

Unix时间

Unix 时间是从 UTC 时间1970年1月1日0时0分0秒起的秒数,但不计入闰秒。这一定义后来又被 POSIX 继承并成为了标准。由于 Unix 时间没有考虑闰秒,因此如何表达闰秒在 POSIX 中是没有定义的。换言之,UTC 时间 2015年6月30日23:59:59的Unix时间是1435708799,2015年7月1日00:00:00的Unix时间是1435708800,两者之间的这个闰秒,根据标准就只能用两个时间之一代替了。很明显,这样一来,在闰秒本身或它后面那一秒,在 Unix 时间戳看来就是完全一样的了。)

这会带来什么问题呢?假如我们令 23:59:59 = 23:59:60,那么如果有事件 A、B 分别发生于 23:59:59.2 和 23:59:60.1,则在 Unix 看来,B发生在A之前,而实际上应该是相反的结果。这样一来,一些程序,例如 POSIX 线程库中某些等待时间采用的是绝对时间,由于闰秒的原因,这些等待可能会提前或推后1秒才会唤醒。又比如,依赖于文件时间戳的应用,如make等,可能会误认为某些文件的修改时间发生了倒序问题,而将已经联编过的文件再联编一遍。一般来说,这些都不至于导致太大的问题,但假如应用依赖于精确的时间,而同时又假定时间戳不会重复的分布式系统来说,这个问题就可能产生比较严重的后果了。

NTP对于闰秒的处理

如果内核支持,NTP 在发现闰秒时,将向内核宣示这一现象(STA_INS 或 STA_DEL),并由后者进行适当的处理。内核的状态机将经历 TIME_OK -> TIME_INS -> TIME_OOP -> TIME_WAIT -> TIME_OK 的变化。在 FreeBSD 的实现中,CLOCK_MONOTONIC 的时间戳将持续前进,CLOCK_REALTIME 的时间戳在 TIME_INS 到 TIME_OOP 状态变化时将倒回前一秒。

如何避免闰秒导致的问题

对于没有使用 ntp/ptp 的机器来说,由于它们本来也无法精确计时,因此自然也就无所谓闰秒了。事实上,这些机器很可能完全不知道闰秒的存在。

对于使用了 ntp/ptp 的机器来说,时间戳可能会出现绕回现象。Google针对闰秒的对策 中提到,他们将引入一个基于余弦函数的调整量(1.0 - cos(pi * t / w)) / 2.0,其中w是闰秒的延展时间。利用余弦函数在0、pi两点的导数为0的特性,这一做法可以避免出现跳变。在延展窗口内,系统时钟由于这种调整被人为变慢。这种做法避免了由于时间戳绕回现象导致的问题,但会导致 Unix 时间戳在某个时间段内不准,不过考虑到反正它也不准(因为符合POSIX标准就不能表示闰秒了)所以似乎也就只能大丈夫了?

另一种比较常见的做法是使用 ntpd 的 -x 参数,不过与Google的做法相比,这种做法引入的随机性更大(Google的做法,整个w周期内的时间戳是点点连续且单调递增的)。

by Xin LI at July 06, 2015 10:07 PM

June 30, 2015

@shell909090

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抄卷子把名字也抄了?

by shell909090 at June 30, 2015 09:25 AM

June 29, 2015

@shell909090

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

论婚姻

从法律上说,婚姻是一种保证性和生育权的制度。他主要反映了统治阶级是如何看待性和生育权的。例如婚姻双方是否在性上面排他,或者是否对称的排他(女性出轨和男性出轨的后果不一样)。双方如何抚养后代(特别是离婚的情况下),如何界定后代继承权。

婚姻制度在开始的时候,出现的目地主要是两个。

  1. 规范性权力。
  2. 促进生育。

其实你仔细想,如果不是因为上两个因素,你爱找谁上床生育,关统治者什么事?最远古时期,一男一女两个生娃,恐怕也不会找民政局去登个记什么的吧。但是随着社会制度的形成,尤其是“私产”和“继承”制度的形成,你找谁上床就不是你一个人的事了。想象一下,如果每个地方的土皇帝都占有了所有的女性,那么其他人怎么办?会不会产生战争?如果一个女性和多个男性保持关系,那么谁(注意以前男性占有多数社会资源)应当抚养她的后代?

所以,世界各个地方开始不约而同的出现了婚姻制度。当然,随着各地情况不一样,婚姻制度也千差万别。例如中国允许一个男性占有多个女性,但是其中只有一个拥有完整的权利。其他女性的权利就会有缺损。伊斯兰教似乎也允许多个妻子(据我听说最多四个)。有些被占领区甚至有“初夜权”的说法(参见“勇敢的心”)。

进入近代,婚姻制度主要是双方具有极度亲密的关系,以及由此衍生的各种权利和限制。例如妻子通常是丈夫的保险受益人,而且拥有在丈夫失去意识时做出各种决定(例如医学决定)的权力。当然,如果你误信非人,这点也经常被用来骗取保险。当然,这种制度同样的,也鼓励生育。

然而这对同性爱人来说并不公平,因为生育要求的基础是一男一女。他们认为自己被歧视了,所以他们也希望在法律的架构下分享各种权利。在同性婚姻不合法的前提下,他们无法和他们爱的人共享各种权利,甚至无法参加告别仪式(因为实际拥有权利的人,例如父母,甚至妻子,可以禁止他们前来)。而且很多同性爱人,因为婚姻的理由被迫和异性结婚。这不但造成了同性爱人的悲剧,还会祸及和他们结婚的无辜者。

区分婚姻的定义

我认为应当将“亲密双方共享权利”和“性以及生育”分开,甚至性和生育都应当分开。某个权利或限制,到底是给予“亲密双方”还是“有性关系双方”,抑或是给予“一个孩子的父母”。在今天看来,三者不再完全的等同,而且分别越来越大。

性和生育的关系

今天,男女找谁上床不再和婚姻划上等号。你可以坚持婚前无性,但是你不能强迫所有人结婚后才发生关系。

当然,在很多地区,婚姻对性的纯洁性(尤其是女方纯洁性)的要求还是非常苛刻的。据我所知,很多地方,丈夫发现妻子不纯洁后,可以将她送回娘家。她的父亲或者兄弟为了洗刷耻辱,会将其生生打死。而丈夫发现偷情的妻子,可以私自处以投石的刑罚。国家并不会惩罚凶手。

但是在另一些地方,性已经和婚姻没有什么太大联系了。我的预计是这些地方会越来越多,逐渐扩大。

当然,有一些权利和限制是需要给予性的,例如儿童色情的禁止等。但是这事和婚姻关系不大。

生育和亲密关系的关系

如果你想清楚的话,其实两者没有关系。想的更开一点,你可以管“共同生育”的关系叫做“婚姻”,管“亲密关系”的关系叫做另一个名词。只要你彻底分开两者的权利细节,其实并没有特别的理由去阻碍同性爱人分享权利,承诺责任。

例如,为什么要阻止同性的爱人能够共享关系内财产呢?

又例如,为什么要阻止双方承诺扶养对方的义务呢?

将两者分开后,你会突然发现——为什么要阻止同性婚姻呢?完全没有道理么。非但不需要阻止同性婚姻,而且到底是“嫁”猫“嫁”狗都无所谓(实际上法律意义上说对象必须具有人格)。到底是“娶”男人“嫁”亲爹,其实完全没有必要阻止——这既不体现性,也不体现生育。

但是我比较倾向于认为,既然生育和亲密关系是两回事,那么很多为生育而制定的规定就不应当延续到亲密关系上。这种改变不是把结婚条款中的服务双方必须是一男一女改成可以同性就结束的。

例如有些国家为了鼓励生育,对夫妻婚后的财产税收缴纳有相当的优惠。我不清楚婚后纳税是否完全是为了鼓励生育,但如果有这种成分的话,那么把这种鼓励延续到同性关系上就是不正确的行为。

同性性关系

这节是最复杂和有争议的一节。

把生育和亲密关系分离,其实不是解决问题的终点,而是问题的开始。很多问题,是同性关系中特有的。你要把它在亲密关系中规范,那就对异性婚姻者不适用。所以同性婚姻的出现,必然开始很多对同性性关系的规范。当然,这些也不一定在婚姻法范畴内。

例如鸡奸罪。你不可能允许同性结婚,却宣布鸡奸有罪。我靠,这是在逗我玩么?

又例如强奸。很多国家强奸罪的客体,必须是一男一女,甚至必须是男性对女性。那问题来了。一对亲密关系中的双方,其中一方受到第三方(三者都是同性)的强奸。但是只能以故意伤害论处?或者更夸张的情况。一对男同性爱人结婚,婚后其中一人被一个女色魔强上(好可怕,这比中国的电视剧更荒谬)。对于这种情况,也不能算强奸?

如果不修正这点,恐怕也不是有点荒谬吧。

oh, BTW。美国法律已经规定强奸罪可以是任何性别对任何性别了,所以以上例子仅仅是例子,OK?

我在说什么

开始的时候,我们需要管理一些关于性,生育之类的问题。于是架构师发明了一个叫做“婚姻”的类,在上面附加了规则,事情就结束了。

后来发现,婚姻这东西其实没法满足需求。因为婚姻上的很多规则是生育的,但是有一些同性的couple需要用他。

怎么办呢?拆类呗?

这个重构工作居然持续了20-30年,你们还好意思说程序员慢?

by shell909090 at June 29, 2015 06:29 AM

June 24, 2015

@shell909090

一个有趣的python问题

quiz

今天在twitter上看到一个有趣的问题。

t = (1, 2, [30, 40])
t[2] += [50, 60]

结果是什么?

  1. t = (1, 2, [30, 40, 50, 60])
  2. TypeError
  3. 都不是
  4. 1,2都发生

出乎意料的,结果是4。

为什么,我们来分析一下。

disassemble

>>> t = (1, 2, [30, 40])
>>> def f(): t[2] += [50, 60]
>>> import dis
>>> dis.dis(f)

以下是结果。

       0 LOAD_GLOBAL              0 (t)
       3 LOAD_CONST               1 (2)
       6 DUP_TOPX                 2
       9 BINARY_SUBSCR
      10 LOAD_CONST               2 (50)
      13 LOAD_CONST               3 (60)
      16 BUILD_LIST               2
      19 INPLACE_ADD
      20 ROT_THREE
      21 STORE_SUBSCR
      22 LOAD_CONST               0 (None)
      25 RETURN_VALUE

我们来解读一下。dis的指令集可以看这里

  1. 先载入全局变量t(因为写法问题,t是全局)。
  2. 载入常数2。现在栈是t|2。
  3. 复制头两项。现在栈应当是t|2|t|2。
  4. BINARY_SUBSCR,取t[2]。现在是t|2|t[2]。
  5. 载入50和60,然后build_list。现在是t|2|t[2]|[50,60]。
  6. INPLACE_ADD,注意这里。现在是t|2|[30,40,50,60]。同时t[2]的list成为了[30,40,50,60]。
  7. ROT_THREE,结果是[30,40,50,60]|t|2。
  8. STORE_SUBSCR,实际是在操作t[2] = [30,40,50,60]。当然,这里出错了。
  9. 最后是return None,这步并未发生。

compare with add

整个最诡异的地方,就在于INPLACE_ADD。从字面上,这要求inplace的做加法。我们换个写法,然后再看看。

>>> def f(): t[2] = t[2] + [50, 60]
>>> f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in f
TypeError: 'tuple' object does not support item assignment
>>> t
(1, 2, [30, 40])
>>> dis.dis(f)

以下为结果。

          0 LOAD_GLOBAL              0 (t)
          3 LOAD_CONST               1 (2)
          6 BINARY_SUBSCR
          7 LOAD_CONST               2 (50)
         10 LOAD_CONST               3 (60)
         13 BUILD_LIST               2
         16 BINARY_ADD
         17 LOAD_GLOBAL              0 (t)
         20 LOAD_CONST               1 (2)
         23 STORE_SUBSCR
         24 LOAD_CONST               0 (None)
         27 RETURN_VALUE

看到没,结果就不一样了。

why

没有为什么,因为+=对应的指令就是INPLACE_ADD。

只是INPLACE_ADD了,理论上就不需要赋值了。我没想明白的是,在什么情况下INPLACE_ADD了又不赋值可能导致错误呢?(我觉得可能有这种情况)

by shell909090 at June 24, 2015 09:57 AM

June 23, 2015

@delphij

换了zsh

作为十几年的 tcsh 拥趸,我最近改信了 zsh。

基于 Robby Russell 的 Oh My ZSH 搞了一套自己的 Oh My ZSH,可以用 ZSH_THEME="delphij" 来启用我的配置,其外观、行为大致与我之前的 csh 配置相同。

经过PGP签名的tag版本可以在 这里 找到(请自行使用安全的方法获得我的PGP公钥)。

安装方法(假定当前shell是zsh或sh或bash):

$ ZSH=~/.oh-my-zsh
$ git clone --depth=1 --branch=delphij-20150522 http://github.com/delphij/oh-my-zsh.git $ZSH
$ cd $ZSH
$ git tag --verify delphij-20150522
# 以上复制一份tag过的 Oh My ZSH 并验证其签名。
# 如果有之前的.zshrc请自行备份。
$ cp $ZSH/templates/zshrc.zsh-template ~/.zshrc
$ sed -i '' -e "/^export ZSH=/ c\\
export ZSH=$ZSH
" ~/.zshrc
$ sed -i '' -e "/export PATH=/ c\\
export PATH=\"$PATH\"
" ~/.zshrc
# 以上使用模板覆盖.zshrc并复制已有的PATH配置。
chsh -s `which zsh`
# 将shell改为zsh

需要注意的是,由于 zsh 并非系统自带的 shell,因此保留一个非 zsh 的 root 账户会是个好主意。

by Xin LI at June 23, 2015 03:03 PM

June 17, 2015

@shell909090

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问题。

by shell909090 at June 17, 2015 08:46 AM

May 29, 2015

@delphij

逗死我了......

对口相声选段:Node.js Is Bad Ass Rock Star Tech。视频:

p1: And in conclusion we have found Apache to be an excellent server for our web applications. Any questions?

p2: Yes, I have a question. Why didn't you use node.js? node.js is an event driven, non-blocking IO server that can be used to build high-performance web applications.

p1: That is an excellent question. We evaluated several alternative web servers and concluded, that while options like node.js are very interesting, Apache meets our needs and has a solid track record.

p2: But it doesn't have performance. Everybody knows that Apache applications are slow because they use blocking IO and have context switches.

p1: That's a commonly held belief that threaded web servers are somehow less performant or as scalable than event based servers. In fact, if you measure carefully, you will find that both models have similar performance characteristics.

p2: Threads don't scale. Simple as that.

p1: That may have been true 10 years ago. Its not true today.

p2: node.js will run circles around Apache because Apache was built before asynchronous was discovered.

p1: This is where I typically stab myself repeatedly in the ears with a fork until I stop hearing you. I've looked at node. It uses a single threaded loop that dispatches events to handlers. Its a proven model that solves some concurrency problems but at the cost of code complexity.

p2: It gives techies like me the control to wring every last CPU cycle out of our servers.

p1: It must feel empowering to be totally responsible for the performance of your application. To be always on the lookout for blocking operations that should be split into little pieces each perfectly tailored for concurrent throughput. All the complexities of assembler with all the speed of JavaScript.

p2: I'm a total speed junkie

p1: Do you know what this reminds me of?

p2: The invention of the transistor.

p1: It reminds me of the invention of threads. Threading libraries do exactly what your doing manually. They break up pieces of code to be executed intermittently, switching from instructions that are waiting on IO to instructions that are ready to run, but your sequential code stays intact. You may recall sequential code. Its the code that you can read.

p2: But its slow as a dog

p1: Your asynchronous program is like something from a 19th century Gothic horror story. Drunk with your own sense of power, you reassemble pieces of code that were once coherent, stitching them together with event loops and callback functions, until your monster, grotesque and menacing, is ready to be brought to life in a JavaScript VM. You throw the switch and the hideous creature awakes, rises, and lurches forward. you're simultaneously elated and terrified that something so unnatural code work at all. When you realize what you've unleashed, the pure immorality of it, your creation reaches out with its bloody, mangled arms, and strangles you.

p2: But its fast as hell

p1: If your willing to suffer complex code for performance, why not write an nginx module and see?

p2: node.js is the most bad-ass rock-star tech to come out since Ruby On Rails.

p1: As much as I want to be an optimist and look forward to human progress, people like you make stop me dead in my tracks. Your a fanatic in the church of technology fashion. I could present you with fact after fact after fact of why your thinking of asynchronous programming is completely wrong. But why bother when you equate technology to rock bands, and fancy yourself a software hipster by wearing your node.js t-shirt and celebrate horrible code. Maybe your cool, hell, maybe you have groupies. But when it comes to knowing what the f*ck you're talking about, you have the facilities of a parrot who says "non-blocking" over and over again.

p2: Non-blocking is the secret in the asynchronous sauce. With it, you go fast. Without it, you go slow.

p1: Do you know when humans discovered that the world was round?

p2: 1492. Columbus sailed the ocean blue.

p1: It was 240 BC by a Greek mathematician named Eratosthenes. He conducted a simple experiment using the length of shadows and the distance between cities to not only prove the earth is round, but to also calculate its circumference.

p2: Sounds low-tech.

p1: It was utterly brilliant. But somehow, for one and a half millenia, it was common knowledge that the earth was flat. Hundreds and hundreds and hundreds of years in daft ignorance. How in mother-f*cking hell does this happen?

p1: It was you. You who makes claims about thread performance without measuring. You who claim hacking your code with a machete, turning it inside out into a twisted, unrecognizable mess will somehow make it go faster. You, who spend your time alternating between problems that are already solved and problems that don't actually exist. You are the reason science was set back 1,000 years. The reason we have not cured cancer. The reason we have not solved world hunger.

p1: Its because of you, mother f*cker, that we are not all using Lisp.

p2: I'm sorry, what was that last part again?

p1: Never mind.

p2: Did you just say Lisp?

p1: You misheard me.

p2: I could've sworn you just said lisp.

p1: If there are no other questions, this concludes my presentation.

by Xin LI at May 29, 2015 08:23 PM

@shell909090

携程本次问题分析

携程这次的事情,实在没啥好多说的了。要骂的话,早就骂过了。我们就来说说携程这次事故中,我们能确定的事情吧。

小道消息

首先我要排除一切小道消息,包括数据库被“物理”删除了,前任总监报复,运营妹子和高管好上了什么的。昨天和朋友开玩笑,物理删除要怎么做呢?你要盯着硬盘,直到他羞愧到不能淡定,自己从服务器里裸奔出来,纵身从楼上跳下去。这才叫物理删除。第二天报纸准出新闻——硬盘们,不要着急,等待反弹。。。

至于前任总监报复,运营妹子和高管好上了。我越听越像电视剧,还是国产的。这些没影子的事情就不多说了,我们来说点有用的。

事实

首先,我们要搞清楚一个问题。携程自己说的话,是没用的。

是的,无论是故障时的混乱情况导致说错话,还是出于稳定情绪角度的说辞,都没太大价值。最多用来旁证分析。我们还是要追踪当时发生的,确定无疑的事件,以这个来佐证。

我们可以确定的事情有:

  1. 携程的系统挂了近12个小时。
  2. 挂掉的是应用层,而不是数据库层。
  3. 携程下午到晚上悬赏解决问题。
  4. 恢复后,历史数据存在,当然部分出问题时的数据丢失(这是必然)。

14是大家都看的到的。2是因为没有数据库连不上时的各种应用错误提示,干脆就是网页直接失踪。这说明问题不是光缆挖断,也不是数据库(至少不能直接佐证)。能够确认的是应用确实没了。3是来自道哥的消息,我觉得应该比较靠谱(毕竟涉及钱)。

分析

好,综合123,我有个推论。携程在出问题的时候,很快就知道了是应用的问题(至少确定应用有问题)。然后试着恢复,但是无效。原因携程自己都不知道。

这是自然。如果携程不知道应用层有问题,太业余。没试着恢复,太二。恢复了有效,不像。携程知道为什么,那还发布个毛悬赏?综合起来,那就是恢复了没见效,而且携程自己都不知道原因了。

同时这个结论也隐隐的排斥高管报复说,至少携程当时不能确认是高管报复,而是作为通用性技术问题来处理的。如果是高管报复,你找外人来管个毛用啊。再黑自己一遍?

当然,这个推论有个前提。携程的悬赏不是为了转移视线的烟幕弹。不过看当时的情况,我觉得这种可能不大。

那么问题的技术细节呢?不知道。携程自己找到没找到原因?不知道。我们知道点啥?数据库备份没事。

是的,我没法确认当天数据库没事(因为我没有当天订单)。不过看事后没人吐槽,估计是没事的。

事后

携程事后说是程序员错误的删除发布的应用,这个和上文“问题出在应用层”一致。在问题原因上,携程没多大掩饰的空间。但是“程序员误删除”这个说法是真是假就不好说了。实话说,这个说辞显得像是背黑锅,推责任。但无法排除,确实可能是事实的真相。

但是这个说法无法解释的是,为什么恢复时间那么长,而且还开出了悬赏。编译整个系统,然后重新发布确实很慢。但是一来时间不会如此长。二来更关键,程序员非常清楚问题在哪,要花多久。你找个技术专家来弄这个事情也未见得快。而且就算要找,也肯定限制在所用技术系统的编译和发布专家里找,不会满世界的开悬赏。如果真的是重发布时间过长,领导层又挂出了悬赏。这无疑是在瞎指挥。

最后就是“携程在系统上做了改进,规范并杜绝技术人员错误删除生产服务器上代码的操作”。这里明显漏了一个要点”加强部署和恢复演练和自动化推进“。

一般来说,在系统设计的时候,首先考虑的是“如果不小心被删除了怎么恢复”。而不是“如何防止错误的删除”。就像我和一位同事解释的,你可以将rm替换成别的程序,但是如果对方用的是dd呢?如果是chmod呢?如果下次,操作人员执行的不是删除,而是格式化呢?或者是更改ACL权限错误。这无疑要求限制所有操作人员能做的事情。

银行里就是采取的这种思路。每个运维能做的事都被严格限死,很难越雷池一步。但是同时要注意两点。首先,银行的业务相对固定,运维要干的事非常规范。携程的运维恐怕很难做到如此规范。其次,银行是有严密的恢复机制的,恢复机制(包括演练)也是运维的固定工作之一。

考虑一下。如果没有恢复演练。那么万一因为不可知因素,携程需要再度恢复(好倒霉。。。)的时候。运维有没有删除数据的权限呢?有没有修改权限的权限呢?携程的”杜绝技术人员误删除“的手段,还要不要坚持呢?

多说一句

网络上有个哥们猜测”可能是高管报复“的时候,推测是在编译环境里做手脚。这个和我当时的观点一致(不代表我认同他说的这个事实)——要让多个系统始终编译和发布了都不能工作,最有效的后门就在编译环境里。毕竟很少有代码能够跨越多个系统,但是几乎所有项目都会使用同样的编译环境。

by shell909090 at May 29, 2015 04:43 PM

May 27, 2015

@shell909090

程序的持续更新

今天有个朋友来问我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年,要找老部件就非常困难了。合理的选择还是弄个新的吧。

by shell909090 at May 27, 2015 08:24 AM

May 19, 2015

@shell909090

试题设计的原则

原则

其实主要就两点。

  1. 分辨率足够。
  2. 简单。

第一点很容易理解。你的题目必须能准确区分傻逼,普通人,和牛逼,因此最理想的状况是,傻逼考零分,牛逼满分,普通人在中间。所以你的题目应该简单。如果题目难到普通人和傻逼一起做不出,那就没有区分能力了。如果不是正好碰到一个牛人,你的考试只能让你啥都招不到。这会把你自己变成傻逼。

所以,你的题目应该有一半是普通人能够做出来的,而不是道道都是神一样的面试题。之所以你在网上经常看到神一样的面试题,那是因为。

  1. 大公司不缺应聘的人,所以他们的“牛人线”比较高。
  2. 你能看到的题目,都是最牛逼的。

当然,题目中确实应当有一些有难度的题目,用来区分真正的牛人。这部分人我们要特别料理他们。

复用题库

混合一个题库,每次面试抽取不同题目形成试卷,这是常识了。

主要是防止试题外泄,还有重复出题造成的疲劳。

当然,每个题目需要加不同的属性,用于后面的一些分析。在抽题的时候也需要参考属性,例如上面提到的难度。

经验题还是能力题

我把试题分为两个类型。一类是测试你是否用过某项技术,用多深。另一类则是你的智力如何,学习,沟通,理解能力如何。

可以预期的是,刚毕业的人,经验题得分会低一些。不过在实际生产中,这些人出活的能力一向不差。所以对于刚毕业的学生,可以在经验题得分上宽容一些。

区分领域

在试题设计中,经常需要测试多个领域。例如网络,系统底层,等等。

将多个领域的题目分开标注,有利于你最终评定这个人的技术范畴。例如系统底层出色,但是网络很糟糕,这显然就不适合扔去一个重网络开发的组。

限制总量

这点才是整个试题设计的核心难点。

长时间的笔试是很高成本的。对于被考试者不是什么很好的体验,对于考试者来说,要出题,要判卷。考试期间还要招待人家,进行计时。如同马拉松一样的考试没有任何好处——除非非常必要。

但是正常来说,技术面试应该要问系统原理,算法,网络,编程语言,智力题等等,至少这么五个方面。每个方面一道题区分普通人,一道题区分牛人。这就是10道题。再复合上经验和能力的区分,还有为了对抗偶然而要每个组合多几个题。综合起来可能多达20-30道。这样1小时的笔试时间,每道题上只有区区2-3分钟。这点时间根本不够考核一些深入的问题。

所以如何减少问题的数量,而非增加数量,才是核心难点。

我的想法是增加过程叙述题,让被试人对一些经典过程做描述,并规范他一定要描述到哪些方面。以此来分析他对一些领域的基础。但是这方法有个明显弱点——不好执行不好打分。

关于这方面大家有啥意见?

by shell909090 at May 19, 2015 03:43 AM

May 12, 2015

@shell909090

Sysctl Timestamp对速度的影响

不知道我是不是写过了。

sysctl中有一个内核设定:

net.ipv4.tcp_timestamps = 1

这个值默认被设定为1,但是当这个设定被设定为0时,会导致tcp序列号高速绕回,从而导致传输速度上限。

tcp的最大报文生存时间(MSL)默认值为60s(这也是为何TIME_WAIT默认120s的原因)。而tcp序列号只有32位,未来区域只有2^31。

2**31 * 8 / 60.0 / 1024 / 1024 = 273Mbps

因此当关闭timestamp时,最大传输速率不超过273Mbps。

在公司内部曾出现过这个现象(由于某个理由,错误的关闭timestamp),在自建系统上的测试也验证了这点。

使用iperf对性能进行测试,最大速度为266Mbps。

但请注意,被设定后,需要长达10分钟以上的时间才会发生效果。因此需要在设定后半小时后,去用iperf检验设定是否生效。

by shell909090 at May 12, 2015 03:33 AM

May 05, 2015

@shell909090

电池标注不好,你上不了飞机

问个问题。谁知道锂电池上飞机的标准。

我在这个页面找到了解释。这是首都机场的主页,还是比较可信的。

  1. 单块电池能量应小于100Wh。100-160Wh的电池需要航空公司批准,160Wh以上的不得上飞机(其实可以按照危险物品托运)。
  2. 在飞机上的锂离子电池,应当随身携带,不应当托运。做好绝缘隔离保护,不要在飞行过程中充电。
  3. 电池总量应小于160Wh(关于这点我不确定,规定相当含糊,解读也可能完全不同)。

OK,上面的事情很多人可能都知道。所以呢?这篇文章重点在哪里?

  1. 按照普通锂电池放电电压3.7V计算,100Wh的锂电池大约合27000mAh。目前主流的两万毫安时电池还不足以达到这个标准,但是看起来很快了。最大能带上飞机的电池规格,应该是25000mAh这个级别。
  2. 按照这篇注解。如果你的锂电池没有标明能量,也没有标明放电电压,只有一个电池容量。是不能上飞机的。哪怕只有1000mAh,没有标注放电电压的电池,从标准执行可能性上就会被没收。

2也许出乎很多人意料外。1000mAh的电池,要满足100Wh标准,其放电电压需要高达100V。目前好像没有任何一种材料的放电电压能达到这么高(变压转换除外)。但是在执行上,硬生生就成了二等公民。

电池的要点并不在2W mAh,而是标注。因此买电池的时候,请注意电池外壳上是否带有清晰的容量标注。

当然,很多机场是压根不执行这么严密的限定的。如果你对这点很有信心,那不妨当我没说。但是这次在太原武宿机场,就正好碰到了这待遇。

笔记本电池电量大的多,更容易碰触到100Wh的限制(例如我的笔记本,三芯电池60Wh,六芯多数就要超标了)。这种情况下,万一不让上飞机很麻烦。考虑到这点,如果你要新买笔记本的话,建议你买一个电池能量100Wh以下的。

by shell909090 at May 05, 2015 03:24 AM

April 22, 2015

@khsing

Youtube downloader 又来一个

youtube-dl 又一个 Youtube downloader,不过这次这个真实大赞,支持的网站还真是多啊。

而且功能很强大,比如下载一个质量超级棒的,带字幕的(Youtube only)

$ youtube-dl -f bestvideo+bestaudio http://www.youtube.com/watch?v=POu1e71OlMo --write-auto-sub

by Guixing at April 22, 2015 11:00 AM

@shell909090

python代码写给你看 [广告]

最近有个朋友问我有没有意向写点和python有关的东西。我说没啥想法。要入门,看dive into python足矣。要学最准确的用法,当然是看python manual。两者都有很不错的中译本了,我还有什么可写的呢。朋友说看了这俩可不代表会写程序啊。我说要真的学会,你只有亲自来看我是怎么写的了。朋友说正好,我们这里就是录电子课程的。。。

所以我就录了这份python代码写给你看。其实录的很粗疏,并不适合纯粹的初学者。因为里面并没有“讲解”python是什么,print是什么,对象是什么。这些东西基本都是在课程中随口提到的。如果没有看过入门书的人,直接看视频的结果就是看一个点卡一个点。也因此,我只推荐“看完了python入门书”,希望“能够像真正的python程序员一样工作”的人来看。

同时,这份视频在求解的时候经常思路卡在那里。因为我追求“必须让观看者看到我真实的代码过程”,所以里面的大部分问题,并没有提前准备过程。我觉得,提前把代码写好,然后到录的时候咔咔敲出来,漂亮是漂亮了,还不如让你直接看源码来的方便。这里的很多问题,我都是当场推论如何解决的。有些问题甚至上来思路错了。但是我觉得这些都不重要。我觉得看到如何使用各种手段去发现,改正错误,比看到正确的代码更有用。

录到最后。我和朋友说,我觉得不能再录下去了。整个视频里提供的问题已经太凌乱没有体系了,再录下去就变成了“现场用python解决各种奇怪问题的,没有人看的大杂烩集合”了。谁愿意总是看一个胖子程序员在那里唠叨一堆问题他是怎么解决的呢?但是我又不大满意。仅仅这里提供的几个例子,并不能完整的反映一个python程序员日常工作中碰到的各种问题和如何解决。比起上百小时的实际工作来说,录像能提供的时间无疑太短了。

无论如何,我最终决定,还是把现在的工作放在这里,放给大家看。希望能够成为大家在python入门之路上的,一颗微不足道的小石子。也希望将来,我能为这份教程去芜存菁。

请大家批评指正,谢谢。

PS:音量的问题就别吐槽了。我们设法改善了几次,最后发现有很多听不清的内容是因为我的“小黄鸭调试法”。简单来说就是没思路的时候就开始自言自语,描述一个个部分的用途,试图发现里面的问题。结果这些自言自语变成了背景里的念经。。。

也许下会我会专门录个“shell读kernel”当睡前读物录音。因为那会更加的颠三倒四语无伦次。。。

by shell909090 at April 22, 2015 07:46 AM

April 21, 2015

@shell909090

ppa的使用

最近用ppa做了backport,这里记录一下用法。

编译简述

ppa的大概工作原理,和mentors非常类似。

  1. 包一个deb包,然后build这个包,生成dsc,deb,build和changes。
  2. 上传这些文件,然后ppa丢弃所有deb(是的,ppa不接受编译好的包,因为可能在编译过程中被做手脚),从源码编译所有文件。
  3. ppa生成了一堆deb文件,并丢到一个特别的目录下。
  4. ppa为这堆deb文件做签署。
  5. 最终用户将这个目录添加到apt源中,就可以安装这些包了。

这里有几个细节:

  1. 服务器怎么知道是你上传的包?
    答案是在打包时进行签署,所以dput是不验证身份的。也因此,你需要将自己的gpg key上传到服务器。
  2. 既然不需要deb,如何构建一个没有deb的编译?
    答案是debuild -S。当然,这也可能有变化。如果是建立一个已经存在的包,是-sd,否则是sa。后面还可以用-k\<keyid>来指定
  3. 最终用户如何构建信任?
    答案是由ppa编译,由ppa签署。用户并不导入维护者的任何key。但是如果用户不信任维护者,那么维护者可以在包内夹杂任何恶意代码。因此ppa只解决安全传递和构建,而不解决维护者信任问题。

申请ppa

不废话,自己去launchpad申请。这个是要ubuntu one帐号的,然后openid认证。不过不算太麻烦。

添加key

首先需要生成gpgkey,这里不解释如何生成key pair。

然后需要将key pair上传到ubuntu key server。我不知道其他key server最终会不会同步,但是即使会,同步时间也是长的那啥。

gpg --keyserver keyserver.ubuntu.com -send <keyid>

这样就行了。

设定dput

这个页面有解释。在ubuntu 9.10以上版本,可以直接dput ppa:userid/ppa <source.changes>来上传。如果是更老版本(或者像我一样用debian),可以设定~/.dput.cf来工作(刚刚的页面下面有样例,照着改就行)。

添加ppa

使用add-apt-repository ppa:userid/ppa就行了。本质上,他做了两件事。

  • 在/etc/apt/sources.list.d/下面生成一个文件,将你的repository添加到系统中。
  • 将ppa的sign key导入到系统中,并添加信任。

by shell909090 at April 21, 2015 09:54 AM

April 20, 2015

@khsing

在 Yosemite 下使用 JDK 1.6

首先下载一个 OS X 的 JDK 1.6.

然后要使用Maven的话,还要安装 3.1 的版本,之后的版本就要求 1.7 起步了。

$ brew install homebrew/versions/maven31

by Guixing at April 20, 2015 12:35 PM

April 16, 2015

@khsing

在 OS X Yosemite 里用 Homebrew 来安装 Tomcat

部分内容用到了Java,所以机器上需要安装JDKTomcatJDKOracle JDK下载站拖回来安装。

然后是brew install tomcat就好了,启动使用catalina start,默认在http://127.0.0.1:8080。停止就catalina stop

by Guixing at April 16, 2015 08:03 AM

April 14, 2015

@khsing

OS X下使用Homebrew来管理服务

使用Homebrew时,经常有一系列的服务要安装启动,通常的做法是copy一个plist文件到~/Library/LaunchAgents目录下再launchctl load一下,比较麻烦。

今天发现了一个不错的玩意-brew services

  1. 安装: brew tap gapple/services
  2. 使用: brew services restart mysql

下面是我的brew services list

$ brew services list influxdb started 658 /Users/khsing/Library/LaunchAgents/homebrew.mxcl.influxdb.plist dnsmasq started 34881 /Users/khsing/Library/LaunchAgents/homebrew.mxcl.dnsmasq.plist nginx started 39552 /Users/khsing/Library/LaunchAgents/homebrew.mxcl.nginx.plist postgresql started 676 /Users/khsing/Library/LaunchAgents/homebrew.mxcl.postgresql.plist php56 started 45046 /Users/khsing/Library/LaunchAgents/homebrew.mxcl.php56.plist redis started 668 /Users/khsing/Library/LaunchAgents/homebrew.mxcl.redis.plist mysql started 34225 /Users/khsing/Library/LaunchAgents/homebrew.mxcl.mysql.plist

而且这个还可以帮助清理brew services cleanup,居家旅行必备。

参考来源:Starting and Stopping Background Services with Homebrew

by Guixing at April 14, 2015 07:51 AM

清理Yosemite的DNS Cache

10.10.1以后就没有mDNSResponder了,取而代之的是discoveryd,所以清理DNS Cache的方法也不一样了。

sudo discoveryutil udnsflushcaches¬

by Guixing at April 14, 2015 05:44 AM

March 24, 2015

@shell909090

EFI和GPT的研究

EFI和GPT的关系 关于EFI和GPT的解释我就不说了,相信来看我blog的人 … 继续阅读

by shell909090 at March 24, 2015 08:04 AM

March 17, 2015

@khsing

打开spdy支持

把自己的站都给放到SSL下也有一阵子了,以前用startssl,头几天更新证书的时候StartSSL宕机了,索性就买了ssl。

今天打开了nginx 1.6的spdy支持,非常简单。

listen 443 ssl spdy;

by Guixing at March 17, 2015 03:23 PM

debian locales错误

某台debian机器的locale执行出现如下错误

locale: Cannot set LC_CTYPE to default locale: No such file or directory

出现这个一般是locale文件缺失,需要重新生成

dpkg-reconfigure locales

选中需要的locale就可以了

by Guixing at March 17, 2015 07:53 AM

March 10, 2015

@delphij

OpenBSD的spamd

许久不碰反垃圾邮件的事情了,一来前段时间垃圾邮件确实也没有那么多,加上spamassassin确实相当有效,二来也是因为犯懒。

不过,最近几天垃圾邮件明显比平时多了许多,所以决定坐下来仔细处理一下。

OpenBSD 的 spamd 是一个反垃圾邮件陷阱软件,它的主要功能是灰名单(SMTP协议要求客户端在一段时间之内重试投递),但又有一个个人很喜欢的特性:以极慢的速度回应发送垃圾邮件的服务器(默认配置为1秒一个字符,最高可以到10秒一个字符)。对发送垃圾邮件的人来说,这样做会显著地降低他们发出垃圾邮件的能力。

结构上,spamd 会修改服务器上的防火墙的转发规则中的地址,简而言之,是维持一份动态的白名单(由通过了灰名单测试的IP形成),所有不符合白名单的IP都转到 spamd 处理。如果符合白名单,则直接正常转到MTA去处理。

简单记一笔配置。

由于我的机器内存够用,所以将 spamd 配置为最大拖住1024个连接。灰名单最短等待期设置为 1 分钟,灰名单过期时间设置为 4 小时;白名单过期时间设置为 36 天。

选择的黑名单是uatraps和nixspam,各自用本地白名单做补。此外,本地另设一黑名单。

启动spamd服务并更新pf规则。接下来用:

grep 'Passed CLEAN {AcceptedInbound}' maillog* | \
cut -f3 -d[ | cut -f1 -d] | grep -v : | sort | uniq -c | \
sort -n | awk '{ if ($1 > 20) print $2; }' | sort -n | \
xargs spamdb -a

来将过去几天的 Amavisd 认为没问题的地址加入本地白名单。

最后可以用 spamdb -Ta 来添加一些陷阱地址。陷阱地址是那种故意流出,但绝不应该收到邮件的地址。

by Xin LI at March 10, 2015 11:49 PM

February 26, 2015

@shell909090

FIN-WAIT-1的问题一例

这是一个早应该知道的事情。但是还是被整了半天。 引子 tcp关闭时有多少个状态? … 继续阅读

by shell909090 at February 26, 2015 08:52 AM

February 23, 2015

@delphij

苏局语录之今儿咱聊聊电梯的事儿......

我有一心得和大家分享一下,话说三个人一起坐一电梯上,其中一个一直跳一直跳,一个蹲在角上一直祈祷,一个满地打滚手脚抽搐,最后都到了十二楼,若干年以后有人问为什么您能到楼上啊?第一个人说,我坚持不懈的努力,和大自然对抗,力竭也不放弃,最终达到了这个巅峰,第二个人说,我真诚而且坚持,我坚持自己的信仰从未忘记初心,第三个人说,我反直觉反传统反对一切,于是创造了完全不可思议的结果。我看很多商业书籍就这感觉,你们几位不聊聊电梯这事到底几个意思?

by Xin LI at February 23, 2015 08:47 PM

February 17, 2015

@delphij

FreeBSD -CURRENT随机数发生器问题

今天 John-Mark Gurney 修正了一个影响过去4个月左右的 FreeBSD -CURRENT 的随机数发生器问题,具体受影响的版本是 r273872(引入问题)到 r278907 (修正)。

由于问题只影响 -CURRENT,因此我们不会就此发表安全公告。

问题的影响:在对随机数发生器 (/dev/random)进行重构的过程中,原先为内核 arc4random(9) API 进行初始化(seeding)的部分没有正确地在新的随机数处理器上线(randomdev_init_reader)时进行配置,导致内核一直使用 dummy RNG 来生成 arc4random(9) 的种子。由于 dummy RNG 的输出范围有限(大约 2^30),导致 arc4random(9) 的输出容易预测。

由于 arc4random(9) 同时也用来在用户态代码中产生随机数种子,因此这个问题也连带影响了用户态的随机数生成(由于 arc4random(9) 在内核中被广泛使用,因此或多或少地减弱了这个问题的实际影响,但我们建议用户不要因此而产生侥幸心理)。

我们建议使用这些版本的 FreeBSD -CURRENT 的用户 立即 升级到最新的 -CURRENT,同时销毁并重新生成在这段时间内生成的全部私钥。

by Xin LI at February 17, 2015 06:52 PM

February 12, 2015

@delphij

假设 3721 = x * y,其中x, y 均为整数,则 x+y 最大是多少?

翻了个船,记一笔。题目如题。

已知 x、y 为整数,由于 3721 是正整数,因此 x、y 符号相同且均不为0。又,题目所求是 x+y 的最大值,故只需考虑 x、y 的正整数解情形。

由 x * y = 3721,令 y = 3721 / x,则 x + y = x + 3721/x。由于 x > 0 且为整数,可知所求为符合条件的 max(x2 + 3721),或 max(x)。

将 3721 开方得到正整数 61。由此可知 x = y = 61 是 xy=3721 的一个整数解。61 是质数,于是很想当然地得到了错误答案 = 61+61 = 122。掉到这个坑里的主要原因是想太多了,实际上题目最终要求的是 x 的最大正整数解,换言之,此类问题:已知C为正整数,C = x*y,求 max(x+y) 的结果应该是 (C+1),不需要任何超出小学算术的计算。本题中的正确答案为3722。

by Xin LI at February 12, 2015 01:01 AM

February 09, 2015

@shell909090

p2p vpn的部署方法

p2p vpn的基本概念 p2p vpn这个概念的提出,是因为openvpn在数 … 继续阅读

by shell909090 at February 09, 2015 03:06 AM

February 06, 2015

@khsing

重新使用Trello

知道Trello这个服务真是时间不短了,但是一直没有怎么用这个东西,最近的事情多到脑子里装不下了,自己的OmniFocus只能给自己看,协同的事情还真是不太好做,所以呢这个Trello就重新用起来了。

他的官方有一个板子叫trello resources,翻了一下确实有不少东西。

比如,在User case里有一些有趣的用法

by Guixing at February 06, 2015 05:48 PM

February 04, 2015

@shell909090

openvpn的几种基本模式

vpn的原始模式 vpn的最简模型,相当于在两台机器上插一块虚拟网卡,然后中间连 … 继续阅读

by shell909090 at February 04, 2015 07:07 AM

February 02, 2015

@shell909090

vpn不要走tcp协议

和大家唠叨一件小事。 vpn不要走tcp协议。 我原本以为这是个常识。因为当网络 … 继续阅读

by shell909090 at February 02, 2015 03:43 AM

January 30, 2015

@delphij

India NIC签发未经授权的 Google SSL证书事件

详情参见 Google Online Security Blog

说两个我认为比较有意思的事情:

第一个是 Google 并没有公布作为证据的证书。由于证书是以 CA 的私钥签署,因此这类未经授权的证书本身就可以作为证据。但是,Google这样做(不公布证书)意味着签发者不得不销毁全部签发的证书,而不仅仅是被公布的那些。

第二个是 Google 在 Chrome 中限制,而不是直接删除或禁止了负有责任的根CA: India CCA 的许可范围。我认为这是远比禁止使用或删除根CA更好的做法(同样的原则也适用于几年前 Mozilla 基金会决定接纳 CNNIC 证书),原因如下:

  1. 在攻击者使用未经授权证书的同时,他们也将自己的身份(持有私钥)暴露在了阳光下,从而使检测和指证变得容易
  2. 加密通讯要比不加密好。鼓励所有人加密通讯,有助于提高攻击所需的代价。
  3. 限制使用范围削弱了CA的权力,阻止了恶意CA对用户的影响,同时对正常证书持有者的影响又不大,降低他们的迁移成本。

by Xin LI at January 30, 2015 04:24 PM

January 27, 2015

@shell909090

Charlie and Dave

公司希望弄一套双授权的安全系统,老大提供了一套算法,求大家review。如果这个 … 继续阅读

by shell909090 at January 27, 2015 02:19 PM

January 05, 2015

@shell909090

无题

路过南京,突然想起前几年在狮子桥吃的鸭血粉丝汤。什么味道其实已经忘了,只是在干完 … 继续阅读

by shell909090 at January 05, 2015 07:46 AM

December 24, 2014

@shell909090

北海道之行的感想

礼貌的老奶奶 这次去日本,让我最受震动的是一位老奶奶。 大家知道我们的日语很差。 … 继续阅读

by shell909090 at December 24, 2014 09:23 AM

December 19, 2014

@delphij

三星滚筒洗衣机门锁的更换

将近三年前搬家的时候买了一台三星 WF350ANW/XAA 洗衣机,结果上周发现门合不上了。上网找到了 这个视频,发现更换并不麻烦,打电话给三星,对方说已经过保,于是决定自己动手修理一下。

首先是断开电源和水源。

拆解比较简单:首先用尖嘴钳从洗衣机下部胶皮中将弹簧拽出(这是一个细金属丝+弹簧构成的圈,用来箍住橡胶皮隔水圈),然后小心将橡胶隔水圈拆开。接下来把门锁的螺丝拧掉,然后把它取出(有连接线)。

首先将外面的塑料外壳卸下(有两个比较重要的塑料卡隼)。接下来将连接的线断开。

拆下来以后,发现最下面的螺丝所在的位置的塑料裂开了,同时在这个地方发生了比较严重的开裂。

由于是受力的地方,而采用的材料是较为廉价的塑料,因此可以预见这个部件在未来还是会发生问题。

安装过程基本是拆解过程反过来,其中比较费力的部分是将金属圈装回的部分,基本上要把圈上到3/5左右,剩下的部分用 iFixIt 套件中的 Spudger 在两侧同时用力来装上。

by Xin LI at December 19, 2014 05:50 AM

December 17, 2014

@delphij

The TIDE

The tide recedes, but leaves behind bright seashells on the sand.

The sun goes down, but gentle warmth still lingers on the land.

The music stops, yet echoes on in sweet, soulful refrains.

For every joy that passes, something beautiful remains.

-- Hardin Marshall via

by Xin LI at December 17, 2014 06:50 PM

December 16, 2014

@shell909090

北海道旅游——札幌附近地区攻略

札幌 白色恋人巧克力工坊 在宫の沢站,从大通坐东西线,340就可达。 工坊庭院非 … 继续阅读

by shell909090 at December 16, 2014 03:52 AM

December 08, 2014

@khsing

在OS X里不同域名用不同的域名解析器

由于公司内网的特殊原因,github.com以及pypi.python.org甚至gmail.com和google.com等网站被IT给劫持到了一个代理上去,本来是好事帮助大家翻墙了,但是这是实现我就不吐槽了。

带来的问题是这些网站都会有https的访问,尤其是以下客户端和命令行,证书是内网下发的假证书(听到这里,是不是很熟悉呢,没错这就是man-in-the-middle attack,#此处可以有呵呵

曾经反应过这样的问题总是不能奏效,只能自己动手了,Mac下可以这么搞

/etc/resolver/目录下放上域名为名的文件,比如/etc/resolver/python.org内容如下

nameserver 8.8.8.8
nameserver 8.8.4.4

by Guixing at December 08, 2014 09:37 AM

December 01, 2014

@khsing

命令行下的代理设置

为了科学上网,访问github之类的快一些,总要在命令行工具下用代理,于是就有了如下设定

# Setup commandline proxy
_proxy="http://127.0.0.1:16888"
_noproxy="localhost,.sina.com.cn,.weibo.com"
alias proxyon="export http_proxy=${_proxy} https_proxy=${_proxy} no_proxy=${_noproxy}"
alias proxyoff="unset http_proxy https_proxy no_proxy"

这个no_proxy是为了让本地内网的repo不要走代理.sina.com.cn代表了该域名下的内容都不走代理。

sudoers里写上环境变量的保持,

Defaults    env_keep += "http_proxy https_proxy no_proxy"

by Guixing at December 01, 2014 12:55 PM

November 29, 2014

@khsing

启用Akismet

趁着收拾blog系统的时候,升级到了MovableType 6,同时也好好处理了一下之前的comments,发现即便是在启用验证码的情况下,依旧有不少Spam。

于是就启用了Akismet,不过我是下载回来之后些许改动,都放在了github/mt-plugin-akismet.

安装很简单,

  1. 建立一个软链接到mt-plugin-akismet/plugins/akismet
  2. 进入 System Overview -> Tools -> Plugins -> MT-Akismet -> Settings
  3. 在API Key的位置上写上在http://akismet.com申请的API Key就好了。

自己试一下,看看Activelog有没有报错,如果没有点进新的Comments应该可以看到如下界面

另外也可以在akismet站上看得到统计信息。

by Guixing at November 29, 2014 05:00 PM

干干净净重装Mac OS X 10.10

重装Mac OS X 10.10

最近很是悲催,家里虽然添置了新的NAS,但是在导数据的时候移动硬盘挂了,这个硬盘了有一部分数据是没有备份的,这是最糟心的了。真是应了墨菲定律,也真是应了那句话"备份不做,日子甭过。"

俗话说的好"祸不单行",就在那个硬盘挂掉的时候我也发现了我的 Macbook Pro 的硬盘分区很不对劲,用Disk Utility并不能修复,即使使用CMD+R启动到Recovery Mode依然不行,HFS+不是一般的渣啊。备份数据,重装系统。

这次要来一个全新的安装,硬盘还要格式化。

  1. 制作一个USB安装盘, 具体参考How to Make an OS X Yosemite Boot Installer USB Drive, 简概之 $ sudo /Applications/Install\ OS\ X\ Yosemite.app/Contents/Resources/createinstallmedia --volume /Volumes/Untitled --applicationpath /Applications/Install\ OS\ X\ Yosemite.app --nointeraction

  2. 用这个U盘启动

  3. 重置硬盘,打开Terminal.app, 执行 $ diskutil eraseDisk JHFS+ OSX disk0

  4. 重置结束之后,检查磁盘应该如下

    $ diskutil list disk0 /dev/disk0 #: TYPE NAME SIZE IDENTIFIER 0: GUIDpartitionscheme *251.0 GB disk0 1: EFI EFI 209.7 MB disk0s1 2: AppleCoreStorage 250.1 GB disk0s2 3: AppleBoot Recovery HD 650.0 MB disk0s3

  5. 退出之后重新安装整个系统。

经验教训还是,经常备份,尤其是重要的数据,电影音乐之类的东西都还好说,最重要的就是拍摄的照片和视频了。

by Guixing at November 29, 2014 03:29 PM

November 20, 2014

@shell909090

上下文切换技术

上下文切换技术 简述 在进一步之前,让我们先回顾一下各种上下文切换技术。 不过首 … 继续阅读

by shell909090 at November 20, 2014 02:38 AM

November 19, 2014

@khsing

手机和桌面的数据分享

苹果的订单发货了,给邮箱里来了一个链接,点开了就是跳转到EMS相应的快递追踪上去了。我习惯这个东西在手机上用「快递100」来管理,问题来了,怎么把这个快递单号扔给手机。之前的方法是放到evernote、Notes之类的云笔记本里,然后拷贝过来。

今天我尝试了一下用Chrome插件直接生成一个QR Code用快递100的App扫描一下就好了。

by Guixing at November 19, 2014 10:20 AM

November 18, 2014

@shell909090

上下文切换测试总结报告

效率测试 测试环境 Intel(R) Pentium(R) CPU G2030 … 继续阅读

by shell909090 at November 18, 2014 08:15 AM

November 12, 2014

@khsing

家庭无线打印搞定

最近给家里添了几个物件,基本实现了在家的无线打印需求。

关于佳能CP910,使用的感觉很不错,属于是热升华技术,相纸的成本比较高,但是家庭使用,也不是大批量打印,成本忽略了吧,打印出照片的喜悦完全淹没了成本问题,而且在TB还可以买到日本代购的相纸,相对稍便宜些。所以家里还缺了一个东西就是照片墙。

拿910配合来打印很方便,需要注意的就是它的dpi是300,在通过Aperture之类的打印的时候一定要选好了DPI,否则默认可是按72dpi打印的,那就糟烂透了。

Airport Express有点问题了,本想拿它作Wifi Repeater,但是这货只能和水果的东西做Repeater,一下子就变成了只和HP 1020打印机配合的AirPrint服务器了,功能减半啊,有点亏,现在开始考虑要不要给家里添一个水果的高端路由器(麻痹啊,苹果毁一生啊

其实CP910就是因为Ricoh GR买的,很不错的相机,成像很好,28mm定焦,有乐趣。不过我拍的比较差。

by Guixing at November 12, 2014 04:03 AM

November 07, 2014

@shell909090

手机上app的权限对比和分析

简述 今天看到这篇文章,勾起了我的好奇。我的手机里有多少app有安全隐患呢?当然 … 继续阅读

by shell909090 at November 07, 2014 08:16 AM

November 06, 2014

@shell909090

October 31, 2014

@shell909090

context切换测试——线程创建有关部分请求review

线程模式开销 使用t_thread程序,循环1M次,重复6次,原始数据如下: 9 … 继续阅读

by shell909090 at October 31, 2014 06:49 AM

October 30, 2014

@shell909090

context切换测试——调用开销有关部分请求review

函数调用开销 使用s_call来测试性能,循环1G次。 2.35,0.00,17 … 继续阅读

by shell909090 at October 30, 2014 08:10 AM

October 29, 2014

@shell909090

context切换测试——python有关部分请求review

python yield模式性能测试 python下的测试就不用time了,我们 … 继续阅读

by shell909090 at October 29, 2014 02:30 AM

October 28, 2014

@shell909090