<?xml version="1.0"?>
<rss version="2.0">

<channel>
	<title>Planet of Woodpecker.org.cn for CPUG</title>
	<link>default</link>
	<language>en</language>
	<description>Planet of Woodpecker.org.cn for CPUG - default</description>

<item>
	<title>@xupeng: MySQL 的临时目录</title>
	<guid>http://blog.xupeng.me/2012/02/04/how-mysql-uses-tmpdir</guid>
	<link>http://blog.xupeng.me/2012/02/04/how-mysql-uses-tmpdir/</link>
	<description>&lt;p&gt;MySQL 服务器设置的 binlog 单文件最大为 1GB，偶然发现会有十几 GB 大小的 binlog 文件，从产生的时间上看像是某个 cron job 使用了超大的 transaction，为了找出“罪魁祸首”，我需要分析一下 binlog。&lt;/p&gt;

&lt;!-- more --&gt;


&lt;p&gt;在使用 mysqlbinlog 将 binary log 转换为文本文件时，发现根分区很快就被塞满了，使用 lsof 发现 mysqlbinlog 在往 /tmp 下写临时文件：&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&quot;line-number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;6&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;7&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;8&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;9&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;code class=&quot;&quot;&gt;&lt;span class=&quot;line&quot;&gt;# lsof -p 17423
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;COMMAND     PID USER   FD   TYPE DEVICE    SIZE/OFF      NODE NAME
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;mysqlbinl 17423 root    1w   REG   0,19   791765366   3186036 /mfs/user/xupeng/tmp/bigbinlogs/bigbinlog.sql
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;mysqlbinl 17423 root    2u   CHR  136,7         0t0        10 /dev/pts/7
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;mysqlbinl 17423 root    3r   REG   0,19 13863171331   3172073 /mfs/user/xupeng/tmp/bigbinlogs/log.000323
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;mysqlbinl 17423 root    4u   REG    8,1   612122624 135332782 /tmp/tmp.rWTNda (deleted)
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;mysqlbinl 17423 root    5u   REG    8,1     2490368 135332784 /tmp/tmp.spKjTA (deleted)
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;…&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;


&lt;p&gt;看 mysqlbinlog 的 Man page，发现并没有参数可以指定临时目录，翻了一下 mysqlbinlog (client/mysqlbinlog.cc) 的代码，看到了下面的代码：&lt;/p&gt;

 &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&quot;line-number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;6&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;7&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;8&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;code class=&quot;c&quot;&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;n&quot;&gt;MY_TMPDIR&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmpdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;n&quot;&gt;tmpdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dirname_for_local_load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;init_tmpdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tmpdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;      &lt;span class=&quot;n&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;n&quot;&gt;dirname_for_local_load&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_strdup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_tmpdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tmpdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MY_WME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;init_tmpdir&lt;/code&gt; 定义在 &lt;code&gt;mysys/mf_tempdir.c&lt;/code&gt; 中：&lt;/p&gt;

 &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&quot;line-number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;6&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;7&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;8&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;9&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;10&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;11&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;12&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;13&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;14&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;15&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;16&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;17&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;18&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;19&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;20&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;21&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;22&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;23&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;24&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;code class=&quot;c&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;n&quot;&gt;my_bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;init_tmpdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MY_TMPDIR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tmpdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pathlist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;copy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FN_REFLEN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;n&quot;&gt;DBUG_ENTER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;init_tmpdir&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;n&quot;&gt;DBUG_PRINT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;enter&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;pathlist: %s&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pathlist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pathlist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;NULL&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;n&quot;&gt;pthread_mutex_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tmpdir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mutex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MY_MUTEX_INIT_FAST&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_init_dynamic_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tmpdir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;full_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pathlist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pathlist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;cm&quot;&gt;/* Get default temporary directory */&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;n&quot;&gt;pathlist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;TMPDIR&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;  &lt;span class=&quot;cm&quot;&gt;/* Use this if possible */&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#if defined( __WIN__) || defined(__NETWARE__)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pathlist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;      &lt;span class=&quot;n&quot;&gt;pathlist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;TEMP&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pathlist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;      &lt;span class=&quot;n&quot;&gt;pathlist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;TMP&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;cp&quot;&gt;#endif&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pathlist&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pathlist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;      &lt;span class=&quot;n&quot;&gt;pathlist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;P_tmpdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;


&lt;p&gt;可以看到，在没有指定 pathlist 时，会使用 &lt;code&gt;TMPDIR&lt;/code&gt; 这个环境变量指定的目录作为临时目录，如果 &lt;code&gt;TMPDIR&lt;/code&gt; 这个环境变量也不存在，在 Windows 下会接着查找 &lt;code&gt;TEMP&lt;/code&gt; 和 &lt;code&gt;TMP&lt;/code&gt; 这两个环境变量，从环境变量查找临时目录失败，会使用 &lt;code&gt;P_tmpdir&lt;/code&gt; 作为默认临时目录，在 Linux 上 &lt;code&gt;P_tmpdir&lt;/code&gt; 是 &lt;code&gt;/tmp&lt;/code&gt; (定义在 stdio.h 中）。&lt;/p&gt;

&lt;p&gt;所以在运行 mysqlbinlog 之前设置 &lt;code&gt;TMPDIR&lt;/code&gt; 这个环境变量就好了。&lt;/p&gt;

&lt;p&gt;MySQL server 和 客户端工具都使用这个临时目录查找策略，怪不得使用 &lt;code&gt;mysqlbinlog tmp directory&lt;/code&gt; 作为关键词没有搜到需要的结果，而使用 &lt;code&gt;mysql tmp directory&lt;/code&gt; 作为关键词，第一条搜索结果就是 &lt;a href=&quot;http://dev.mysql.com/doc/refman/5.0/en/temporary-files.html&quot;&gt;Where MySQL Stores Temporary Files&lt;/a&gt;，选择正确的关键词很重要啊。&lt;/p&gt;</description>
	<pubDate>Fri, 03 Feb 2012 23:18:00 +0000</pubDate>
</item>
<item>
	<title>@delphij: unbound之DNSSEC缓存服务器作弊条</title>
	<guid>tag:blog.delphij.net,2011://2.2139</guid>
	<link>https://blog.delphij.net/2011/11/unbounddnssec.html</link>
	<description>&lt;p&gt;DNSSEC 是一种验证域名信息真实性的协议扩展。个人之前一直觉得这事相当的蛋疼：DNS协议本身是不安全的，而DNSSEC无非是增加了数字签名验证，而这验证还依赖于相当复杂的密钥更新和分发机制，这一切都给它的推广带来了困难。&lt;/p&gt;

&lt;p&gt;最近闲着没事把几台自己的机器上的 &lt;a href=&quot;http://unbound.net/&quot;&gt;unbound&lt;/a&gt; 配置了 DNSSEC 支持。 unbound 是一款 NLnet Labs 开发和维护的 DNS 缓存（解析）服务器实现，它内建了对 DNSSEC 的验证支持。与比较常用的 BIND 相比， unbound 性能更好，并且在设计时充分考虑了安全问题，在安全方面有很好的记录。&lt;/p&gt;

&lt;p&gt;在 FreeBSD 上可以使用 port 来安装 unbound：&lt;/p&gt;

&lt;pre&gt;
# cd /usr/ports/dns/unbound
# make install
&lt;/pre&gt;

&lt;p&gt;在 /etc/rc.conf.local 中启用 unbound：&lt;/p&gt;

&lt;pre&gt;
# echo 'unbound_enable=&quot;YES&quot;' &gt;&gt; /etc/rc.conf.local
&lt;/pre&gt;

&lt;p&gt;配置 unbound，如果需要对外提供服务，在 /usr/local/etc/unbound/unbound.conf 中的 server 小节添加：&lt;/p&gt;

&lt;pre&gt;
	interface: 0.0.0.0	# 监听所有IPv4地址
	interface: ::0		# 监听所有IPv6地址
&lt;/pre&gt;

&lt;p&gt;当然，对于对内网服务的机器来说，应单独指定内网的 IP 地址而不是监听全部可用 IP 地址，以避免暴露攻击面。此时还应配置 outgoing-interface，具体请参见配置文件中的说明。&lt;/p&gt;

&lt;p&gt;然后是获得 trust anchor，这和根证书的意思类似。unbound-anchor 可以创建和更新 trust anchor。用下面的命令来下载和立即检查trust anchor的完整性，这个检查是使用 unbound-anchor 内建的 ICANN 证书进行的，如果不确认的话，还应检查它的完整性，包括 unbound-anchor -l 和检验源代码，不过由于 FreeBSD 的 portsnap 系统采用了数字签名验证，并对每个源码包都做 SHA256 校验，因此一般来说可以认为没有问题。&lt;/p&gt;

&lt;pre&gt;
# sudo -u unbound unbound-anchor
# sudo -u unbound unbound-anchor -a &quot;/usr/local/etc/unbound/root.key&quot; || echo &quot;Wrong key!&quot;
&lt;/pre&gt;

&lt;p&gt;如果一切正常，则系统不会给出任何提示。&lt;/p&gt;

&lt;p&gt;配置 unbound 使用 DNSSEC 验证只需在 server 小节增加一行：&lt;/p&gt;

&lt;pre&gt;
	auto-trust-anchor-file: &quot;/usr/local/etc/unbound/root.key&quot;
&lt;/pre&gt;

&lt;p&gt;然后重启 unbound 即可。用 dig com. SOA +dnssec 应该可以看到 DNSSEC 验证成功（flags: ad）：&lt;/p&gt;

&lt;pre&gt;
% dig com. SOA +dnssec 

; &lt;pre&gt;&gt; DiG 9.8.1-P1 &lt;pre&gt;&gt; com. SOA +dnssec
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER- opcode: QUERY, status: NOERROR, id: 4552
;; flags: qr rd ra &lt;b&gt;ad&lt;/b&gt;; QUERY: 1, ANSWER: 2, AUTHORITY: 14, ADDITIONAL: 1
(...)
&lt;/pre&gt;

&lt;p&gt;此外也可以用浏览器访问 &lt;a href=&quot;http://dnssectest.sidn.nl/&quot;&gt;http://dnssectest.sidn.nl/&lt;/a&gt; 来测试。&lt;/p&gt;

&lt;p&gt;目前美国联邦政府的许多网站都已经启用了 DNSSEC，但在大家的缓存服务器以及更多的商业站点支持 DNSSEC 之前，这样做并不能显著改善安全性。&lt;/p&gt;&lt;/pre&gt;&lt;/pre&gt;</description>
	<pubDate>Fri, 03 Feb 2012 18:35:17 +0000</pubDate>
</item>
<item>
	<title>@delphij: 湾区买房记(1)</title>
	<guid>tag:blog.delphij.net,2012://2.2151</guid>
	<link>https://blog.delphij.net/2012/02/1-3.html</link>
	<description>&lt;p&gt;在次贷危机导致房产泡沫破裂之后，美国这几年一直处于经济衰退中。这次金融海啸影响的范围相当深远，许多地方的房价被直接腰斩到一半左右的水平，并且银行业不再敢于放贷给中小企业和个人。为了刺激经济，联储局（相当于美国的中央银行）采取了多轮&quot;量化宽松&quot;政策，通过直接以虚拟的货币购入债券来压低利率。&lt;/p&gt;

&lt;p&gt;个人一直认为房地产不是一个好的投资，因为它的流动性很差，并且杠杆率很高，例如，在需要用钱的时候有可能必须以非常亏的价格来一次性出售（与此相反，证券如股票等，可以以&quot;sell-to-cover&quot;这样的方式去交易）；另一方面，美国的房产需要根据其价值向地方政府缴纳物业税，这在每年都会是一笔不小的开支，此外，屋主需要对房屋进行各种修缮，而租房则不需要操心这些问题。&lt;/p&gt;

&lt;p&gt;不过，从另外的角度看，房地产又是很好的投资方式。首先，如果一个地区的人口在持续增加，由于地皮不会增多，这个地方的房地产价格便会不断增加；其次，美国税法规定，物业税、向银行支付的利息等可以部分或全部冲销收入，因而节省的这部分税金会变成个人的产权；还有就是，在预期会发生通货膨胀的情况下，投资或负债是要好过持有现金的。&lt;/p&gt;

&lt;p&gt;在这个背景下，到了2010年9月左右的时候，我开始考虑是不是要买房的问题。经过长时间的准备、看房、下单，最后在2012年1月底买到了位于 San Jose 的 Evergreen 地区的一栋 Single Family House。这里总结一下经验教训，供其他有类似情况的同学参考，也给自己留下一个记录。&lt;/p&gt;
        &lt;p&gt;一、购房前的准备&lt;/p&gt;

&lt;p&gt;对个人而言，买房是一项巨大的投资，因为需要支付房价相当比例的首付款（通常在 10% 到 40% 不等）。为了减少未来需要支付的利息，往往会希望尽可能多支付首付款，一般来说，今天多付一美元，几十年后便可以节省至少两美元的利息。对于完全或大部分需要靠自己来支付首付款的买家来说，这是相当沉重的经济负担。&lt;/p&gt;

&lt;p&gt;所以，在考虑购房之前，首先需要做的事情便是存款。根据税法，延后付税的退休金账户（传统IRA、401(k)等）并不能用于现在的个人用途，所以退休金账户中的钱是不能用于购买自住房屋的。在美国购房，通常会希望贷款额不超过个人税前3-5年的收入总和，假如以贷款额为4年税前收入，5倍杠杆（首付为20%）的话，至少要存够一年的税前收入才可以考虑买房，当然，这个存款可以是传统的支票、储蓄账户，也可以是证券或其他投资。由于证券价值在银行看来只能以 75% 的价格来做抵押，因此在购房前应适当将其转换为现金。&lt;/p&gt;

&lt;p&gt;还有就是积攒信用记录。美国以社会保障编号 SSN 为索引的信用记录由三家信用评级公司来根据个人过去的还款情况给出信用分数，这个分数决定了一个人能够拿到的最低贷款利率（信用分数越高越好）。想要提高信用分数，比较快的方法是开少量提供较高信用额度的信用卡，并确保每月以比较稳定的模式消费，将花费控制在信用额度总和的10%以内。在申请贷款之前，应有一年左右没有申请新的信用卡或其他贷款的稳定的消费记录，争取拿到 720 分以上的信用分数（华人的还款和消费习惯，只要没有欠债不还的记录，通常在几年之内就可以做到）。&lt;/p&gt;

&lt;p&gt;有了存款和良好的信用记录之后，就可以去银行申请贷款预授权证明（Pre-approval letter）了。这个预授权证明可以向卖家说明几件事：第一、银行愿意借给买房者这么多钱，换言之不太可能因为贷不到款而导致交易失败；第二、买房者确实有认真的购买意愿。遇到有很多人提交购买意向（叫做multiple-offer）的情况，拿着证明信可以在一定程度上提高卖家接受购买意向的可能性，不过，如果其他竞争者提出更好的条件，例如提出更高价格，并且按现金支付全款等，卖家还是会选择其他买家。&lt;/p&gt;

&lt;p&gt;此外，和在美国买任何东西一样，事先要多做功课，了解购买房屋时可能遇到的问题。&lt;/p&gt;

&lt;p&gt;二、购房的基本交易流程&lt;/p&gt;

&lt;p&gt;在卖家看来，卖房也是具有相当风险的一件事。卖家需要支付房产经纪大约房款的大约6%作为提成，通常需要支付产权保险的费用，以及买家提出需要进行的修缮费用（这个是双方谈判的内容），等等。&lt;/p&gt;

&lt;p&gt;一旦买卖双方就购房意向达成一致，就需要有一个机制来确保双方不再反悔。个人理解，这个过程主要是保护买家的利益。进入购买合同（通常在交易过程中，卖家会要求买家付3%房款的定金，而为了防止卖家拿了这个钱卷款潜逃，通常会引入一个叫代管账户 Escrow 的公司来保管这些钱，因此，这个过程也叫做进入 Escrow）之后，卖家便不能单方面决定引入新的买家，而由于这个过程中卖家需要冒流动性风险，因此买家通常也需要同意，如果反悔的话，卖家可以扣留这笔定金的部分或全部金额。&lt;/p&gt;

&lt;p&gt;买家为了保护自己的权益，可以在购买意向中指明一些意外条款 (称作 contingency)。常见的意外条款包括贷款意外（通常是无法贷到低于某个利率的贷款时，或贷不到贷款时使用）和房屋检查意外（通常是在房屋检查时发现重大问题时使用）。假如发生了意外条款规定的情况，买家可以退出合同并拿回定金。这些意外条款需要在一定时间内撤销，如果双方同意，还可以延长有效期。在进入 Escrow 之后，买家需要雇人来检查房子的基本状况（Home Inspection），空调和供热系统 (HVAC Inspection)、烟囱检查(对于有壁炉的房屋, Chimney Inspection)和白蚁检查(通常是作为 termite 修理的前期准备工作，多数白蚁公司会免费做这个检查)，等等。这些检查是可选的，并且买家即使最后决定不买房子，也需要支付相关的费用。有些卖家会事先做一系列报告出来，但个人认为还是有必要自己雇人去做一遍检查的，一方面是图个安心（多数检查会包含一年左右的保险费用，如果事后发现没有检查到的问题，保险公司会支付修理费用），另一方面，在检查过程中，这些专业人士会给买房者讲解一些房屋维护的常识等等。&lt;/p&gt;

&lt;p&gt;做完房屋检查之后，买家可以撤掉检查意外条款，也可以在撤掉之前拿着检查结果和卖家继续讨价还价。&lt;/p&gt;

&lt;p&gt;与此同时，在银行方面也需要做相当多的工作。银行会雇一个估价师来对房屋进行估价，估价师会对房屋的状况进行评估，并根据近期房屋交易的情况给出一个估价，假如这个估价比买家的出价低，则买家可以拿着这个结果去和对方砍价，或提高首付额来令贷款通过；假如这个估价比买家的出价高（在湾区这种情况并不常见），那就偷着乐吧，不过，估价师最终还是要把他的估价拉回到买家出价附近的。&lt;/p&gt;

&lt;p&gt;拿到估价之后，银行会批准贷款，这时买家应撤掉贷款意外条款，至此，合同就箭在弦上了。买家需要去产权保险公司（也就是做 Escrow 的公司）签署大约120页的协议来完成交易。签署完各类协议之后（总共需要1-2个小时才能做完），买家向 Escrow 支付剩余的首付款，银行将贷款汇入 Escrow，并最终完成交易。&lt;/p&gt;

&lt;p&gt;三、相关人员&lt;/p&gt;

&lt;p&gt;买家 Buyer 卖家 Seller 这个没什么可说的。&lt;/p&gt;

&lt;p&gt;卖家房产经纪 Seller (Listing Agent) 是卖家雇用的房产经纪。&lt;/p&gt;

&lt;p&gt;买家房产经纪 Buyer Agent 是买家雇用的房产经纪，注意，虽然买家房产经纪名义上是买家雇用的，但是他们的利益通常是尽快让交易完成（这样他们可以拿到佣金），而且最终他们拿到的佣金也是和卖家房产经纪来分，所以他们的利益与买家并不一致。一直解决方法是按小时去付他们工资，而不让他们拿佣金，但是这么做的人很少。&lt;/p&gt;

&lt;p&gt;双面房产经纪：如果愿意，可以让卖家房产经纪同时作为买家房产经纪，这样可以省掉一些佣金，但也会有房产经纪和卖家串谋之虞，所以如果自己没有做足够多的功课和经验的话，最好不要考虑。&lt;/p&gt;

&lt;p&gt;所有的房产经纪人都应该有房产经纪执照。&lt;/p&gt;

&lt;p&gt;贷款经纪 Mortgage Broker 是买家雇用的申请贷款的专业人员。贷款经纪不会直接向买家索要相关费用，通常他们自己是银行的经理人，并从银行拿到提成。&lt;/p&gt;

&lt;p&gt;若干房屋检查、维修人员。&lt;/p&gt;

&lt;p&gt;未完待续。&lt;/p&gt;</description>
	<pubDate>Fri, 03 Feb 2012 08:43:26 +0000</pubDate>
</item>
<item>
	<title>@delphij: 再见，山景城</title>
	<guid>tag:blog.delphij.net,2012://2.2150</guid>
	<link>https://blog.delphij.net/2012/01/post-613.html</link>
	<description>&lt;p&gt;来美国快5年了，这5年中一直住在旧金山湾区的 Mountain View （中文通常译为山景城）。今天终于到了离开的时候，虽然以后还是会经常来这里，不过不会再有那么多的机会了吧。&lt;/p&gt;

&lt;p&gt;Mountain View 是湾区的一个新兴城市，由于距离 旧金山国际机场 (SFO) 和 圣何塞国际机场 (SJC) 距离都比较适中，同时拥有连接穿过东湾的州际 I-880 高速公路的州 CA-237 高速公路，以及连接 Cupertino - San Jose 的西硅谷高速公路 CA-85，并且连接美国西海岸的 US-101 也穿过这里，因此硅谷的许多高科技企业都在这里设立分公司或总部。其中比较著名的有 Google、 Microsoft、 Symantec、Intuit 等。此外，这里也是 Intel、Netscape、SGI 等许多重要的硅谷企业的诞生地。&lt;/p&gt;

&lt;p&gt;Mountain View 的地标性建筑是位于 Moffet Field 的 NASA Ames 研究中心，以及在 Google 附近的 Shoreline 露天剧场。此外， Mountain View 也是附近治安较好的城市之一。&lt;/p&gt;</description>
	<pubDate>Thu, 02 Feb 2012 09:15:59 +0000</pubDate>
</item>
<item>
	<title>@shell909090: 教育的思考</title>
	<guid permalink="False">http://shell909090.com/blog/?p=2080</guid>
	<link>http://shell909090.com/blog/2012/02/%e6%95%99%e8%82%b2%e7%9a%84%e6%80%9d%e8%80%83/</link>
	<description>&lt;p&gt;    首先说明一点，这是贝壳自己对自己受到教育的反思。由于本人不从事教育行业，所以结论可能和现有的理论相悖离，也不保证正确。
&lt;div&gt;    教育最重要的时刻，不是在高中，而是在幼儿园。幼儿园的老师不应当教知识，而是应当教常识。常识是非常重要的，我们有意无意，善意或恶意，都会给小孩子灌输扭曲的常识，例如孩子问你他是哪里来的，你说是从垃圾桶中捡来的。等孩子成长了，他的第一件事就是推翻不正确的常识。还记得那个笑话么？——我知道你的父母和老师都对你这么说，但是，圣诞老人是不存在的。是的，超人也不存在。哦，不不，驯鹿和美国总统是存在的。&lt;/div&gt;
&lt;div&gt;    孩子听到越多不正确的常识，就需要浪费越久的时间逃脱常识的束缚。大部分孩子甚至终身会带着一些偏见——例如以前的“地球是宇宙的核心”，到不久前的“空间是连续的”。从有意的“抢到的东西就是自己的”，到无意的“大人说谎也不受惩罚”。越多错误的束缚，孩子需要浪费越多的时间逃离束缚，将来的成就就越小，这就是为什么我觉得幼儿园是一个孩子成长的关键的原因。&lt;/div&gt;
&lt;div&gt;    至于第二语言，真的没有必要在幼儿园就开始学起，我甚至觉得语言不应当被独立教授。还记得你的打字是怎么练成的么？我打赌我的读者中，有一半以上不是在正规的课堂中，按照老师的指示一点一点去练习每个键位，最后成为打字高手的。我自己是在QQ起步的时候，在网络上和别人聊天。从开始的一对一还是被人家嫌慢，到最后可以很轻松的一对二甚至一对多，大概只花了我半年多的时间。同样，要在课堂上学习语言，比不上在语言的环境中学习，这个大多数人都知道。但是什么是语言的环境？这不是说找个外教，或者用英语授课就解决的。孩子使用语言的关键，在于和同龄人组织学校社会的时候。如果他们圈子里面用英文，你的孩子只有三种可能，1.不和同龄人交往，变成书呆子，2.根本不去上课，退学了，3.英文熟的你根本听不懂。问题是，在中国如何控制学校中的学生交际圈呢？所以从这个意义上说，在中国要稳定的学好英文，而且和老外差不多，是不现实的。只能靠你孩子的天赋和运气。&lt;/div&gt;
&lt;div&gt;    很多人把孩子送到了国外，实话说，这是一个不负责任的选项。孩子可以没有很强的英语能力，但是在成长中，脱离家庭的关心是致命的。除非你送到国外后，在当地有其他人可以替代你关心孩子，否则将来成长的结果只能靠运气。有很多人，在出国后交往男女朋友（这个很正常），颓废，不用功学习，失去生活目标（这个不应当在初中和高中出现），乃至吸毒（这个也不算太少）。当然，以国内不少家长的情况而言，陪着孩子成长只会导致更严重的问题。&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;    中国的小学和初中教育，是一个学习的过程，这个没问题。但是学的内容太深入，又不够广泛。现在家长都在喊教育内容不要超纲，喊教学速度过快，喊小学上大学内容。但是，什么是纲，为什么要有纲。诚然，学习的问题上，有些时候不到一定年龄，学生是理解不了某些问题的。但是在学习知识上，实际是没有边界的。我们拆掉考试的问题来反观教育，如果真的是为了更好的工作，那么凡是需要的知识都必须要学，可以多不能少，何来超纲？超纲是一个基于考试产生的现象，本质是考试的难度无法增加，就通过增加范围来提高分辨率，强行区分学生。&lt;/p&gt;&lt;/div&gt;
&lt;div&gt;    以初中数学为例，我们初中数学的很大一部分都在教授二次方程特性和解法。实际上呢？二次方程用到的机会非常少。大家也都是从考试中走出来的社会人，你们凭良心告诉我，毕业后有多少机会用到了二次方程？个人觉得这部分教到过概念和解法就可以了，不必对特性深入到奇怪的地步，特意构造一些特例问题来考察学生的解题能力。其实只要在需要的时候，找一下wiki，然后根据问题能解出来就行了。我的高等数学学了很久，现在也差不多都还给了老师。但是需要的时候，我可以通过很短时间的查找资料，把问题现场解出来。反倒是从小学到高中，对一些现代数学的基础学习不足，尤其是线性代数和统计学。高中没有教授现代统计学，因为这依赖于高等数学。线性代数只教了方程组解法和行列式，没有教授矩阵运算。实际上这是现代数学概念的基础，应当在足够的时间内深入学习。&lt;/div&gt;
&lt;div&gt;    至于语文和思政，更是沦为执政党的免费广告课程。这部分课程大部分人在高中开始就吐掉了，吃都吃不下去。&lt;/div&gt;
&lt;div&gt;    高中开始，学校教授的不应当是知识了，而是研究方法。当然，研究方法其实应当从小就开始学习了，包括论文格式，研究过程和方法，预算控制等等。尤其是一些现代科学中基本的精神，都应当在实际的课题报告中做足够的检讨。国人经常在一些莫名其妙的地方出奇奇怪怪的毛病，部分可能就源自没有系统的接受过研究方法论的影响。例如，在研究效果的时候，应当应用双盲法。如果这是一道填空题，我估计大部分国人都能做对。但是实际操作的时候，有很大可能陷入双盲误区中。尤其是单向相关性断定，当有A，就发生B时，就开始断定是A导致了B。又例如中医问题，对于接受过研究方法论的人而言，双盲法检验需要不需要根本不应当是一个问题。要么就拜托你，不要自称中医是科学，这也行。不是每个结论，在科学上都有解释。不管你信不信，反正有人信。这没什么，有人信上帝，有人信科学。但是不要对外声称，我们的上帝经过科学检验。。。&lt;/div&gt;
&lt;div&gt;    至于有些民科，或者一些不知道什么的人，写出来的东西就更神奇了。为什么地球在远处向太阳坠落就会形成旋转，为什么太阳是黑洞在发光。他们写的每个字我都认得，但是连贯起来就完全看不懂说了些什么。老外的神奇论文，是从常识性的结论和公式出发，通过推导，得出一个反常识的结果。然后再验证这个结果，而且居然是对的。例如泊松斑，水星近日点漂移，宇宙膨胀。对于这些东西，我虽然看不懂，但是每个上下文的联系都能看到，只是不明白基础知识，也不知道为什么要如此推导。民科的论文则相反，是从常识性的结论和没有公式出发，跳跃性的得出反常识的结果，然后没有人能够验证。我不但看不懂上下联系，而且连他想说什么都看不明白。当然，最神奇的是这样的东西也有人买。。。&lt;/div&gt;
&lt;div&gt;    至于大学，会在大学学习知识的人是傻子。大学是一个教授研究方法论和寻找人生意义的地方，如果一个学生大学毕业，能够找到自己的人生目标，认识一群好兄弟，就已经很满足了。至于学到的知识，真的和大学无关。如果要说有什么关系的话，最多是借助大学的环境，可以更广泛的接触自己想要接触的东西。当然，后者即使对于毕业的人也不是无法做到，所以去大学绝对不是学知识的。&lt;/div&gt;
&lt;div&gt;    说到这里，国人有个奇怪的现象。大部分人好像都相信知识改变命运，更多的知识就能带来更成功的人生。但是实际操作的时候却都是脑体倒挂，进行脑力劳动的不如进行体力劳动的。程序员赚钱靠什么？加班。书本靠什么赚钱？印刷。&lt;/div&gt;&lt;/p&gt;</description>
	<pubDate>Wed, 01 Feb 2012 19:57:42 +0000</pubDate>
</item>
<item>
	<title>@shell909090: 如何写基于google code的watch file</title>
	<guid permalink="False">http://shell909090.com/blog/?p=2078</guid>
	<link>http://shell909090.com/blog/2012/02/%e5%a6%82%e4%bd%95%e5%86%99%e5%9f%ba%e4%ba%8egoogle-code%e7%9a%84watch-file/</link>
	<description>&lt;p&gt;    google code很好用，可是他的下载页面很恶心，很难跟，而且还改过一次。debian打包党要做watch file的时候，估计会很郁闷。
&lt;div&gt;    去&lt;a href=&quot;http://googlecode.debian.net/&quot; target=&quot;_blank&quot;&gt;http://googlecode.debian.net/&lt;/a&gt;，然后提交你的包名，你会得到一个url（其实自己猜也可以猜到）。每次访问这个url的时候，他会代你解析google code，告诉你有没有更新。&lt;/div&gt;&lt;/p&gt;</description>
	<pubDate>Tue, 31 Jan 2012 20:06:39 +0000</pubDate>
</item>
<item>
	<title>@shell909090: PXE模式使用openwrt网络安装debian</title>
	<guid permalink="False">http://shell909090.com/blog/?p=2076</guid>
	<link>http://shell909090.com/blog/2012/01/pxe%e6%a8%a1%e5%bc%8f%e4%bd%bf%e7%94%a8openwrt%e7%bd%91%e7%bb%9c%e5%ae%89%e8%a3%85debian/</link>
	<description>&lt;p&gt;    废话不说，上干货。
&lt;div&gt;    首先，禁用arptables。当然，如果你没开这个防火墙，那么没必要。其次，注意你的openwrt必须有udisk，否则空间相差太多，根本没有实现的可能。&lt;/div&gt;
&lt;div&gt;    然后，如果你用的是新版的rom，应该在/etc/init.d/dnsmasq里面看到，dnsmasq()这个函数里面有。&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;        append_parm &amp;quot;$cfg&amp;quot; &amp;quot;tftp_root&amp;quot; &amp;quot;&amp;#8211;tftp-root&amp;quot;&lt;/div&gt;
&lt;div&gt;        append_parm &amp;quot;$cfg&amp;quot; &amp;quot;dhcp_boot&amp;quot; &amp;quot;&amp;#8211;dhcp-boot&amp;quot;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;    如果没有，加一下，有的话说明原生支持。下面可以直接修改。&lt;/div&gt;
&lt;div&gt;    dnsmasq是一个dhcp/dns双重服务器，而pxe引导的第一步就是支持bootp协议。这个选项在/etc/config/dhcp里面。config dnsmasq一节上，增加。&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;        option 'dhcp_boot' 'pxelinux.0'&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;    重启dnsmasq，完成bootp准备。&lt;/div&gt;
&lt;div&gt;    然后，安装tftpd-hpa，opkg update，opkg install tftpd-hpa。这是一个tftp服务器，默认不启动。如果你打算让pxe引导模式持久化，那么就改为默认启动，同时永久关闭arp防火墙。在/var/tftpd-hpa里面，可以看到tftpd的根路径。从参考3的的连接里面，你可以找到合适的一个下载路径，下载netboot.tar.gz到这个文件。解压后，可以看到pxelinux.0，这个和上面的pxelinux.0相对应。这是pxelinux的组件，隶属于syslinux项目，可以用来完成启动。&lt;/div&gt;
&lt;div&gt;    这样，就完成了安装的所有准备工作。你可以找一个设备实验一下，应当可以完成网络安装的步骤。&lt;/div&gt;
&lt;div&gt;    另外，如果需要启动选择amd64或者是i386，或者更进一步定制。那么需要下载其他镜像，自己生成pxelinux.cfg这个目录中的内容。&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;1. PXE &lt;a href=&quot;http://wiki.debian.org/PXE&quot; target=&quot;_blank&quot;&gt;http://wiki.debian.org/PXE&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;2. NetbootPXE &lt;a href=&quot;http://wiki.debian.org/DebianInstaller/NetbootPXE&quot; target=&quot;_blank&quot;&gt;http://wiki.debian.org/DebianInstaller/NetbootPXE&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;3. netinst &lt;a href=&quot;http://www.debian.org/distrib/netinst&quot; target=&quot;_blank&quot;&gt;http://www.debian.org/distrib/netinst&lt;/a&gt; &lt;/div&gt;
&lt;div&gt;4. 配置pxe，安装debian和ubuntu &lt;a href=&quot;http://my.unix-center.net/~whtbie/wordpress/?p=290&quot; target=&quot;_blank&quot;&gt;http://my.unix-center.net/~whtbie/wordpress/?p=290&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;&lt;/p&gt;</description>
	<pubDate>Mon, 30 Jan 2012 19:14:14 +0000</pubDate>
</item>
<item>
	<title>@delphij: 水密隔舱与可靠系统设计</title>
	<guid>tag:blog.delphij.net,2012://2.2146</guid>
	<link>https://blog.delphij.net/2012/01/post-610.html</link>
	<description>&lt;p&gt;我国在最晚不晚于宋代发明了水密隔舱。所谓水密隔舱，是指将船体分成若干个互不相通的舱区，这样当一个或几个舱区进水时，整个船体仍然可以有足够的浮力而不致沉没。这是一项相当重要的发明，类似的设计思路在其他领域也有应用。&lt;/p&gt;

&lt;p&gt;在计算系统中，往往也会采取类似的设计思想。例如，操作系统会对进程地址空间的访问提供隔离，这样当一个进程吐核的时候不会影响其他进程的运行。又比如，在设计安全方案时，采用分层、相互隔离的信任状实体，分隔特权服务和非特权服务，把绝大多数的输入处理放在非特权服务中运行。再比如，在设计大容量计算系统时，可以将高优先级的任务单独设计一个队列，并限制所有worker能够容纳的任务总数，在运营时以逐步提高上限的方式来避免出现超载导致大家都无法使用的情况。&lt;/p&gt;

&lt;p&gt;总之，我不认为中国人在宋代就已经想出来的方法，到了21世纪还可以被中国人认为是「非常特别的系统」「应用的场合很少」「中国目前研究这种系统的人不多」的高精尖。这么想的人，是的，你也就配做个末学。&lt;/p&gt;</description>
	<pubDate>Mon, 30 Jan 2012 02:48:26 +0000</pubDate>
</item>
<item>
	<title>@shell909090: tcp连接的建立和释放</title>
	<guid permalink="False">http://shell909090.com/blog/?p=2074</guid>
	<link>http://shell909090.com/blog/2012/01/tcp%e8%bf%9e%e6%8e%a5%e7%9a%84%e5%bb%ba%e7%ab%8b%e5%92%8c%e9%87%8a%e6%94%be/</link>
	<description>&lt;div&gt;    大家新年好，新年第一博，我们来写一点干货。&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;p&gt;    建立tcp为什么是三次握手？
&lt;div&gt;    从两军问题说起太远了，三次握手的假定是一条双工线路的每个方向，要么持续通，要么持续不通。就好比一个电话，你和对方可以同时说话，所以是双工线路。你说了对方能听到，这叫单方向。单方向上，要么通，要么不通。&lt;/div&gt;
&lt;div&gt;    如果从一个不保证稳定的电话线上（例如移动电话，这是典型例子），你怎么确定你们通话是正常的？&lt;/div&gt;
&lt;div&gt;    假如你首先说“喂”，这时候你什么都不知道，对方能听到，他就知道你到他这里的电话是好的。他会说“喂，我听到了”。你听到了，会知道他到你这里的电话是好的。&lt;/div&gt;
&lt;div&gt;    事情结束了么？没有呢，他还不知道你能听到他讲的东西，所以你还要回“我听到了”，然后开始说正事。&lt;/div&gt;
&lt;div&gt;    回想一下自己打电话的经历，是不是往往漏掉了最后一个“我听到了”呢？这样会使得对方无法确认你能听到他说的东西。不过一般来说，当你开始滔滔不绝的时候，他会假定你听到了那句“喂，我听到了”。因为通常没有人会没听到对方的回应就开始说话说个不停。这个模式在tcp中也是可以做到的，在最后一个ack上附加数据。&lt;/div&gt;
&lt;div&gt;    为什么由发起方开始？因为我们必须要假定有一个方向开始，任意开始就需要处理碰撞问题（就是同时开始）。接通socket总是由发起方开始传输第一个包，你不觉得直接在这个包上面开始测试连通会比较合理一些么？&lt;/div&gt;
&lt;div&gt;    电话为什么由被叫方开始说话？因为主叫方打电话后，被叫方决定了电话什么时候接通。电话接通的时候，被叫直接就可以说话了（假如电话稳定的话），而主叫要等到下一个“嘟”不出现才能有所反应。所以通常都是被叫先开口。当然，也有被叫方接起电话来等着主叫说话的情况。&lt;/div&gt;
&lt;div&gt;    另外提一句，如果你使用手机拨打的话，当听到对方“喂，这里是XX，您好”之类的信息的时候，应当先说“喂，我是XX，您好”。等对方确认能听到了，再开口说正事。因为手机有不算太小的几率，双方都听不到，或者单方向听不到。如果不巧是后者，很容易引起不必要的误会和麻烦。例如你滔滔不绝的说，对方作为反应，说了几句。然后你什么都听不到，继续说。对方当然会生气，对不对？&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;    OK，现在我们来说说挂电话。&lt;/div&gt;
&lt;div&gt;    tcp的fin机制，其实是要解决这么一个问题。当你说“再见”后，能够马上把电话放下么？&lt;/div&gt;
&lt;div&gt;    不行的，因为对方可能还有一些重要的事情还没说。你一说再见就挂断，这个会造成问题。从简单的思考上，我们会得出一个结论。当你说了“再见”后，对方可能还需要说一些事情。当对方也说了“再见”后，你就可以挂电话了。&lt;/div&gt;
&lt;div&gt;    可是且慢，对电话而言这个模型成立，我们得稍作修改才符合网络——当你挂下电话机后，对方不会出现忙音。于是，当你说再见，对方说再见，你必须再说一次再见，对方才能确定你听见了再见。而且这次，事情非常符合两军问题——你们永远也无法就什么时候挂机达成一致。这个问题再折衷回来，也是一个三次模型，对方说再见，你说完你要说的话，然后说再见，对方再见，挂机。&lt;/div&gt;
&lt;div&gt;    被动关闭上，这个模型基本是正确的。当你收到“再见”后，把你要说的事情说完，然后再见。这时候不能挂电话，因为你不确认对方听到你的“再见”了。如果你的“再见“对方没收到，那么对方会死等到天荒地老。至于为什么对方可以肯定你收到了他的再见，是因为刚刚你说的那堆废话里，应该已经包含了“我知道你要挂电话了，我会尽快说完”的意思。所以，你需要等对方的“再见”回来。&lt;/div&gt;
&lt;div&gt;    当然，在tcp的实现上说，所有对对方的回应，都在ack里面。所以是FIN FIN-ACK ACK，关闭。最后一个ACK前，叫做LAST ACK状态。如果ACK丢失，会造成被动方挂断有问题，因此这里需要一个超时机制。用电话术语来说，就是最后一个再见没听见，你就要等到天荒地老，因此当对方首次再见完成的时候，你说再见，如果一定的时间等对方的最后一个再见等不到，就别等了，直接挂机。这个时间比等不到对方任何消息而挂机，要来的短。tcp标准设定为两倍最大生存周期，即2MSL。当然，如果等到了最后一个ACK，就直接删除连接数据结构。&lt;/div&gt;
&lt;div&gt;    主动关闭的时候，情况会更加复杂一点。为什么？因为刚刚的超时机制。我们从你说再见之前开始说起，这次你是主动告别一方。&lt;/div&gt;
&lt;div&gt;    你首先说了一个再见，然后进入FIN_WAIT1状态，换成电话术语，就是等对方说再见。tcp机制上，对方的ACK先到，就是FIN_WAIT2。对方的FIN先到，就是CLOSING——这种情况不多见，只在双方同时想挂断的时候发生。如果对方的FIN-ACK一起发送，那就直接保送上TIMED_WAIT。无论是哪种先，最后会收到一个ACK和一个FIN，并且发送一个ACK。换成电话术语，就是你说了再见，对方一定会说知道了和再见，并且你会说知道了。差别在于tcp需要用多个状态来表示哪个事情先，哪个事情后，打电话就不要这么麻烦了。&lt;/div&gt;
&lt;div&gt;    最复杂的事情，在于说了最后一个再见之后。当你说完最后一个再见，就可以直接挂电话么？电话可以，但是作为tcp，却不可以。因为某些情况下，对方的FIN包没有到就会进入TIMED_WAIT状态。另外一些情况下，对方的LAST_ACK等不到你的ACK，会把他的FIN重发一遍。如果直接销毁连接结构，那么最后一个FIN包可能对新的连接造成干扰，而且会阻碍对方关闭连接。所以，作为主动挂断一方，你有一点很不利的是，无论如何，你必须等这个2MSL的时间。这个值在linux中一般是60s，更进一步可以查看&lt;a href=&quot;http://www.faqs.org/rfcs/rfc1337.html&quot; target=&quot;_blank&quot;&gt;rfc1337&lt;/a&gt;。&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;    刚刚解说的最后一个情况，就是很多机器TIME_WAIT很高的原因——因为你的服务器主动关闭了连接。作为本质解决方案，你需要理解为什么会发生这件事情，服务器端关闭连接是否正常。如果正常，那么加一些内存，并且启用tcp_tw_recycle来减缓这个问题。注意，这个参数不应当在NAT后的机器上被启用。具体可以查看&lt;a href=&quot;http://www.ietf.org/rfc/rfc1323.txt&quot; target=&quot;_blank&quot;&gt;rfc1323&lt;/a&gt;。&lt;/div&gt;&lt;/p&gt;</description>
	<pubDate>Sat, 28 Jan 2012 18:03:43 +0000</pubDate>
</item>
<item>
	<title>@shell909090: 龙年新年</title>
	<guid permalink="False">http://shell909090.com/blog/?p=2072</guid>
	<link>http://shell909090.com/blog/2012/01/%e9%be%99%e5%b9%b4%e6%96%b0%e5%b9%b4/</link>
	<description>&lt;p&gt;大家新年快乐哈。&lt;/p&gt;</description>
	<pubDate>Sun, 22 Jan 2012 12:24:55 +0000</pubDate>
</item>
<item>
	<title>@delphij: 包含贷款保险的还款方案计算</title>
	<guid>tag:blog.delphij.net,2012://2.2149</guid>
	<link>https://blog.delphij.net/2012/01/post-612.html</link>
	<description>&lt;p&gt;问题：如果银行要求购买贷款保险，并且已知贷款保险在本金+首付达到22%时会自动撤销，但已经支付或预付的部分不会退还，已知贷款总金额、固定利率、年限，计算采用不同还款方案（按PMT计划，比PMT多还定额等）中一次性支付，以及每月支付的金额变化，以及若 cash out 时的收益差异。&lt;/p&gt;

&lt;p&gt;（本质上这个问题是个动态规划问题，不过具体的计算过程比较有实用价值，本文以 Google Docs 的 Spreadsheet 来举例，其他电子表格软件如 OpenOffice 的 Calc，以及 Excel 大同小异）。&lt;/p&gt;

&lt;p&gt;假定总共的还款期数为 360 期（30年），可以创建一个有362行的表格（第一行是表头）。A列填入月份的序号，0 .. 360，B列填入还款日期（这个可以用公式做，也可以直接填充，这些日期并不参与计算，因此不太重要）。C列全部填0（计划多还）。&lt;/p&gt;

&lt;p&gt;首先要算出贷款的 PMT 值，这个很容易，假设年名义利率为 RATE，贷款金额为 PV，贷款期数为 NPER（按月算），则公式为　=PMT(RATE/12,NPER,PV) 。把这个数字（由于 Google Docs 的限制，最好直接复制这个数字然后填充，如果是公式，则会因为填充时会自动根据单元格位置来调整导致数字不对）填入所有360行的 E 列，标记为&quot;原计划还款&quot;。&lt;/p&gt;

&lt;p&gt;由于需要考虑提前还款的情况，我们不能用 PPMT 和 IPMT 来直接计算本利的偿还情况。但是，如果知道上一月份的本金余额，当月偿还的利息是容易计算的（相当于以同样利率、上月本金余额，按360-当月序号的长度来重新贷款）。在 L 列填入当月本金余额：在第0个月，很明显这个金额就是总价 - 首付。因此，在L2这一行填写这个数值。接下来就可以知道每个月所偿还的利息了，我们用 J 列来表示所付利息，在 J3 填写 =IPMT(RATE/12,1,360-A3+1,L2)，然后将其填充至 J4..J362。此时，J4..J362还无法算出（因为我们并不知道 L3..L361 的数值）。&lt;/p&gt;

&lt;p&gt;为了方便观察提前 payoff 的效果，我们还应算出每个月累计偿还的总利息。在 K 列填入利息偿还累计，K2填0， K3 公式为 K2+J3，填充至 K4..K362。&lt;/p&gt;

&lt;p&gt;想要知道当月的本金余额，就必须知道当月偿还的本金金额。这个金额是当月支付的还款额减去当月应该支付的利息，即 E列 + C列 - J列。对于固定利率的贷款，如果提前还款的话，由于本金减少但每月还款额并不减少，因此会导致之后每个月偿还的本金增加（这也是为什么提前还款可以减少很多利息）。所以为了直观起见，在 I3 填入公式 =PPMT(RATE/12,1,360-A3+1,L2)，并填充到 I4..I362。这样，当月额外偿还的本金就可以用 C 列 + (E列 - I列 - J列) 算出。我们将这个公式填充到 D 列（额外偿还本金），并在 L3 填入公式 =IF(L3+I4+D4&amp;gt;0,L3+I4+D4,0)，填充至 L4..L362。&lt;/p&gt;

&lt;p&gt;F列是实际支付的贷款金额。F3公式为 =IF(L2&amp;gt;-E3-C3,E3+C3,-L2+J3)，即如果当月可还清，则为还清金额，否则为原计划还款+额外还款金额。&lt;/p&gt;

&lt;p&gt;G列填入当月需要缴纳的贷款保险金额。设贷款标的总价为 TOTAL，每月需要支付的贷款保险金额为 INS，则公式 G3 为 =-IF(L2&amp;gt;TOTAL*0.78,INS,0)，其中 0.78，填充至 G4..G362。&lt;/p&gt;

&lt;p&gt;H列填入实际支付给银行的金额，F+G。&lt;/p&gt;

&lt;p&gt;这样就可以很容易的得出汇总值：&lt;/p&gt;

&lt;p&gt;正常还款时，支付的总利息为 =CUMIPMT(RATE/12,360,PV,1,360,0)。&lt;/p&gt;

&lt;p&gt;实际支付的利息总额为 =SUM(J:J)。&lt;/p&gt;

&lt;p&gt;实际还款期数为 =COUNTIF(F:F,&quot;&amp;lt;0&quot;)&lt;/p&gt;

&lt;p&gt;实际支付的贷款保险费用为 预先支付的金额 + SUM(G:G)&lt;/p&gt;

&lt;p&gt;在对应月份的 C 列填入计划多还的金额即可看到计算结果（注意，上述公式假定此列数值应为负值）。&lt;/p&gt;

&lt;p&gt;上述方法仅供参考。&lt;/p&gt;</description>
	<pubDate>Sun, 22 Jan 2012 11:04:03 +0000</pubDate>
</item>
<item>
	<title>@delphij: 用市场比较法来估算价值</title>
	<guid>tag:blog.delphij.net,2012://2.2148</guid>
	<link>https://blog.delphij.net/2012/01/post-611.html</link>
	<description>&lt;p&gt;之前一直对市场如何决定一件东西的价值有疑问，现在记录一下其中一种方法。注意，这是个人对于这个问题的认识，而非科学论述，文责不负。对于读者自己遇到的具体问题，请咨询有关专业人士。&lt;/p&gt;

&lt;p&gt;以房屋价值为例，房屋的价格是不太容易确定的，因为每一个房子都不一样，决定房屋价值的因素又很多，例如它的位置、朝向、内外部装修的情况、保养的情况、内部电器的摊销价值，甚至买家卖家的心情，等等。在买卖双方没有必须成交的压力（例如法院拍卖，或因为人口增加必须购买房子）的情况下，往往会有一个讨价还价的过程，最终双方会共同认可一个交易价格，这个价格通常也会成为最终的交易价格。&lt;/p&gt;

&lt;p&gt;但是，对普通人而言，因为房屋是一种金额巨大的投资，往往在交易时会涉及贷款。这样就牵扯进来了一个新的利益攸关方----银行。从银行的角度来看，它既不太关心房子是否能够卖掉或者买进房子，而是需要关注风险（借贷人是否有偿还能力、房屋价格是否与价值相符，或者说贷款金额小于房屋合理价格的某个比例）和投资回报。因此，银行在提供贷款时就必须首先对房屋的价值进行评估。&lt;/p&gt;

&lt;p&gt;于是估价师就出现了。估价师不隶属于上面任何一个利益攸关方，最符合估价师利益的是尽量给出一个合理的评估，拿到相关报酬走人。那么，如何做出合理的评估呢？&lt;/p&gt;

&lt;p&gt;首先是收集数据。第一个来源，是郡政府公开的、用于征收地产税的房屋估值数据。在美国，对房屋的价值估算包括两部分，第一部分是土地价值（&quot;land&quot;），另一部分是土地上面的建筑等的价值（&quot;improvement&quot;）。在加利福尼亚州，依据1978年通过的第13号州宪公投，用于收税的房产估值每年可根据通胀情况上调最多2%。房产用于收税的估值，可根据其土地 APN 在对应郡的政府查询，但由于前面所述的13号公投，除非房屋在最近发生过交易，或发生了类似房产泡沫破裂这样的情况令纳税人主动要求调低估值，这个估值往往会比实际的市场价值低很多。&lt;/p&gt;

&lt;p&gt;另一个来源，也是比较可信的数据，是周围房屋在近期的交易价格。在进行房地产交易时，会在对应的政府部门进行登记；此外，由 MLS 维护的公开的数据中也会包含房屋从开始放到市场上，到最终完成交易的每一次价格变动记录。估价师会查找附近情况类似（面积、建筑年限、地皮尺寸等）的房屋在最近一段时间的成交价格和具体情况，并根据每一栋房屋的具体情况对交易价格进行一致化，所谓一致化就是消除房屋之间差异所导致的价格差异，例如，如果房屋位于较为安静的小路，通常在这个地区的交易价格会比位于较忙的路边的房屋高一万美元，则应在评估时使用的一致化价格中减去。&lt;/p&gt;

&lt;p&gt;有了足够多的市场价格，并根据具体情况分别进行一致化之后，估价师会得出一组一致化价格，并取其中位数来得到市场所认可的价格。&lt;/p&gt;

&lt;p&gt;有些估价师还会用其他估价方式给出另外的估值。例如，将土地价格加上按房屋年限摊销后的现时新建造价，再加上新增改建/家电设施的价格得到房屋的价格；或者，计算房屋按租赁价格和可以&quot;经济地&quot;租赁出去的时间来计算房屋的租赁价值，等等。&lt;/p&gt;</description>
	<pubDate>Sun, 22 Jan 2012 09:24:20 +0000</pubDate>
</item>
<item>
	<title>@shell909090: python的字符串相加效率</title>
	<guid permalink="False">http://shell909090.com/blog/?p=2070</guid>
	<link>http://shell909090.com/blog/2012/01/python%e7%9a%84%e5%ad%97%e7%ac%a6%e4%b8%b2%e7%9b%b8%e5%8a%a0%e6%95%88%e7%8e%87/</link>
	<description>&lt;p&gt;    今天文章被人纠了错，就跑去人家主页上逛。结果看到有篇文章说字符串相加速度的，看看结论很奇怪。就做了一下实验。原文可以看&lt;a href=&quot;http://www.keakon.net/2011/10/19/%E5%AD%97%E7%AC%A6%E4%B8%B2%E7%9B%B8%E5%8A%A0%E5%B9%B6%E4%B8%8D%E6%85%A2&quot; target=&quot;_blank&quot;&gt;这里&lt;/a&gt;。我们只讨论python部分的行为。首先是论证我观点的测试，无关部分就跳过了，大家应当可以自行补上。
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;def f():&lt;/div&gt;
&lt;div&gt;    s = ''&lt;/div&gt;
&lt;div&gt;    for i in xrange(3):&lt;/div&gt;
&lt;div&gt;        s += '123'&lt;/div&gt;
&lt;div&gt;        print id(s)&lt;/div&gt;
&lt;div&gt;    return s&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;f()&lt;/div&gt;
&lt;div&gt;f()&lt;/div&gt;
&lt;div&gt;输出：&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;138190216&lt;/div&gt;
&lt;div&gt;138276992&lt;/div&gt;
&lt;div&gt;138276992&lt;/div&gt;
&lt;div&gt;138190216&lt;/div&gt;
&lt;div&gt;138276992&lt;/div&gt;
&lt;div&gt;138276992&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;    至少在几十的规模，这个结论还是成立的。说明对象确实被缓存了，这导致了字符串相加的多次测试中，后续次数都没有实际的执行字符串分配动作。召dis来问之。&lt;/div&gt;
&lt;div&gt;
&lt;div&gt; 11           0 LOAD_CONST               1 ('')&lt;/div&gt;
&lt;div&gt;              3 STORE_FAST               0 (s)&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt; 12           6 SETUP_LOOP              41 (to 50)&lt;/div&gt;
&lt;div&gt;              9 LOAD_GLOBAL              0 (xrange)&lt;/div&gt;
&lt;div&gt;             12 LOAD_CONST               2 (3)&lt;/div&gt;
&lt;div&gt;             15 CALL_FUNCTION            1&lt;/div&gt;
&lt;div&gt;             18 GET_ITER            &lt;/div&gt;
&lt;div&gt;        &amp;gt;&amp;gt;   19 FOR_ITER                27 (to 49)&lt;/div&gt;
&lt;div&gt;             22 STORE_FAST               1 (i)&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt; 13          25 LOAD_FAST                0 (s)&lt;/div&gt;
&lt;div&gt;             28 LOAD_CONST               3 ('123')&lt;/div&gt;
&lt;div&gt;             31 INPLACE_ADD         &lt;/div&gt;
&lt;div&gt;             32 STORE_FAST               0 (s)&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt; 14          35 LOAD_GLOBAL              1 (id)&lt;/div&gt;
&lt;div&gt;             38 LOAD_FAST                0 (s)&lt;/div&gt;
&lt;div&gt;             41 CALL_FUNCTION            1&lt;/div&gt;
&lt;div&gt;             44 PRINT_ITEM          &lt;/div&gt;
&lt;div&gt;             45 PRINT_NEWLINE       &lt;/div&gt;
&lt;div&gt;             46 JUMP_ABSOLUTE           19&lt;/div&gt;
&lt;div&gt;        &amp;gt;&amp;gt;   49 POP_BLOCK           &lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;
&lt;p&gt; 15     &amp;gt;&amp;gt;   50 LOAD_FAST                0 (s)&lt;/p&gt;&lt;/div&gt;
&lt;div&gt;             53 RETURN_VALUE             &lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;    我们看到s是local变量，这个符合我们的预期。但是后续确实发生了add，而string的+算法，我们可以参考Objects/stringobject.c:1015这里，string_concat函数的内容。这里没有加速过程，即使有，也只有发生在len(a) == 0 or len(b) == 0的情况下。对于123的求和无法说明原因。&lt;/div&gt;
&lt;div&gt;    这里我只能做一个假定，我们发现的id相等，其实可能是由于内存重分配的结果。一个对象被回收后，是存放在对象池中的，再分配的时候，可能按照规则被重新分配。当然这只能是一个推测，实际证明必须在python源码中修改并且重编译，我就不找这个麻烦了。&lt;/div&gt;
&lt;div&gt;    另一个问题，实验的时候，只是把固定字符串更换为随机字符串而已，长度也没有发生变化。预期的结果应当是+=的速度变慢，结果+=速度不变。问题是join的速度加快算是怎么回事？关于join，我们可以参考Objects/stringobject.c:1574，这里说明了join的工作流程，也没有任何加速！&lt;/div&gt;
&lt;div&gt;    唯一的解释，就是append的工作速度慢到超乎正常人类的想像，实验证明了这点。&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;def g():&lt;/div&gt;
&lt;div&gt;    a = []&lt;/div&gt;
&lt;div&gt;    for i in xrange(1000):&lt;/div&gt;
&lt;div&gt;        a.append('1234567890')&lt;/div&gt;
&lt;div&gt;    # s = ''.join(a)&lt;/div&gt;
&lt;/div&gt;&lt;/p&gt;
&lt;div&gt;print Timer('g()', 'from __main__ import g').timeit(10000)&lt;/div&gt;
&lt;div&gt;    结果是0.91，append动作比join慢10倍。&lt;/div&gt;</description>
	<pubDate>Tue, 17 Jan 2012 17:51:37 +0000</pubDate>
</item>
<item>
	<title>@shell909090: 计算机自动化的方向</title>
	<guid permalink="False">http://shell909090.com/blog/?p=2068</guid>
	<link>http://shell909090.com/blog/2012/01/%e8%ae%a1%e7%ae%97%e6%9c%ba%e8%87%aa%e5%8a%a8%e5%8c%96%e7%9a%84%e6%96%b9%e5%90%91/</link>
	<description>&lt;p&gt;    我认为，人类操纵各种设备的权利不言自明，这是软件/电气设备进化的必然结果。
&lt;div&gt;    OK，我在吐槽什么？&lt;/div&gt;
&lt;div&gt;    昨天，老婆用了一次家里的新自动洗衣机。很好用——晚上把衣服全丢进去，然后设定模式，倒进去洗衣粉，今早六点他会自动启动。早上就拿着半干的衣服去阳台晾晒，整个过程没有一点麻烦。外婆家里的那台老洗衣机，每次使用都需要搬进搬出，连接一堆管线，然后发出巨大的响声，再由人工把半湿的衣服拿去晾。&lt;/div&gt;
&lt;div&gt;    ——如果要那样的话我们还得看着洗衣机，或者任由刚刚洗好的湿衣服在洗衣机里面闷六个小时。&lt;/div&gt;
&lt;div&gt;    我觉得，这才是享受人生的方式。当然，老婆和我也是一样的观点——我们在父母家里可是受够了老式洗衣机的刁难。她在发现这玩意的好处后，脑筋动的可比我快多了。早上还没有睡醒，我就被她吵起来，然后问了一个问题。&lt;/div&gt;
&lt;div&gt;    怎么远程遥控家里的微波炉和空调？&lt;/div&gt;
&lt;div&gt;    OK，很得意的说，这是家居设计时我早就发现的一个问题，然后很遗憾，我告诉她——暂时不行。这个是我调查了很久后得出的结论。我不大不小好歹是个程序员，怎么说在控制电器上也是有点经验的，不过这个问题确实超出了我的能力范围。目前我所知道的，控制电器的方式基本有三种。&lt;/div&gt;
&lt;div&gt;1.电器本身支持某种协议，例如wifi，或者蓝牙。我的电视机就支持eth网络，我可以通过手机遥控电视，或者直接在电视上观看某些节目，而不用打开电脑。&lt;/div&gt;
&lt;div&gt;2.通过电源接口做。例如我看到房屋装修中卖的最多的，号称智能屋的系统。大部分都只能支持电灯的开关，或者电灯开关支持的最好。因为电灯的开关是一个只和电源有关的问题，我们只需要做一个很小的单片机系统，装置在开关面板上。当这个机器收到无线信号的时候，就打开或者关闭电灯开关。&lt;/div&gt;
&lt;div&gt;3.通过红外线仿真做。这个适用于IrDA兼容的无线红外遥控设备。通过购买一个红外线装置，接收遥控发出的红外信号，再对着设备重发。&lt;/div&gt;
&lt;div&gt;    而以上三种方案，都是有缺陷，而且是严重缺陷的。&lt;/div&gt;
&lt;div&gt;    方案一，需要设备支持。通常来说，这样的设备都是相当昂贵的，而且不是每类别的设备都能买满意了。如果有一个很小的厂子生产一种空调，支持wifi。但是这个厂的空调机以不稳定而出名，你是否愿意为了遥控而冒常常要去修空调的麻烦呢？&lt;/div&gt;
&lt;div&gt;    方案二，不是每个设备都能灵活控制。空调和微波炉接入电源后处于待机阶段，而不是启动——这是最有遥控价值的两台机器。即使能启动好了，我再如何通过电源告诉他，把里面的东西给我加热10分钟？而且单片机接收信号必须有相当复杂的加密，至少能对抗差分攻击。否则就会陷入汽车解锁遥控器同样的问题——被破解。&lt;/div&gt;
&lt;div&gt;    方案三，更加糟糕。红外是一种指向性相当强的方案，所以当年的红外数据传输方案很快就被蓝牙替代了。也就是说，我要遥控三台空调，需要买三个红外设备，做固定指向。或者买两个电机来摇动红外设备。即使给我做出来了，不支持遥控的微波炉，自然也无法使用这个方案。&lt;/div&gt;
&lt;div&gt;    然而你很容易的想到，如果一个完全不明白技术关键的外行，在接触程控的第一天，就把我摇起来问这个问题。那么这个问题，肯定是我们将来的目标。&lt;/div&gt;
&lt;div&gt;    未来的设备，不但需要一套硬件界面（这个是必须的），而且还需要一套协议界面。为什么？你可以在家里的电脑里，通过符合协议的软件，一次性控制家里的所有设备，这就是所谓的“完全中控”。如果你觉得我是瞎说，鬼才会想要这种东西。请自己问问手里有一台ipad的同学，他们是否想在ipad上装个软件，直接遥控家里所有的电器？&lt;/div&gt;
&lt;div&gt;    他们想死了。&lt;/div&gt;
&lt;div&gt;    晚上的时候，把面包放进烤炉，执行一个good morning app。早上到时间了，闹钟会自动叫你起床，同时餐厅空调开始工作。当你确定起床后，面包就会自动开始烤，刷牙完毕正好出炉。出门的时候，所有设备都会自动关闭——整个房间里面没有任何一台中控设备了。晚上回家前，你的移动中控设备会通过3G自动唤醒灯光和空调。出门购物的时候，家里的冰箱会把缺什么东西传到你的手机上。&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;    这才是人生阿。&lt;/p&gt;&lt;/div&gt;
&lt;div&gt;    睡觉前总是习惯要听点音乐，睡着后需要自动关闭么？装个app吧，亲。那个app不能连带关闭空调么？换这个app吧，亲。想要起床前空调就开始工作么？我们的app带定制功能，而且有默认配置模板提供修改哦，亲。Bill Gates在《未来之路》里面所幻想的美好未来，其实和我们只有一步之遥。&lt;/div&gt;
&lt;div&gt;    这一步问题在哪里？协议。&lt;/div&gt;
&lt;div&gt;    其实我们是可以做到的，这样美好的生活。问题是，我们缺少一个协议。&lt;/div&gt;
&lt;div&gt;    有专业公司，提供装修服务。他们可以对你的家里进行改造，部分安装他们的外接设备，部分改为专用电器，并且在iphone上安装专用软件，实际上可以部分做到我刚刚说的。&lt;/div&gt;
&lt;div&gt;    问题是，贵，而且不开放。&lt;/div&gt;
&lt;div&gt;    开放的好处在于，如果这个系统不支持晚上睡觉前关闭空调，我可以自己写一个替换掉。而且如果某个电器坏了，我不需要高价问他们买一个新的专用电器，而是直接可以在商场里面买一个。而专用电器支持的问题则是，我必须持续使用他们的设备和服务，他们也不能关门。&lt;/div&gt;
&lt;div&gt;    所以我才说，我们需要一个协议。&lt;/div&gt;&lt;/p&gt;</description>
	<pubDate>Mon, 16 Jan 2012 22:56:19 +0000</pubDate>
</item>
<item>
	<title>@shell909090: 加密学中一个规定的来历</title>
	<guid permalink="False">http://shell909090.com/blog/?p=2066</guid>
	<link>http://shell909090.com/blog/2012/01/%e5%8a%a0%e5%af%86%e5%ad%a6%e4%b8%ad%e4%b8%80%e4%b8%aa%e8%a7%84%e5%ae%9a%e7%9a%84%e6%9d%a5%e5%8e%86/</link>
	<description>&lt;p&gt;    为什么密码学中总有个假定，算法是对方已知的，密钥是可以更改的？
&lt;div&gt;    因为在很久以前，密码算法是靠人工运算的，更改算法每次都需要培训一堆人，很麻烦。所以变态的需求催生了变态的解法——算法彻底公开，靠密钥保密。&lt;/div&gt;
&lt;div&gt;    还记得很多谍战片中的“密码本”么？如果在现代，那就只一个记载着256个字符的纸条。因为整个过程其实地球人都知道，双方只是相差一个纸条上的256个字符而已。&lt;/div&gt;
&lt;div&gt;    觉得这点东西不靠谱，随便记忆一下就搞定了？你想想，以前的密码本也可以照相阿。是重建一个密码本，并且分发给各处安全，还是重建一个纸条并分发方便？&lt;/div&gt;
&lt;div&gt;    现代？其实还是很有意义的。因为很多遗留系统/硬件模块中的算法会长达10多年不变，如果依靠算法保密来保护安全性，哪天泄露了不是开玩笑的。上千万的硬件模块，没有人维护的遗留系统，都要整死人的。&lt;/div&gt;
&lt;div&gt;    而且算法本身也必须足够强，如果没有公开算法，“足够强”这个事情本身就是含糊不清的。没有人见过你这个算法，没有人讨论，谁知道是不是“够”安全呢？md5以前一直作为哈希的标准，我们都觉得够安全了，但是哈希碰撞的研究使得现在基本都推荐sha256了。同样，DES也不要再用了，换成AES吧。&lt;/div&gt;&lt;/p&gt;</description>
	<pubDate>Sun, 15 Jan 2012 19:24:54 +0000</pubDate>
</item>
<item>
	<title>@delphij: delphijfork 9.0</title>
	<guid>tag:blog.delphij.net,2012://2.2147</guid>
	<link>https://blog.delphij.net/2012/01/delphijfork-90.html</link>
	<description>&lt;p&gt;可以在 &lt;a href=&quot;http://research.delphij.net/freebsd/delphijfork/&quot;&gt;这里&lt;/a&gt; 下载。&lt;/p&gt;

&lt;p&gt;和过去一样，风险自担 USE AT YOUR OWN RISK！&lt;/p&gt;

&lt;p&gt;和 FreeBSD 9.0-RELEASE 相比的改动：&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;修正了一组 tmpfs 的 bug；&lt;/li&gt;
	&lt;li&gt;针对 nullfs、 devfs 的可靠性改进；&lt;/li&gt;
	&lt;li&gt;&quot;skeljail&quot;；&lt;/li&gt;
	&lt;li&gt;top(1) 默认显示每个CPU的占用比例；&lt;/li&gt;
	&lt;li&gt;针对 powerd 的多处理器支持；&lt;/li&gt;
	&lt;li&gt;对 IPv4 流量分 IP 进行统计【注意，由于上锁开销，此改动会略微降低IPv4性能】；&lt;/li&gt;
	&lt;li&gt;重启时设置 watchdog；&lt;/li&gt;
	&lt;li&gt;改善 csh 可用性配置；&lt;/li&gt;
	&lt;li&gt;预设将共享内存绑在主存内；&lt;/li&gt;
	&lt;li&gt;Winbond watchdog 驱动；&lt;/li&gt;
	&lt;li&gt;对虚拟化环境默认不测试内存；&lt;/li&gt;
	&lt;li&gt;修正 NEW_PCIB 导致某些硬件问题的bug；&lt;/li&gt;
	&lt;li&gt;一系列 ZFS 相关改进；&lt;/li&gt;
	&lt;li&gt;减少 AHCI 上下文切换开销，高负载状态可达 3.8%；&lt;/li&gt;
	&lt;li&gt;一组 VM 性能改进，提高了异步操作以及 msync 情形的性能；&lt;/li&gt;
	&lt;li&gt;改善了 NFS 服务器预取的顺序读性能；&lt;/li&gt;
	&lt;li&gt;等等。&lt;/li&gt;
&lt;/ul&gt;</description>
	<pubDate>Sun, 15 Jan 2012 03:39:13 +0000</pubDate>
</item>
<item>
	<title>@shell909090: 昨天那个事情的后续——也谈网络安全</title>
	<guid permalink="False">http://shell909090.com/blog/?p=2064</guid>
	<link>http://shell909090.com/blog/2012/01/%e6%98%a8%e5%a4%a9%e9%82%a3%e4%b8%aa%e4%ba%8b%e6%83%85%e7%9a%84%e5%90%8e%e7%bb%ad-%e4%b9%9f%e8%b0%88%e7%bd%91%e7%bb%9c%e5%ae%89%e5%85%a8/</link>
	<description>&lt;p&gt;    安全无小事阿，昨天批评到一半，发现遇到李鬼了。尴尬，赶紧修正文章，不知道影响多大。
&lt;div&gt;    我们事后推理，问题可能是这样的。有人故意在赶集网上用别人电话发布信息，然后等你的电话被打爆。赶集网本身只允许举报手机滥用，而不支持座机举报。所以你会找客服电话，但是他们客服电话又找不到。他们做一下SEO搜索，或者直接买关键词。你通过搜索，找到的就是他们。你要取消，他们就要你汇保证金。保证金进去了，然后你就被骗了。
&lt;div&gt;    当然，文章本身的批评也算是成立，常规发布电话信息应当是先确认再使用的，投诉的系统也应该支持座机等方式。由李鬼客服的存在，你可以想见到底有多少人试图投诉电话被错误使用，在系统中又无法删除。&lt;/div&gt;
&lt;div&gt;    但是我要说的是，这个诈骗差点成功的关键原因在于——赶集网没有公布自己的客服电话。由于没有官方公布，因此使用搜索引擎搜到的根本是李鬼。当然，如果打官司，赶集网肯定是无责任的。但是，被骚扰过的公司都知道，真的到了这个地步，你会很烦，非常烦。我相信对百度恨之入骨的不少公司应该都知道我的意思——明明不是我的事情，脏水泼头上，客户在骂娘。&lt;/div&gt;
&lt;div&gt;    我更进一步看了一下赶集网这个网站，安全么？也不安全。别的不说，登录系统还是使用http，而非https。两者差异非常大。使用http的，只要通过一个恶意的网关，就可以捕获到用户密码。作为玩玩而已的网站，我觉得使用http也就算了。作为一个商业公司，登录系统不使用https，实在是有点不专业。至于投诉电话也是一个例子。如果你打算联系新浪，打开网页，拉到最下方，直接就有400电话，根本不用担心这个问题。&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;     各个网络教材反复告诉我们，安全不是一个技术问题。实际上，安全是一个从最高层到最下面的意识问题。作为安全的头一步，首先你要告诉你的用户——你应当信任什么。&lt;/p&gt;&lt;/div&gt;
&lt;div&gt;    如果你的公司是一家实体公司，以电话业务为主。那么你的宣传要点可能就是电话，而网站的具体网址可能就是通过短信方式进行分发（至少要有这个功能）。这方面的例子有携程。而如果是一家网络公司，以网络业务为主。那么你的宣传要点就是你的网址。为了安全，我建议稍微做大一点的时候，就干脆点，把常见的拼写错误全买下来，省的李鬼入侵。你的地址，联系电话，都通过网络分发，而且要让别人找的到。&lt;/div&gt;
&lt;div&gt;    上面一段简单点来说，就是，一个主要的宣传方式，上面发布所有的可信联系方式。为什么？如果你不发布，就可能有李鬼进来。到时候再处理，就非常困难。&lt;/div&gt;
&lt;div&gt;    盗梦空间里面说过，要确认你在真实的世界，而不是梦境中，并不容易。现实中，要确认和你说话的人的真实身份，也不容易。通常来说，如果你问我借钱，我要给你钱，你都能在对话里面发现我会问你一些有点奇怪的问题。frank应该心领神会，他问我借卡的时候，我可是在敲定事情后直接抄起手机给他打了个电话。通常来说，IM可以被偷，但是电话没有道理一起被偷。即使被偷了，还能伪装声音，那我也认栽了。我现在还欠着钱没还的小一，某位报社编辑，还有我帮忙充过卡的老燕子。如果你们看到这篇文章，应该也能回想起我给你们相关信息时问过一些奇怪的问题吧。&lt;/div&gt;
&lt;div&gt;    这些问题，叫做背景知识验证，我在前面的一篇文章中提到过。背景知识验证的基础是你们拥有相同的知识。而对于一个网站，你没办法使用这个办法的。所以，为了防止李鬼，你要反过来，使用无知假定。所谓无知假定，就是，在你面前的人充分证明自己之前，没人知道他是谁。也就是俗称的《互联网上没人知道你是一条狗》。所以作为客户来说，不要轻易相信搜到的联系方式，最好用114。当然，114上如果没有，那也没有什么太好的办法。&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;    另外昨天和42区的同学谈了谈，他说会警告赶集的朋友。毕竟李鬼的存在对正品网站是一种伤害。但是从现在来看，只能采取防御策略。具体什么策略，就看赶集网的计划了。不过比较有意思的是，昨天我们谈到李鬼的时候，说到“互联网人士也无法分辨”，他给了我一个例子。&lt;a href=&quot;http://rexsong.42qu.com/10037273&quot;&gt;在淘宝被诈骗5.46万始末&lt;/a&gt;。我看完吓了一跳。千鸟是小米的信息架构，算是IT圈子里面的人，不能算外行。在购物的时候，也是小心又谨慎。即使如此，还是被骗了！这只能说一点，即使是内行，也不要仗着自己专业就放松警惕。&lt;/p&gt;&lt;/div&gt;
&lt;div&gt;    我仔细看了一下流程，主要能找到的问题有以下几个。不过需要提前说明的是，这些都是马后炮。很多事情我们知道不应该，但是真的都有避免么？如同我某篇文章说的那样，就是彻底的神经质了。&lt;/div&gt;
&lt;div&gt;1.在不可信环境中消费。这是一切问题的根源。本质上说，应当把环境分为“可信”和“不可信”，并且在几个信任等级间架防火墙。可信机器可以通过虚拟机产生一个不可信环境（沙盒），但是反之不可以。同密级机器可以弱密码或无密码互联。高密级机器可以无密钥连接低密级，反之不行。&lt;/div&gt;
&lt;div&gt;2.没有在发生问题的第一瞬间进行止损。对于大额支付（对我而言，1000以上统统叫大额），网银一旦提示成功，而支付宝里面没看到钱。第一瞬间反应绝对不是再来一次，而是直接敲电话给网银，然后是支付宝。绝对不要试图在支付失败问题没搞明白的时候再试验一次，就算试，最多也只能试一毛钱。&lt;/div&gt;
&lt;div&gt;    但是归根结底，这件事情轮到谁头上基本都是中招的，因为要管理的问题太多了。&lt;/div&gt;
&lt;div&gt;    反思了一下自己，我打算在自己的环境中推进几个事情。&lt;/div&gt;
&lt;div&gt;1.重新设定防火墙，关闭不需要的服务和开放设定。&lt;/div&gt;
&lt;div&gt;2.重整U盾，假定他可复制，因此需要使用特殊的保密环境进行支付。&lt;/div&gt;
&lt;div&gt;3.对环境中的几台不可信机器进行行为监控。&lt;/div&gt;
&lt;div&gt;4.定期读日志，尤其是异常报告。&lt;/div&gt;
&lt;div&gt;5.关掉“仅使用手机动态密码支付”的选项。&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;PS.这篇文章不代表我支持网络实名制，但是我觉得应当让自己想实名制的人实名制。&lt;/div&gt;
&lt;/div&gt;&lt;/p&gt;</description>
	<pubDate>Thu, 12 Jan 2012 20:06:09 +0000</pubDate>
</item>
<item>
	<title>@delphij: 为什么输入敏感数据（如登录信息）的页面也要做成 https？</title>
	<guid>tag:blog.delphij.net,2011://2.2145</guid>
	<link>https://blog.delphij.net/2011/12/-https.html</link>
	<description>&lt;p&gt;有一种错误的观念是，对于不太敏感的内容（例如论坛之类），只要用 https 保护登录过程中提交密码的部分就足够了。例如国内非常流行的网易邮箱，很早以前便提供了&quot;SSL安全登录&quot;的选项，这样做显然是比完全不提供SSL登录选项的新浪邮箱要强多了[注1]，但是仍然是不够的。&lt;/p&gt;

&lt;p&gt;为什么呢？因为通过明文传输的网页没有提供任何保护，而通过 https 传输的内容则是提供端到端（从服务器到客户的浏览器）的安全保证的。例如，代理服务器可以根据需要按URL（这是非常成熟的技术）来替换掉页面，而配合 DNS 攻击，或者攻击者掌握了受害人使用的网络基础设施，便可以在对方不知情的情况下把敏感数据传到攻击者控制的服务器上。假如采用了 https，攻击者能够选择的选项就大大减少了（例如，攻击者必须能够伪造适当的证书，并劫持、解密所有流量，等等）。&lt;/p&gt;

&lt;p&gt;当然，使用 https 并不能阻止用户访问钓鱼网站并在其中输入敏感数据。这类用户应远离 Internet。&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;[注1] 不过很讽刺的是，新浪邮箱的登录首页实际上是有 https 版本的，但是这个 https 版本并不处理提交；而网易邮箱则完全没有提供 https 版本的登录首页。&lt;/p&gt;</description>
	<pubDate>Wed, 11 Jan 2012 23:57:10 +0000</pubDate>
</item>
<item>
	<title>@xupeng: Code Swarm</title>
	<guid>http://blog.xupeng.me/2012/01/12/code-swarm</guid>
	<link>http://blog.xupeng.me/2012/01/12/code-swarm/</link>
	<description>&lt;p&gt;&lt;a href=&quot;http://www.michaelogawa.com/code_swarm/&quot;&gt;Code swarm&lt;/a&gt; 是一个可视化项目，最常见的用途是把代码仓库的提交历史可视化，changesets 以时间顺序回放，每个发生变更的文件作为一个闪亮的光点从各处汇聚在对应的 committer 身上，把项目的演进历史以视频的方式形象地呈现出来，通常还会配上激动人心的背景音乐，令程序员们潸然泪下。&lt;/p&gt;

&lt;!-- more --&gt;


&lt;p&gt;很多著名的开源项目比如 &lt;a href=&quot;http://vimeo.com/1093745&quot;&gt;Python&lt;/a&gt;、&lt;a href=&quot;http://vimeo.com/1265258&quot;&gt;Subversion&lt;/a&gt;、&lt;a href=&quot;http://vimeo.com/1223937&quot;&gt;Django&lt;/a&gt;、&lt;a href=&quot;http://vimeo.com/1081680&quot;&gt;PostgreSQL&lt;/a&gt;、&lt;a href=&quot;http://www.vimeo.com/1076588&quot;&gt;Apache&lt;/a&gt; 等等都有 code swarm 视频，很多互联网公司也都有 code swarm 视频，比如 &lt;a href=&quot;http://vimeo.com/9225227&quot;&gt;Twitter&lt;/a&gt;、&lt;a href=&quot;http://vimeo.com/2249514&quot;&gt;Last.fm&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;可视化是一项伟大的技术，它使非专业人士也能形象地感受到“虚无事物”的发展历程，向致力于可视化的科学家和程序员致敬！&lt;/p&gt;

&lt;p&gt;豆瓣发展至今已经有 7 年了，2008 年的时候 &lt;a href=&quot;http://www.douban.com/people/hongqn/&quot;&gt;hongqn&lt;/a&gt; 做过一个 &lt;a href=&quot;http://www.youtube.com/watch?v=4f2xkvKAAXo&quot;&gt;code swarm 视频&lt;/a&gt;，时至今日，豆瓣的工程师队伍已经壮大了数倍，再次做了 code swarm 视频。&lt;/p&gt;

&lt;p&gt;这次我使用了 &lt;a href=&quot;http://www.michaelogawa.com/code_swarm/&quot;&gt;code_swarm&lt;/a&gt; 项目的一个 &lt;a href=&quot;https://github.com/rictic/code_swarm&quot;&gt;fork&lt;/a&gt;，这个 fork 最大的亮点是加入了头像支持，除了 committer 的 ID 之外，还可以显示头像，使辨识度更高，按照项目的简要文档可以很容易地为单仓库生成视频。&lt;/p&gt;

&lt;p&gt;code_swarm 接受的输入是一个配置文件和一个 XML 格式的 events 序列，每一个发生变更的文件加上 commiter ID 和时间（1970-01-01 00:00:00 起的毫秒数 / UNIX timestamp * 1000）组成一个 event，最终的 events 文件会是类似这个样子：&lt;/p&gt;

 &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&quot;line-number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;code class=&quot;xml&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;file_events&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;nt&quot;&gt;&amp;lt;event&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;date=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;1104508800000&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;author=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;bo&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;filename=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;/trunk/luz/doulist/douledit_ui.ptl&amp;quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/event&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;nt&quot;&gt;&amp;lt;event&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;…&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/event&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/file_events&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;


&lt;p&gt;为了生成 events 文件，需要先将代码仓库的变更历史导出，code_swarm 的 &lt;a href=&quot;https://github.com/rictic/code_swarm/blob/master/bin/convert_logs.py&quot;&gt;convert_logs.py&lt;/a&gt; 工具提供了对多种版本仓库的支持，可以从仓库导出历史并转换为 events log，不过不太符合我的需求。&lt;/p&gt;

&lt;p&gt;为了把很多个代码仓库做为一个整体来呈现，需要把所有仓库的历史按时间顺序合并到一起，于是我将这个过程分成了四个串行的步骤：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;从各个仓库导出历史&lt;/li&gt;
&lt;li&gt;解析历史为中间格式并合并为一个文件：&lt;code&gt;&amp;lt;committer ID&amp;gt; &amp;lt;timestamp&amp;gt; &amp;lt;file path&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;对中间格式的文件按时间排序&lt;/li&gt;
&lt;li&gt;生成最终需要的 events log&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;这个过程不再赘述，每个步骤都比较简单，这中间比较比较麻烦的是，在不同的代码仓库中尤其是分布式版本仓库中同一个 committer 的 ID 可能是不一样的，甚至同一个 committer 会有很多个不同的 ID，需要 normalize 为辨识度最高的那一个，另外还有一些系统账号的自动 commit，也需要排除在外。&lt;/p&gt;

&lt;p&gt;另外一个输入是配置文件，可以在 &lt;a href=&quot;https://github.com/rictic/code_swarm/blob/master/defaults/code_swarm.config&quot;&gt;默认配置文件&lt;/a&gt; 基础上做调整，以达到比较好的可视效果，这个步骤是整个过程中耗时最长，也是耗费硬件资源最多的，为了在大屏幕上有一个较好的效果，可能还需要修改一些硬编码在代码中的参数、更换或微调整物理引擎，不同的项目不同的变更历史不同的 committer 数量需要使用的参数差别可能比较大，只能逐个调整并测试…&lt;/p&gt;

&lt;p&gt;另外需要准备每个 committer 的头像，使用 PNG 格式，以 committer 的 ID 命名，需要注意的是，头像需要是正方形的，可以借助 PIL 或 imagemagick 来做辅助的切割和格式、大小转换，长宽相差比较多的头像可能需要手工裁剪才能得到比较好的可视效果。&lt;/p&gt;

&lt;p&gt;code_swarm 直接实时地呈现视频，但并不是直接输出视频文件，而是生成一帧一帧的图片文件，这样比较方便对最终的视频做定制，比较遗憾的是，code_swarm 没有 headless 模式，没有办法选择不显示实时视频而只生成图片文件，所以这个过程会很慢，在我的 MBP 990 上生成 7 年 12780 帧图片需要 40 分钟以上…&lt;/p&gt;

&lt;p&gt;图片生成之后，可以使用视频编码工具将图片合并为视频，强大的 mencoder 和 ffmpeg 都能轻松完成这个任务，比如使用 ffmpeg 生成 quicktime 格式的视频是这样：&lt;/p&gt;

 &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&quot;line-number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;line&quot;&gt;ffmpeg -f image2 -r 43 -i ./code_swarm_frames/%05d.png &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;  -sameq ./codebang.mov -pass 2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;


&lt;p&gt;其中 -r 43 是指每秒钟 43 帧，因为需要配乐，对音乐做裁剪相对麻烦并且影响听觉效果，所以可以直接生成与音乐长度相当的视频，这里的 43FPS 是总帧数除以音频文件秒数得到的，帧速可以使用小数，所以可以精确控制视频长度。&lt;/p&gt;

&lt;p&gt;项目演进过程中肯定会发生很多大事件，以字幕的形式标注这些大事件是一个比较好的方法，srt 是最简单的字幕格式，每一节字幕是这样的：&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&quot;line-number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;code class=&quot;&quot;&gt;&lt;span class=&quot;line&quot;&gt;1
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;00:00:07,414 --&gt; 00:00:11,414
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;2005年3月6日 豆瓣上线&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;


&lt;p&gt;第一行是字幕序号，递增，第二行是起始时间和结束时间，精确到毫秒，控制字幕出现和隐去的时间，第三行之后是字幕，可以有多行。两节字幕之间以空行分割。因为有大事记，所以都会有具体的日期，根据视频的长度，和仓库变更的起始、结束日期，可以计算出每一节字幕在视频中的绝对位置，所以生成字幕这个步骤可以半自动化，在测试搭配不同长度的音乐时可以节省不少手工调整字幕的时间。&lt;/p&gt;

&lt;p&gt;最后一个步骤是将视频、音频和字幕合成为一个文件，我使用了 mencoder：&lt;/p&gt;

 &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&quot;line-number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;6&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;line&quot;&gt;mencoder -o codebang.avi -ovc lavc &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;  -lavcopts &lt;span class=&quot;nv&quot;&gt;vcodec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;mpeg4:mbd&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;2:vbitrate&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;16000 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;  -oac mp3lame -lameopts cbr:br&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;320:q&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0 -sub codebang.srt &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;  -utf8 -subfont-text-scale 2.5 -overlapsub &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;  -font &lt;span class=&quot;s2&quot;&gt;&amp;quot;Hiragino Sans GB W6&amp;quot;&lt;/span&gt; -subpos 92 codebang.mov &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;  -audiofile background.mp3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;


&lt;p&gt;要得到好的可视效果，这个过程实际上还是挺耗费精力的，不过很值得，工程师嘛，就这点追求&amp;#8230;&lt;/p&gt;

&lt;p&gt;更新：Code swarm 视频在&lt;a href=&quot;http://v.youku.com/v_show/id_XMzQzNDc4MDk2.html&quot;&gt;这里&lt;/a&gt;。&lt;/p&gt;</description>
	<pubDate>Wed, 11 Jan 2012 22:49:00 +0000</pubDate>
</item>
<item>
	<title>@shell909090: 越想避开2B事，事情就越找上门——一个朋友的隐私泄漏问题</title>
	<guid permalink="False">http://shell909090.com/blog/?p=2062</guid>
	<link>http://shell909090.com/blog/2012/01/%e8%b6%8a%e6%83%b3%e9%81%bf%e5%bc%802b%e4%ba%8b%ef%bc%8c%e4%ba%8b%e6%83%85%e5%b0%b1%e8%b6%8a%e6%89%be%e4%b8%8a%e9%97%a8-%e4%b8%80%e4%b8%aa%e6%9c%8b%e5%8f%8b%e7%9a%84%e9%9a%90%e7%a7%81/</link>
	<description>&lt;p&gt;首先向赶集网道个歉，核实下来居然是李鬼，主题还真没写错。下文根据事实情况做了修正，看过原文的可以对比看看。&lt;/p&gt;
&lt;p&gt;今天一个朋友中午给我打电话求助，问我能不能在网络上把一个信息给删了。我顿时一惊——你被陈老师了？还是有人曝光你们家怎么怎么，所以花钱删帖？&lt;/p&gt;
&lt;div&gt;    结果都不是的，她家里电话被登在了赶集网的某个页面上，还置顶了。一个中原地产的人发布房屋消息时，用的是她的座机。&lt;/div&gt;
&lt;div&gt;    我顺手查了查，赶集网有删除错误信息的选项阿。&lt;/div&gt;
&lt;div&gt;    ——你自己用用试试看？&lt;/div&gt;
&lt;div&gt;    我输入号码，我去阿，居然是js验证，要求号码必须是手机。仔细看看，是输入手机后发送验证码，输入验证码删除。&lt;/div&gt;
&lt;div&gt;    有点道理，可是我朋友家里是座机，咋办？&lt;/div&gt;
&lt;div&gt;    她找了找赶集的客服，但是没找到客服电话。搜索了一下网络上，有个人表示是赶集网的客服部，他说对方是付费用户，自己选择的置顶，她们无法删除。要么，交1000押金，立刻删除。对方三天内没提出意见，押金退还。&lt;/div&gt;
&lt;div&gt;    这个事情就很搞笑了，我自己的信息，要付费才能删除？传说中的百度产品经理去了赶集网么？&lt;/div&gt;
&lt;div&gt;    我说，你要么找发布者看看？&lt;/div&gt;
&lt;div&gt;    她说我找了，对方是中原地产的，说话很不客气。说这个事情我们检查一下，如果有问题，我们会处理的。她怀疑是对方在故意整她，不过这个事情目前没有任何证据的。&lt;/div&gt;
&lt;div&gt;    然后她只能等着，期间电话还是一个接一个的进。她家里也是开公司的，电话不能不接，也没法做垃圾过滤。&lt;/div&gt;
&lt;div&gt;    逼急了，她准备去报警，还不知道警察受理不受理。&lt;/div&gt;
&lt;div&gt;    42qu的某同学找我，说他认识一个赶集的人。他准备和对方沟通一下，看看能不能删除。先谢谢该同学。&lt;/div&gt;
&lt;div&gt;    过了中午，赶集的产品给了我一个消息。只要打给客服，客服会要求你提供电话。然后他们会回拨你一下，你接，就可以认证身份，然后对方就会删除信息。&lt;/div&gt;
&lt;div&gt;    我联系了朋友，她顿时觉得——怎么和上一个说的一点都不一样阿。&lt;/div&gt;
&lt;div&gt;    我和42qu的同学联系了一下，要了一下他们的客服电话（我们都找不到客服电话，他们的产品只有打过去要）。然后我朋友打过去，很快，问题解决了。&lt;/div&gt;
&lt;div&gt;    OK，大家现在应该猜到了，上午我们碰到了李鬼，也不知道我朋友是不是用百度搜索的。&lt;/div&gt;
&lt;div&gt;    如果真的打钱过去，就完蛋了。&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;    先不说登录信息人的问题，我首先说赶集网的策略。&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;    对于没有验证过的个人信息，采取“首先使用”的策略合理么？如果我找个虚假信息登记一下，成为用户，然后付费置顶，再录入某人或者某公司座机为火车票预定电话。那他们的电话不是瘫痪了？&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;    其次，对于问题的反应，赶集网并不是很上心。网站的快速删除根本没有考虑座机如何操作，只考虑了手机。普通投诉在24个小时内也没有响应。而且没有明确的提供客服电话——至少两个程序员没有找到。如果赶集网本身提供了客服电话，或者快速响应了人工投诉，那么也没有后文的问题。问题是赶集网本身对客服并不是很热心。也许这是因为他们需要压缩客服成本。&lt;/div&gt;
&lt;div&gt;    最后，归结到根本上，赶集网对于有可能侵犯客户隐私的事情，有什么成本呢？&lt;/div&gt;
&lt;div&gt;    我怀疑没有成本。&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;    我朋友如果去报警，最大可能是警方只提供记录，但是不处理。要解决，可以，自己起诉赶集网去。首先去公证处取证，一个页面3000（这还是07年的价格），然后去侵权所在地。赶集网的总部在北京，中关村软件园八号楼，所以要在北京市海淀区法院进行起诉。然而起诉前不能排除调解，因此可能还要过一遍调解过程。如果调解无效，那么开始起诉过程。如果对方不服，还有上诉。我不说隐私泄漏的结果如何计算，仅仅是这个时间和成本，就远远不是一般人能接受的。&lt;/div&gt;
&lt;div&gt;    因此赶集网实际上是没有风险的，因为很少有人会去执行。既然没有风险，那么自然也就没有动力考虑，如果被错误使用的不是手机如何，如果被错误使用的是地址如何，如何规避不慎泄漏了对方信息造成的风险——反正也没风险么。&lt;/div&gt;
&lt;div&gt;    在这里我批判的不是赶集网这个网站本身，作为一个公司，天大地大赚钱最大，你不能说这个是错的。那么和赚钱无关的事情不优先考虑，同样，也不能说是错的。我固然欣赏谷歌“不做恶”的信条，但是同样深知，你不能指望每个公司都信奉这点。&lt;/div&gt;
&lt;div&gt;    然而，难道说用户信息泄漏就是对的么？我们的电话被登录在网站上，被打爆，关键电话接不到，导致经济上的损失，或者其他一些事情，难道这就是对的么？&lt;/div&gt;
&lt;div&gt;    你必须让泄漏用户隐私变成公司的成本，而且是很大的成本，公司才会去关注这个问题。这点不仅对赶集如此，对百度如此，对人大代表如此，对你我也是如此。&lt;/div&gt;
&lt;div&gt;    你是否有把自己的手机写在人人和开心的页面上？&lt;/div&gt;
&lt;div&gt;    有写的话，就不要在接到垃圾短信的时候光抱怨各个公司泄漏你的个人消息。&lt;/div&gt;
&lt;div&gt;    你是否也有侵犯别人隐私的时候呢？例如你问，结婚了没？工资多少？在哪里上班？父母还在不在？&lt;/div&gt;
&lt;div&gt;    这些难道就不是隐私了么？&lt;/div&gt;
&lt;div&gt;    你见到没信用的公司的时候，是否还会用他们的产品呢？例如三鹿。虽然现在他被并购了，但是并购前，你还会喝他的牛奶么？如果不会，你看到侵犯隐私的公司，你会不会和他们提出意见呢？会不会用他们的产品呢？还是笑笑当作没事一样？&lt;/div&gt;
&lt;div&gt;    我知道这个社会一向不大把隐私当回事的。大到公司能大喇喇的把别人的家庭电话具体住址贴出来。小到我们每个人每天都在问别人的薪水。远到网络实名制的时候有人说，要么我们全填方老师的信息好了，并且把方老师的信息全公布出来。近到你看着看着这篇文章，突然手机响了，打开一看——又是垃圾短信。&lt;/div&gt;
&lt;div&gt;    我们每天都在被别人侵犯隐私，也在侵犯别人的隐私。我相信，即使在隐私保护比较好的国家，类似的问题也是层出不穷。问题是，我们多关注，多做一些事情，也许我们的情况就能好转点。虽然听起来没有联系，但是你少问别人工资，看到垃圾短信多举报（前提是这个机制要有用），看到网站对隐私保护不利要多投诉，也许在几千次的尝试后，你自己，或者你的后代，就能拥有更好的生活。&lt;/div&gt;
&lt;div&gt;    当然，如果你也不关心这个问题，那请当我没说。&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;    最后，赶集网的客服电话是：010-59013666。特此公布以正视听。如果你发现有问题，可以在关于那里找到我的联系方式，我会尽快响应。&lt;/div&gt;</description>
	<pubDate>Wed, 11 Jan 2012 21:19:34 +0000</pubDate>
</item>
<item>
	<title>@shell909090: 最牛电商</title>
	<guid permalink="False">http://shell909090.com/blog/?p=2060</guid>
	<link>http://shell909090.com/blog/2012/01/%e6%9c%80%e7%89%9b%e7%94%b5%e5%95%86/</link>
	<description>&lt;p&gt;    昨天聊天，聊到最牛电商的问题，大家都笑了。&lt;br /&gt;    frank订票45分钟花了45分钟，还没搞定。先是从chrome换到IE，因为前面的部分chrome能用，付款不行。然后从工商付款，上限500，不行，必须一次付款800，而且不能用支付宝。问我借卡，我的也不行。最后借到卡了，结果过45分钟了，重排，没票了。&lt;br /&gt;    淘宝买东西要是需要超过5分钟，喵喵就会少买好多东西。&lt;br /&gt;    还有个朋友说，他的卡能支付5000，买票，扣款后没票。人家说钱能拿回来的——钱能回来可是票回不来阿。好，再买，又扣钱没票。再买——没钱了。&lt;/p&gt;
&lt;p&gt;    我去阿，这TMD不是坑爹么？&lt;br /&gt;    这种网站，转化率还是100%，广告成本0，绝对最牛电商阿——没有之一。&lt;/p&gt;
&lt;p&gt;    关于顶不住这个问题呢，大家都懂的。我自己也做过类似的事情——甲方设法让自己的厂家中标，也不管人家有没有能力做。厂家领导是先中标再说，不中标自己就完蛋了。下面的人没能力，要么是不知道自己没能力，要么是知道也不敢说。做着做着问题一堆，也不敢和甲方沟通。不沟通问题就越来越多，交货的时候一看，甲方吐血。然后厂家领导就和甲方领导搞协调，厂家要去修一些问题的，甲方延一点时间，最终还是会让这个系统上去的——否则领导也麻烦阿。&lt;/p&gt;
&lt;p&gt;    最后只要这个烂摊子不被揭出来，大家皆大欢喜。中国政府领域的IT，大多都是这个样子。&lt;br /&gt;    比较大的烂摊子揭出来的，一个是绿坝。没办法，太烂了，还要所有机器供应商都来做支持。索尼干脆发了个文，这是中国政府让我们装的，出了问题不要找索尼，谢谢。结果这样还被告上美国法庭了。最后领导实在顶不住压力，撤了。另一个就是这个，最牛电商，估计回头也会撤的。因为后面订票压力越来越大，搞事情的人也越来越多，烂摊子搞到后来领导也会怕的。&lt;/p&gt;
&lt;p&gt;    其实昨天gary说了一句比较实在的话，这个系统不应该做成这个样子的。一切说中国买票的人太多，瞬间交易压力大，刷不出票的人持续刷的，都是借口。知道压力大，搞分时销售和抽签制分散压力。前端做负载均衡和CDN负担压力，后端真到订票的时候转换成MQ去操作。大型机再怎么做的差，每秒1000个transactions是出的来的。一小时就能完成360W的交易，一天八小时，3000W的票就出来了。中国有多少人需要订票的？3亿？就算做瞬时压力，铁道部车票成交比纽约股市买卖还快，要求还高？技术做不到根本是扯淡，最多是钱的问题——现在还是花钱没解决问题。
&lt;div&gt;
&lt;p&gt;    为了见证奇葩，我特地上去看了一下，结果第一眼就晕倒了——铁道部需要你自行下载根证书。我去阿，堂堂铁道部，一个多少万的项目，连TM买一张证书的钱都没有？！&lt;br /&gt;    其他细节就不多写了，相信用过的人比我都清楚的多。需要多次点击才能买到一张票，访问过程长导致压力大。定时开票，时间集中导致压力大。需要注册，导致注册过程冗长，也是增加压力。这些都不是技术问题。&lt;br /&gt;    整个过程中耗时最长的（抱歉我懒得注册，只去看了余票查询），一个是&lt;a href=&quot;http://dynamic.12306.cn/TrainQuery/leftTicketByStation.jsp%E3%80%82&quot;&gt;http://dynamic.12306.cn/TrainQuery/leftTicketByStation.jsp。&lt;/a&gt;这个的服务器响应表明是来自Apache-Coyote/1.1，由squid/3.1.18缓存，未命中。另一个是&lt;a href=&quot;http://dynamic.12306.cn/TrainQuery/passCodeAction.do?rand=rrand%E3%80%82&quot;&gt;http://dynamic.12306.cn/TrainQuery/passCodeAction.do?rand=rrand。&lt;/a&gt;这个的服务器响应表明来自Apache-Coyote/1.1，是一张image（验证码），同样未命中。基本squid命中的都在ms级别返回了，出问题的都是&lt;a href=&quot;http://dynamic.12306.cn&quot;&gt;dynamic.12306.cn&lt;/a&gt;这个域名没有命中的页面。这个表明前端的缓存还行，压力都压到了后端。至于造成这个现象的原因是前端缓存策略错误，还是后端性能相对不足，就不知道了。&lt;/p&gt;
&lt;p&gt;    我注意到，至少有一个页面&lt;a href=&quot;https://dynamic.12306.cn/otsweb/css/contact.css%E3%80%82Server&quot;&gt;https://dynamic.12306.cn/otsweb/css/contact.css。Server&lt;/a&gt;字符串是asfep/2.3.0 svn:3075。asfep是什么我不知道，google了一下也没出来。不过svn？这文件是从svn服务器上出来的么？！如果是，这就有点奇葩的味道了。&lt;span class=&quot; &quot;&gt;&lt;/span&gt;
&lt;div&gt;    然后我点了一下查询，这下大奇葩出现了。一个query居然执行了30s以上。在验证码故意输错的情况下，返回速度在10s这个量级，而输入正确就天长地久了。由此可见系统是分成多个部分的，最外面是&lt;a href=&quot;http://dynamic.12306.cn&quot;&gt;dynamic.12306.cn&lt;/a&gt;和&lt;a href=&quot;http://12306.cn&quot;&gt;12306.cn&lt;/a&gt;两个域名，上面用squid做了缓存。后面是一堆应用服务器。其中有一些Coyote服务器的响应特别慢，大概在1-10s这个量级。而这些服务器当访问数据库的时候，就彻底变成访问无望了。按照网络上说法，铁道部用的是Oracle数据库，估计已经半瘫痪了。&lt;/div&gt;
&lt;div&gt;    说是Coyote，其实如果没什么意外，这个就是Tomcat。那么铁道部的架构底子基本也就出来了，是J2EE的架构。估计是一帮ERP工程师照猫画虎做出来的。J2EE不是不能用来做电子商务，有些网站还做的很成功。但是不做任何优化，直接就敢拿J2EE做ERP的架构去做大规模电商的，这就是找死了。尤其是某些ERP严重依赖于Oracle，业务逻辑根本就是用Oralce写的，用J2EE封装了一个壳子。这种就更麻烦。&lt;/div&gt;
&lt;/p&gt;&lt;/div&gt;
&lt;div&gt;    目前还不能确定铁道部订票网站到底是什么情况，不过可以确定的是，这个网站的状态在未来几天内还会继续恶化。搞不好到一定程度就直接没法用，或者被铁道部直接关闭网站一段时间了，需要订票的同学最好尽早想办法。&lt;/div&gt;&lt;/p&gt;</description>
	<pubDate>Tue, 10 Jan 2012 23:25:56 +0000</pubDate>
</item>
<item>
	<title>@shell909090: 两天的生活</title>
	<guid permalink="False">http://shell909090.com/blog/?p=2058</guid>
	<link>http://shell909090.com/blog/2012/01/%e4%b8%a4%e5%a4%a9%e7%9a%84%e7%94%9f%e6%b4%bb/</link>
	<description>&lt;p&gt;    我刚刚看了酷壳上的&lt;a href=&quot;http://coolshell.cn/articles/6346.html&quot; target=&quot;_blank&quot;&gt;一篇文&lt;/a&gt;，讲的是女程序员的故事。然后我准备说个无关的故事——数一数我两个典型的日子，2012年的1.3和1.4。这两天，一天是休假最后一天，一天是工作第一天，又刚刚过去，所以我还记得。听上去没什么关系，你听完就知道联系了。
&lt;div&gt;
&lt;div&gt;    1.3日&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;8:30 早上8点半就醒了，工作时间醒习惯了，睡不着了。起来洗脸刷牙开机煮饭——是的，老婆暂时回娘家，我要自己烧饭。（吐槽一下，程序猿婚后还是得学做饭）半个多小时后，大概吃喝完毕，开始处理邮件。&lt;/p&gt;&lt;/div&gt;
&lt;div&gt;9:00 从九点到十一点，处理了所有的邮件，回了blog上的评论，顺便把整个广西游玩过程写成blog，大概4500-5000字。&lt;/div&gt;
&lt;div&gt;11:00 从网络上买点东西，然后继续做饭——水饺。&lt;/div&gt;
&lt;div&gt;12:00 吃完东西，开始研究hash冲突漏洞，大概研究到下午三点。收集了一下相关的问题，大致读了一下paper，包括squid上可能出现的情况什么的。把基本问题写了个blog。&lt;/div&gt;
&lt;div&gt;15:00 给老婆发个消息，看看醒了没，给老妈发个消息报平安，收拾一下家里，大概花了半小时。给外婆打个电话说晚上去吃饭。然后开始健身。三组动作重复四次，总共半个小时。&lt;/div&gt;
&lt;div&gt;16:00 去京东和淘宝上买点东西，看到有音箱，想起来家里的播音系统和视频系统还没有搞定。于是开始研究linux下的视频系统。&lt;/div&gt;
&lt;div&gt;15:30 外婆打过来问什么时候去吃饭，出门去吃晚饭。&lt;/div&gt;
&lt;div&gt;20:00 晚饭回来，装吃的，做家务。&lt;/div&gt;
&lt;div&gt;20:30 看了一下，又是一堆邮件和评论，继续处理评论。&lt;/div&gt;
&lt;div&gt;21:00 hash冲突需看一下python源码，然后写一个程序验证一下，发现maillist里面的过程有点问题。发个邮件过去确认一下，然后接着看了一下相关部分的python源码，三个版本。&lt;/div&gt;
&lt;div&gt;23:00 看会动漫，然后洗澡。顺便说一下，最近在跟《便当》。&lt;/div&gt;
&lt;div&gt;00:00 确定似乎要看一下论文，翻了一下论文，大概搞明白了什么意思。不过差不多一点了，该上床了。&lt;/div&gt;
&lt;div&gt;1:00 在床上玩手机，安装一下各种程序，看点动漫，遂觉。&lt;/div&gt;
&lt;div&gt;    共计如下：写游玩过程的blog和整理相片两小时，研究技术和写程序六个半小时。&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;    1.4日&lt;/div&gt;
&lt;div&gt;8:10 开始起床&lt;/div&gt;
&lt;div&gt;8:20 努力起床&lt;/div&gt;
&lt;div&gt;8:30 起床（没老婆的日子里，闹钟要提早20分钟，不然会迟到），洗脸刷牙做早饭吃饭上班，路上听两首歌，处理一下私人邮件。&lt;/div&gt;
&lt;div&gt;9:30 到公司，开始处理各种邮件，开始解决bug #600。&lt;/div&gt;
&lt;div&gt;10:00 bug #600验证出了问题，等待测试验证，开始写cmdb项目的映射部分代码。&lt;/div&gt;
&lt;div&gt;11:00 hash那里想到一点问题，写个代码验证一下。&lt;/div&gt;
&lt;div&gt;11:30 吃饭了，hash那个问题可以走通，不继续写了。&lt;/div&gt;
&lt;div&gt;13:30 午觉醒来，开始继续cmdb的代码。&lt;/div&gt;
&lt;div&gt;14:00 测试验证出了bug #600的情况，开始修正问题，并出补丁。&lt;/div&gt;
&lt;div&gt;14:30 开始写年终总结报告&lt;/div&gt;
&lt;div&gt;15:00 继续cmdb的映射代码&lt;/div&gt;
&lt;div&gt;16:00 健身一下，处理一下自己的邮件&lt;/div&gt;
&lt;div&gt;16:30 从淘宝和京东上买了点东西&lt;/div&gt;
&lt;div&gt;17:00 继续cmdb的映射代码处理&lt;/div&gt;
&lt;div&gt;18:00 本来应该去健身的，没带衣服，算了，吃了饭回家自己健身去&lt;/div&gt;
&lt;div&gt;19:00 开始做家务&lt;/div&gt;
&lt;div&gt;20:00 开始研究mp3文件格式&lt;/div&gt;
&lt;div&gt;22:00 健身，WTF&lt;/div&gt;
&lt;div&gt;23:00 洗澡看动漫咯&lt;/div&gt;
&lt;div&gt;0:00 突然有个人问到如何设计一个架构，自动的识别处方，并且按照一定规则报警。大概聊了一下想法&lt;/div&gt;
&lt;div&gt;1:00 聊不动了，去床上玩手机，看动漫&lt;/div&gt;
&lt;div&gt;    共计如下：bug #600一个小时。cmdb三个小时。hash半个小时。mp3格式两个小时。&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;    一天休息在家，技术相关花六个半小时，一天工作，技术相关花六个半小时。今天晚上参加聚会，基本上算是半和技术沾边的，估计一天又是六七个小时在技术上。去掉各种杂务，加上零散时间利用手机看资料，大概一年的每一天，包括出去玩，都平均有六个小时在技术上。一年2160小时，五年就是10000小时。&lt;/div&gt;
&lt;div&gt;    我觉得，能坚持这个量，做的事情又不是无用功，坚持五年以上。这个人，无论男女，年龄老少，都可以做程序了。有这种积累，不管你是男是女，漂不漂亮，都不会有人歧视你。当然，有些MM，如果没有这个积累，不少程序员也会很友善，但是脑子里的念头和程序无关。&lt;/div&gt;
&lt;div&gt;    我认得的不少人，基本都保持这个量，有些人已经保持了十五年以上。如果你觉得他很拽，记得那是有理由的。&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;    也许有不少MM觉得自己辛辛苦苦在男人扎堆的程序员圈子里面晃荡，还要受到各种歧视。我不知道其他地方是如何实现“歧视”这种东西的，就我认识而言，有点技术的MM比男程序员更吃香，也更容易受到优待——无论漂亮不漂亮。一个MM来讲一个技术毕竟比一个大老爷们更加赏心悦目一些。我们是IT圈，不是gay圈（注意，我没有歧视后者的意思，只是取向不同）但是我认识的大部分“程序员”MM，其实只能算会写程序的普通MM。真正算的上有程序员资质的，不会超过20人。真正说入门了，可以当做一个圈子里面的人来谈谈了，不会超过一只手。&lt;/div&gt;
&lt;div&gt;    我有歧视他们么？我不觉得，至少我不会比同等技术的男性更加亏待他们，当然，也不一定会善待她们。实际上，我觉得多数程序员MM除了姨妈来了需要请假，以及生儿育女需要产假外，不需要什么额外的优待。做程序不是请客吃饭。如果说因为“MM必须要睡美容觉”，或者“MM不需要处理技术细节”，“有问题可以找GG做”，“我需要谈恋爱”，就不做的话，那我觉得是自己的问题，怪不得我鄙视你们。&lt;/div&gt;
&lt;div&gt;    有不少MM还是很强悍的，有几个我觉得比我还强。但是大多数MM，我即使没有看不起你们的意思，也没法和你们聊到一起去。这不是性别的问题——如果对着一个男士，我讲到挑战-回应验证模式，并且解说过程后，还是一脸茫然的，我会让他直接走人。对着女士我不大好这么直接，所以一般是叫HR喊你们走人。如果你觉得这样冒犯了你，很抱歉，下次我会亲自请你走的。&lt;/div&gt;
&lt;div&gt;    以上的大多数话不仅针对MM，也针对所有的男性程序员——除了你们没有姨妈（或者说不需要为姨妈请假）。你们面临比MM更多的挑战，即使做出同样的东西，MM得到的关注永远比你多。如果你觉得不公平，可以去一趟泰国，我相信你得到的关注会比MM更多。（特别说明一下，我也没有歧视变性人的意思，我觉得应当尊重别人努力改变自己先天情况和后天心理差异的努力）&lt;/div&gt;
&lt;div&gt;    听起来很苦逼？没错，IT界是个摧残人的行当。在IT界，你会找不到女朋友/男朋友，找到了也没时间经常出去玩，很容易分手，导致变成宅男/女。经常在家，不注意保养也不注意形象的结果就是，出现在朋友面前的永远是一张吸血鬼或者熊猫妆。对MM更加残酷的是，男程序员还可以帮别的MM修电脑——虽然经常是好人当到老，坏人床上搞。但是作为一个MM，如果你胆敢去任何一个梦中情人家里修电脑——你就等着出局吧，除非对方也是个苦逼程序员。我建议你们可以努力练习烟熏妆，掩盖掉黑眼圈的同时说那就是黑眼圈，是因为昨天你们可恶的老板让你们加班导致的。然后假装晕倒，说今天修bug早饭还没吃。通常这招的成功率比较高一点，大部分GG会顿生呵护之心，嘘寒问暖买吃买喝。&lt;/div&gt;
&lt;div&gt;    但是注意，对着老板使用这招是无谋的自杀行为，即使你昨天炒了一晚上炒饭（咳咳），或者是姨妈光临心情烦躁，这些都和老板没有关系。你可以为姨妈请假，但是不可以上班不干活。只要来了，就必须做事，修bug，研读材料，解决问题。如果某个严重问题落在你身上，即使现在拉肚子在厕所里面不能出来，也要一边打电话一遍用笔记本把问题搞定了。&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;    如果你觉得我是在说程序员的悲崔生活，你可以转头看看医学院学生的生活，天下医科生大都苦逼。除去少部分的天才，和有个好出生的人，大部分的人生是自己选择的。我现在过的比别人差，是因为1.我不够努力，2.我运气不好。前者无法埋怨别人，而后者也不行。&lt;/div&gt;
&lt;div&gt;    上面说到程序员的资质，什么叫做资质？实际上这个问题很有趣。就一个问题，不同的人会看到不同的东西。看到一包中华烟，美术院的学生会想到图案设计，程序员会想起加班，销售员会想起要送礼。而看到我上面说的那个hash碰撞漏洞，社会学者会想到it业的发展，销售会想到自己在卖的产品和竞争对手的产品。如果你想到的是这个东西为什么会实现，还有哪些东西有问题，并且在家里休息的时候也会做几个实际的例子来玩一玩的话。&lt;/div&gt;
&lt;div&gt;    OK，你就挺有程序员资质的。&lt;/div&gt;&lt;/p&gt;</description>
	<pubDate>Tue, 10 Jan 2012 19:39:23 +0000</pubDate>
</item>
<item>
	<title>@shell909090: 广西游记下</title>
	<guid permalink="False">http://shell909090.com/blog/?p=2056</guid>
	<link>http://shell909090.com/blog/2012/01/%e5%b9%bf%e8%a5%bf%e6%b8%b8%e8%ae%b0%e4%b8%8b/</link>
	<description>&lt;div&gt;阳朔&lt;/div&gt;
&lt;div&gt;    我们前后两次路过桂林——先从南宁坐过夜火车到桂林，吃过一碗桂林米粉马上上船去阳朔。桂林米粉就是普通的煮米粉，然后自己加上各种配料。当地人是干拌，吃完加点汤。我们吃就是加汤吃，味道很鲜，但是没有老友粉那么特色。我怀疑外面卖的桂林米粉多是因为这东西比较容易操作。作为师傅，只要配料和汤料准备完，剩下的就是小碗煮米粉而已。人多的时候也可以很快操作。老友粉和螺蛳粉就没那么快的操作速度了。&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;     从桂林到阳朔的船是旅行的重点。上船先买票，到了船上还可以包包厢。我建议——最好是多人去，直接包一间包厢，6人间600，送一套午餐。这样既不吵，而且中午吃的也会比较好一点。我们看过他们的普通午餐，根本就是白煮白菜加上米饭！上层的风景非常好，可惜我们去的不是时候，漓江正好处于枯水季。不是上游水库放行部分水流的话，我们今天的船根本一步都开不出去。而且当天略有阴雨，看漓江风光的时候朦朦胧胧。往好了说是别有风味，往糟糕了说就是白干一场。不过这次有几处，江面上开阔大气，两旁山水气势磅礴，船头上又没有什么人，感觉这几处还是值得的。&lt;/p&gt;&lt;/div&gt;
&lt;div&gt;    阳朔据说是最早的旅游酒吧聚集地，资本主义的桥头堡——比丽江早多了。我们看了看，不算大，只有三条街的大小。看看点评，里面最热门的是“谢大姐啤酒鱼”，出门发现谢三姐啤酒鱼，后面什么刘大姐张大姐全都站出来了，李鬼不但比李逵还多，而且多多了。我们找正宗店家找了半天，吃完还没法肯定自己吃的是正宗的。不过东西不错，啤酒鱼中午也有吃，是用啤酒来烧鱼，而不是清水。鱼的味道很赞，和中午效果完全不同——中午连鱼鳞都没有去干净。&lt;/div&gt;
&lt;div&gt;     我们吃东西的要点是——找一家，少点点，好吃再加，不好吃付钱去别处。因此啤酒鱼垫个肚子，我们又去了点评上的第二家——黄记玉米汁。讲到这里，感觉这趟游玩纯粹变成吃喝之旅了，没办法，两个吃货出门，还能指望点啥呢？&lt;/div&gt;
&lt;div&gt;    玉米汁不错，据说浦东也有分店，就在八佰伴旁边。好像是用煮过的玉米，用豆浆机打碎，滤过其中的植物纤维，只剩下植物蛋白的粘稠溶液。店里的特色是准备了很多便利贴，让客人自己写各种东西贴在墙壁上作为装饰。我们去的时候，墙壁上已经贴了一层又一层的便利贴了。&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;黄姚&lt;/div&gt;
&lt;div&gt;    黄姚不大不小也算是个旅游城市，不过名气上远没有阳朔和丽江那么响亮。猫咪不知道怎么把这个地方挖出来的，绝对赞，强烈推荐。我们去的时候还算是淡季，街道上的人不多不少。看着热闹，又不会拥挤。据说每到逢年过节，春秋风光明媚的时候，镇子上的民宿和镇口的旅馆全部爆满——镇口有一家四星级旅馆。由此可见这地方值得一去。&lt;/div&gt;
&lt;div&gt;    黄姚古镇是一个很小的镇子，离桂林大概3小时的车程。镇上水土很好，旅游业小有规模，又没有像阳朔和桂林那么夸张，感觉进去好像进了义乌一样。当地的小巷子还是很原生态的，大概有一半不到改成了商店和民宿，另一半还是普通民居。巷子四通八达，山水相连风光秀丽。据说有不少电视剧都是在此取景，因此墙上有很多民国年代的招贴画，像是回到那个年代一样。镇子上特产豆腐和豆豉（都是豆制品哈），尤其是其中一家的姜糖水豆腐花，超级赞。豆腐白花花，入口即化，姜糖味道很明显。一碗两元，一定要吃。&lt;/div&gt;
&lt;div&gt;    镇子白天进去是收门票的，晚上就不收钱了，随便进。住民居，吃农家饭，都随意。这里的农家饭真的是农家，我们在前厅吃饭，一墙之隔就传来小孩的哭声和笑声，门外还有只黄狗，每次有人经过，就汪汪的叫起来。我们吃的鸡是自己挑的，走地鸡——不走也不行啊，这里根本没有专门的养鸡器具，晚上都是关在一个小笼子里面。笼子顶上还有个洞，居然有一只鸡从里面跳了出来。行，公鸡中的战斗机，就是它了。&lt;/div&gt;
&lt;div&gt;    先上的是一道扣肉，用芋艿和五花肉烧的。热的时候很香，冷一点就不好吃了。然后是枸杞梗烧鸡杂鸡血什么的，用枸杞梗烧汤是这里的常态，我们两顿都吃到了这样的汤。鸡肉果然鲜美好吃，我们基本干光——剩下的骨头就喂了前面的阿黄。他倒是很挑剔，好吃的吃，不好吃的就不吃了。一点不像我们后来碰到的一只在路上的狗，给什么吃什么。&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;桂林&lt;/div&gt;
&lt;div&gt;    桂林基本就乏善可陈了，我们只在桂林停留了半天，而且还没吃到什么好东西。&lt;/div&gt;
&lt;div&gt;    中午的老字号米粉怀疑是李鬼店，汤头不鲜，而且免费的料太辣。辣不要紧，关键是一点都看不出，而且吃下去过一会才辣起来。我们一行人全都跑出来买水喝，喵舌头还吐个不停——我说这家原来是做辣酱出身的吧。下午去了象鼻山——既然来了，总不能不去吧。象鼻山现在在枯水季，所以不算很好看。然后我们到正阳路步行街逛了一下，回来吃了一碗螺蛳粉。螺蛳粉其实里面没有螺蛳，是用螺蛳肉煮汤，然后放酱料做的。感觉和老友粉非常类似，只是不放酸笋，略有差异。如果去柳州，记得吃上一碗，看看差异。&lt;/div&gt;
&lt;div&gt;    OK，广西之行基本就是这个样子，如果你也要去，不妨参考一下。另外补充两个值得去的地方，七星山和龙脊梯田。这次我们时间有限，未能成行，非常遗憾。&lt;/div&gt;</description>
	<pubDate>Sun, 08 Jan 2012 18:24:51 +0000</pubDate>
</item>
<item>
	<title>@shell909090: 广西游记上</title>
	<guid permalink="False">http://shell909090.com/blog/?p=2054</guid>
	<link>http://shell909090.com/blog/2012/01/%e5%b9%bf%e8%a5%bf%e6%b8%b8%e8%ae%b0%e4%b8%8a/</link>
	<description>&lt;p&gt;    说是游记，大概会写成一笔流水帐吧。我写东西大多数情况下，信息多于修饰，一贯如此。
&lt;div&gt;
&lt;div&gt;北海&lt;br /&gt; 
&lt;div&gt;    头天飞的北海，天气不错，气候宜人，下了飞机我就脱掉了棉裤棉衣。北海位于广西最南端，几乎是中国大陆最南方的城市，规模并不大，冬暖夏凉气候宜人。我们住在侨湾那里，听当地人说，是当年东南亚排华的时候，从国外逃回的华侨，当地政府在这里安置，形成的村落。所以当地居民很多会说越南语，而且很多东西上标注的都是泰文或者越南文。这里离著名的北海银滩并不很远，打车15就到。&lt;/div&gt;
&lt;div&gt;    银滩其实没有想象中的好，主要是因为现在是冬季，海水虽然不刺骨，但却不能游泳，因此来的人几乎没有。据当地居民说，这里在旺季的时候，几乎全是人，完全无法游泳。银滩的海浪冬夏不尽相同，不便评价。但是她的沙滩非常好，沙子洁白细腻，踩上去一点都不痛，粘在脚上拂拭不去，干了还是薄薄一层。不仅远离海岸的地方如此，而且海岸边上的沙子也如此，明显是冲积形成的。厦门的白城更加商业化一些，一年四季都有人，卖小吃的，栈道上观景的，冲淡的，始终不断，但是沙子是个先天劣势。厦门远离海岸的沙子是细沙，但是岸边的就是粗砂，踩上去如同足底按摩一般，明显后面的沙子是运过来的。但是银滩在淡季的时候，冲淡的，卖东西的，基本都没有人经营，明显只做一个季度的生意。&lt;/div&gt;
&lt;div&gt;    我们去了南珠宫买了点珍珠，这里的珍珠非常好，属于当地特产。珍珠的常识是，海珠比淡水珠好。但是海珠更加圆滑透亮，不适合做胸针什么的，大部分都是项链手链。珍珠项链又不适合每个人，所以要不要买，见仁见智。我们买的是淡水珍珠胸针，也不算贵，就是买着玩玩而已。猫咪倒是对这里的甘蔗汁更加感兴趣，喝过一次后念念不忘，吵着要喝。这里的甘蔗是青皮甘蔗，现场压榨。汁液鲜甜，在上海可是很难喝到哦，来的不妨买一杯尝尝。&lt;/div&gt;
&lt;div&gt;    侨湾那里也有个海滩，和银滩差不多，只是名气没那么响。我们在旁边饭店吃的晚饭，贵死了！！！不过饭店外的风景甚好，我还抓了好几张不错的夕阳，算是心理平和点。&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;    从北海坐火车到南宁只需要三个小时不到，不过一天只有两班火车。与此相对的，火车站修的广大气派，不知道是干什么用的。照我说不妨学学杭州的火车站，把上面的部分改建成商业建筑，还能充分利用。列车上一点让人不爽的地方就是，上去后一趟火车3个小时，推销东西的有四批。一个卖毛巾的，一个卖鞋油的，一个卖牙刷牙膏的，一个卖速算书的。从头卖到底，五分钟清静都没有，猫咪想睡觉都睡不着，铁道部最近穷疯了还是怎么？&lt;/div&gt;
&lt;div&gt;    火车上我们对面的一对老头老太是北京人，石油部的，退休了到处玩。老爷子心脏有问题，所以在气闷的火车上非常不舒服。问老太太为啥年纪这么大了还到处跑，老太太说，老爷子心脏不好，装了支架，闷在家里不痛快。出来和老朋友见个面，顺便在北海休养休养。北海气候宜人东西便宜，他们住了一个月了。说着呢，老爷子散步好久没回来，我跑去厕所敲了半天门，没开。刚说要不要找列车员开门，老爷子回来了。他去后面车厢上了个厕所，顺便透透气。没事我就准备回去和老太说一声，老爷子继续往前走。过一会，老爷子从前面绕回来了——他原本倒是想回座位，可是找不着座位在哪了。我们的火车上下两层，他光在上面找，是找不到。我碰到了他，以为想继续散步，也没拉他回来。&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;南宁&lt;/div&gt;
&lt;div&gt;    我们只在南宁呆了半天，但是对南宁的夜市印象非常深刻。除掉下午去了一趟广西博物馆，剩下的时间就是吃吃喝喝。先是打油茶，狗肉（都是好东西啊），后来还有一个艾粑粑。打油茶是当地特产，用糯米脂肪和茶打出来的一种饮料，具体可以自己百度。我喝喝感觉口味一般，味道不算好也不算糟。艾粑粑是用艾草汁做的一种糯米食品，大概就是没有馅的艾草青团拍扁。不过这年头还有哪里有正宗艾草青团？&lt;/div&gt;
&lt;div&gt;    夜市里面吃到的各种奇奇怪怪的东西就多了去了，我甚至在里面看到了整只的鳄鱼和鲨鱼。我们首先吃的烧烤，旁的不用细说，里面最特殊的就是猪鞭，平时烧烤这东西可没有当成鸡翅一样在卖吧。然后还有南宁特色，老友粉。广西这里偏爱米粉，而且各地做法不同。到桂林要吃桂林米粉，到柳州要吃螺蛳粉，到南宁就要吃老友粉了。这个是用酸笋和各种料来烧的米粉，味道酸酸馊馊，据说很多人吃不惯。我吃吃很好吃啊，和北京的豆汁完全不是一个概念。&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;    后面有一碗牛杂汤，是用各种牛的下水熬的汤。猫咪不吃内脏，所以让我来吃。我貌似吃到的是牛肺，也好，润肺通气。然后，今日重点登场——王老吉。我们是在一个糖水铺里面看到王老吉的，当地朋友立刻就一脸暧昧的笑容。我们点上各种糖水，然后点了一杯王老吉来品尝。我第一个下手，一口下去——我去啊，这玩意苦的厉害。不过还好，当年我也是喝了好几年中药的，脸上神色不变，点点头，恩，这玩意有点苦。还记得那个笑话么？三个傻瓜摸烧红的秤砣是什么味道的——傻喵马上说，是么是么？多苦啊，我尝尝。恩，很好很好，马上看到某只喵像被掐住喉咙一样的扑腾——我趁机喝掉她的糖水，缓解一下嘴巴里的味道。&lt;/p&gt;&lt;/div&gt;
&lt;div&gt;    后面一帮不信的人，前仆后继的相继中招。这玩意的味道不但苦，而且从喉咙里面不断散发出来，根本不是喝口糖水就能压掉的。这是当地正宗凉茶，可不是外面卖的王老吉那种水货。当地朋友是感冒，当作药喝的。我们几个就傻傻（好吧，里面也许有一点点我的因素）的分别中招。&lt;/div&gt;
&lt;div&gt;    最后一个吃的是南宁的小馄饨，这个很赞。里面放的丸子是牛肉丸，打的很彻底，很Q很有弹性。馄饨包法很特殊，是用皮子卷出来的，馅料粉红色，煮开后有嚼劲。就是吃的时候有点苦——这个绝对是王老吉惹的祸。总体来说，南宁之旅还是留下了很深刻的印象的——东西好吃！！！&lt;/div&gt;&lt;/p&gt;</description>
	<pubDate>Wed, 04 Jan 2012 17:46:45 +0000</pubDate>
</item>
<item>
	<title>@khsing: 年复一年，2011</title>
	<guid>https://blog.khsing.net/?p=466</guid>
	<link>https://blog.khsing.net/2012/01/say-goodbye-to-2011.html</link>
	<description>&lt;p&gt;2011过去三天了，今天我才拖着来写去年的事情。&lt;/p&gt;
&lt;p&gt;2010年总结的时候我给自己的2011定了几件事儿，先看看：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;继续克服拖沓症。
&lt;p&gt;有所改进，但是不够，拖沓的事情还是有不少。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;继续学习科学技术，数学是重点，算法和数据结构要有个交待。
&lt;p&gt;这个进展很小，没有学进去太多。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;学车，在党同意并且运气好的情况下，希望能抽个号，买个车。
&lt;p&gt;车是11月学完了，还撞了一次车。但是党还没通过我的申请，有一个暂住证没办，1月8号以前搞定一个，争取1月的奖池里有我。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;继续学习外语，把重点放在英语上，得空的时候顾及一下法语。
&lt;p&gt;英语的学习今年还是可以的，基本上是可以听的懂了，但是词汇量还是太小了，语法和写作是接下来的重点。法语已经忘的连10以内的数字都数不完了。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;带着老婆孩子旅个游，目的地未定。
&lt;p&gt;中秋去了一趟厦门，总体的感觉还是不错的。我也从很远的地方看到了“三民主义，统一中国”的标语（实际上是拍的照片回来才看清楚，远处只看到了一个大的标语牌子上有字）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;得空儿回老家办二代身份证和护照，这是淫威啊。
&lt;p&gt;5.1的时候回去了一趟，护照、身份证、港澳台通行证都一起办完了。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;计划外的事情是：2月的时候换了一次工作。&lt;/p&gt;
&lt;p&gt;2012年，我对自己有一些要求，也有一些期许。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;继续和拖沓症作战&lt;/li&gt;
&lt;li&gt;利用业余时间把自己的小项目搞出个眉目来&lt;/li&gt;
&lt;li&gt;出国旅游一次&lt;/li&gt;
&lt;li&gt;考一次雅思，争取到6分&lt;/li&gt;
&lt;li&gt;每2个月读1本书,其中1/3要是英文的&lt;/li&gt;
&lt;li&gt;拼RP，买车&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;希望年底的时候，不会对自己这一年的作为失望。&lt;/p&gt;</description>
	<pubDate>Wed, 04 Jan 2012 14:42:02 +0000</pubDate>
</item>
<item>
	<title>@shell909090: 哈希冲突漏洞的原理和对策</title>
	<guid permalink="False">http://shell909090.com/blog/?p=2052</guid>
	<link>http://shell909090.com/blog/2012/01/%e5%93%88%e5%b8%8c%e5%86%b2%e7%aa%81%e6%bc%8f%e6%b4%9e%e7%9a%84%e5%8e%9f%e7%90%86%e5%92%8c%e5%af%b9%e7%ad%96/</link>
	<description>&lt;p&gt;    cpug上面最近在讨论一个严重级漏洞，漏洞的相关资料如下： &lt;span&gt;&lt;a href=&quot;http://www.kb.cert.org/vuls/id/903934&quot; target=&quot;_blank&quot;&gt;ERT-VN:VU#903934&lt;/a&gt; &lt;/span&gt; &lt;a href=&quot;http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-4815&quot; target=&quot;_blank&quot;&gt;CVE-2011-4815&lt;/a&gt;&lt;span&gt; &lt;/span&gt;&lt;a href=&quot;http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-3414&quot; target=&quot;_blank&quot;&gt;CVE-2011-3414&lt;/a&gt;&lt;span&gt; &lt;/span&gt;&lt;a href=&quot;http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-4838&quot; target=&quot;_blank&quot;&gt;CVE-2011-4838&lt;/a&gt;&lt;span&gt; &lt;/span&gt;&lt;a href=&quot;http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-4885&quot; target=&quot;_blank&quot;&gt;CVE-2011-4885&lt;/a&gt; 
&lt;div&gt;
&lt;p&gt;     上面主要讨论的是这么一个概念，当用户post一个数据，而且这个数据又是一个form的时候，应用需要先将form解析为dict，然后才能方便的使用。例如a=1&amp;amp;b=2，可以解析为{'a':'1', 'b':'2'}。之所以1和2是字符串，是因为只有用户自己才清楚这个数据的类型。&lt;/p&gt;&lt;/div&gt;
&lt;div&gt;    通常情况下，这个form的key都是随机的，生成的hash碰撞概率很低，因此dict的默认实现——hash table没什么问题。但是当攻击者恶意构造数据的时候，情况就完全不同。我们首先讨论一下hash table的实现——开链法和二次探测法。&lt;/div&gt;
&lt;div&gt;    所谓开链，就是指对所有同余hash，将他们挂到一个hash表项上，形成一个链表。而所谓二次探测，就是在第一次hash冲突后，再进行一次hash，作为第二地址。&lt;/div&gt;
&lt;div&gt;    开链法对碰撞冲突是有先天缺陷的，因为同余碰撞的构造远比hash碰撞的构造简单。假定hash table有11个表项，那么平均11次尝试就可以得到一个元素，和原始元素hash同余。如果选用这样的恶意key序列，在执行构造的时候，hash table就退化为了链表。链表的插入复杂度是O(n^2)级的。而作为攻击者，为了获得n个hash同余对象，所需消耗的复杂度做如下估量。首先考虑hash table length和n同阶，因此以n作为hash table长度。这样每n次尝试就可以获得一个恶意元素，获得n个元素的复杂度为O(n^2)级。&lt;/div&gt;
&lt;div&gt;    也就是说，即使是sha256这样强的hash算法，只要保证哈希函数特性，对同样的值得到同样的哈希，就无法保证开链法的安全。&lt;/div&gt;
&lt;div&gt;    而二次探测法对这个是有先天抵抗的，二次探测法的第一次碰撞并不难构造，但是第二次哈希后依然保持同余的构造难度就由n增加到了n^2，多次碰撞的构造难度以此类推。虽然我没有完整的计算过这个值，但是猜测难度量级应当是O(n*n^n)级别的。这个级别基本就不用玩了——前提是哈希算法必须是安全的。&lt;/div&gt;
&lt;div&gt;    由于为了节约计算过程，因此python和php的hash算法都没有采用md5之类的高散列算法，而是一个很简单的算法。我摘抄一下Python2.7.2中的这段代码。 &lt;a href=&quot;http://shell909090.3322.org/pycode/shell909090@gmail.com/python_string_hash.c&quot; target=&quot;_blank&quot;&gt;python_string_hash.c&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;static long&lt;/div&gt;
&lt;div&gt;string_hash(PyStringObject *a)&lt;/div&gt;
&lt;div&gt;{&lt;/div&gt;
&lt;div&gt;    register Py_ssize_t len;&lt;/div&gt;
&lt;div&gt;    register unsigned char *p;&lt;/div&gt;
&lt;div&gt;    register long x;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;    if (a-&amp;gt;ob_shash != -1)&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;         return a-&amp;gt;ob_shash;&lt;/p&gt;&lt;/div&gt;
&lt;div&gt;    len = Py_SIZE(a);&lt;/div&gt;
&lt;div&gt;    p = (unsigned char *) a-&amp;gt;ob_sval;&lt;/div&gt;
&lt;div&gt;    x = *p &amp;lt;&amp;lt; 7;&lt;/div&gt;
&lt;div&gt;    while (&amp;#8211;len &amp;gt;= 0)&lt;/div&gt;
&lt;div&gt;        x = (1000003*x) ^ *p++;&lt;/div&gt;
&lt;div&gt;    x ^= Py_SIZE(a);&lt;/div&gt;
&lt;div&gt;    if (x == -1)&lt;/div&gt;
&lt;div&gt;        x = -2;&lt;/div&gt;
&lt;div&gt;    a-&amp;gt;ob_shash = x;&lt;/div&gt;
&lt;div&gt;    return x;&lt;/div&gt;
&lt;div&gt;}&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;    按照&amp;lt;&lt;a href=&quot;mailto:python.leojay@gmail.com&quot; target=&quot;_blank&quot;&gt;python.leojay@gmail.com&lt;/a&gt;&amp;gt;的计算，以很短的时间，就可以构造出大量同样hash的字符串。既然hash相同，后续的同余不同余就没了意义。不过刚刚我复现了一下他的结论，在64位下有点问题。源码中是这么定义的。&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;typedef struct {&lt;/div&gt;
&lt;div&gt;    PyObject_VAR_HEAD&lt;/div&gt;
&lt;div&gt;    long ob_shash;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;static long&lt;/div&gt;
&lt;div&gt;string_hash(PyStringObject *a)&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;    注意两者都是用的是long。C在64位下，long的长度是64位的。按此说，哈希碰撞的概率会进一步减小。为此我查了一下算法。&lt;/div&gt;
&lt;div&gt;    &lt;a href=&quot;http://www.nruns.com/_downloads/advisory28122011.pdf&quot;&gt;这篇论文&lt;/a&gt;里面提到了meet-in-middle-attack，这是一个以空间换时间的算法。当一个哈希函数可逆，内部状态和输出一样大，并且可以把一个算法分解成两个部分，每个部分使用一半的字符串的时候，可以实行这种攻击。攻击过程首先将算法分解为两部分，一部分计算出中间内部状态，另一部分计算从中间状态到结果。然后由于算法可逆，后半部分可以逆向为由某个固定值，经由一半的字符串，计算出一个中间状态。&lt;/div&gt;
&lt;div&gt;    攻击者首先枚举了第一部分的值和所有的内部状态，并且存入查找表（讽刺的是，这个最好用的就是hash table）。而后枚举第二部分的逆向中间状态，并在查找表中查找。当有对应后，将两部分拼接，就得到了碰撞字符串。&lt;/div&gt;
&lt;div&gt;    穷举的攻击复杂度大概是O(2^n)，而meet-in-middle-attack将复杂度降为了O(2^(n/2))。与此对应的，空间消耗大致是O(2^(n/2))。&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;    python是采用上述哈希算法的二次探测法hash table，由于hash算法很容易找到大量同余字符，因此将这些字符组成一个form数据提交后，服务器在解析为dict的过程中，将消耗大量CPU时间。多次重发，服务器就死机了。&lt;/div&gt;
&lt;div&gt;    作为一个简单的对策，首先请先限制form表单提交的最大长度。冲突表单通常都高达上万条记录，即使一条记录5字节，也有50k大小。常规的表单一般都不会超过4k大小。由这一点可以很快过滤问题。当然，这个前提必须是——你可以先于框架获得处理数据的机会。php似乎是由框架主动完成这个过程的，因此很难对恶意数据直接返回。这使得php成为了本漏洞的重灾区。（这点是由其他人推测得到的，不一定准确，也不代表个人观点）php给出的补丁据说只是限制form最高可以提交100个key，从而规避了这个问题。&lt;/div&gt;
&lt;div&gt;    另一个对策是，对上述的算法使用一个随机值作为初始值，使得客户这里的哈希函数特定和服务器端的特定完全不一致。这使得构造服务器端冲突的概率减少了很多。但是这需要对源码进行修改，因此实行起来并不是那么快。而且同样的计算表明，这个思路还不一定可行。对初始值进行小幅修改后，又很快产生了大量碰撞。&lt;/div&gt;
&lt;div&gt;    最稳妥的对策是，像perl一样，采用&lt;a href=&quot;http://en.wikipedia.org/wiki/Universal_hashing&quot; target=&quot;_blank&quot;&gt;Universal hashing&lt;/a&gt;作为基本算法。这个思路和随机值很类似，但是数学上更加严谨。假定有一组函数H，其中任何两个元素h1, h2，对集合中任何两个元素x, y，h1(x) == h2(y)的概率小于等于1/m，则称这组函数为universal family。其中m为hash目标值空间大小。满足这个条件后，服务器端在单次计算的时候采用同一个函数，可以保证哈希的正常工作，但是客户端无法做出碰撞。&lt;/div&gt;
&lt;div&gt;    从Universal hashing的算法时间来看，这是一个很古老的漏洞了。只是以前大家都没有在意。突然有一天，大家发现——原来世界还是很脆弱的。&lt;/div&gt;&lt;/p&gt;</description>
	<pubDate>Tue, 03 Jan 2012 19:59:57 +0000</pubDate>
</item>
<item>
	<title>@shell909090: 理想的平板</title>
	<guid permalink="False">http://shell909090.com/blog/?p=2050</guid>
	<link>http://shell909090.com/blog/2012/01/%e7%90%86%e6%83%b3%e7%9a%84%e5%b9%b3%e6%9d%bf/</link>
	<description>&lt;ul&gt;
&lt;li&gt;7寸以下宽屏，原因，可以一手拿住。&lt;/li&gt;
&lt;li&gt;300g以内，原因，可以一手拿住。&lt;/li&gt;
&lt;li&gt;厚度1cm以内，原因，拿得舒服。&lt;/li&gt;
&lt;li&gt;10小时续航，原因，一天可以只充电一次。&lt;/li&gt;
&lt;li&gt;3g支持，原因，不支持3g的不叫理想的平板。&lt;/li&gt;
&lt;li&gt;IPS/PLS屏幕，原因，普屏的视角的却有的时候很不爽。&lt;/li&gt;
&lt;li&gt;usb可充电，原因，外部电源续航方便，充电方便。&lt;/li&gt;
&lt;li&gt;支持TF卡，原因，方便。&lt;/li&gt;
&lt;li&gt;USB OTG，原因，可以拖U盘和键盘。&lt;/li&gt;
&lt;li&gt;GPS支持，原因，地图是很重要的。&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;    好吧，我们合并要求起来看看。300g以内10小时续航，目前芯片和屏幕的功耗连电池重量都不够。所以这个无形就要求更加节能和强劲的芯片，还有更加节能的屏幕。同时，这个屏幕还不能比IPS视角差。&lt;/div&gt;
&lt;div&gt;    继续等吧。&lt;br clear=&quot;all&quot; /&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/div&gt;</description>
	<pubDate>Mon, 02 Jan 2012 06:37:32 +0000</pubDate>
</item>
<item>
	<title>@shell909090: 语言的继承和历史包袱</title>
	<guid permalink="False">http://shell909090.com/blog/?p=2048</guid>
	<link>http://shell909090.com/blog/2012/01/%e8%af%ad%e8%a8%80%e7%9a%84%e7%bb%a7%e6%89%bf%e5%92%8c%e5%8e%86%e5%8f%b2%e5%8c%85%e8%a2%b1/</link>
	<description>&lt;p&gt;    出去玩，在阳朔过的新年，随便发点吧。&lt;br /&gt;     我们知道，C++继承了C语言的语法，并且号称完全兼容。实际玩下来，C标准自己也不怎么统一，说基本兼容大家是没异议的。这个给C++带来了无限的好处，从一开始，C++的用户数量和其他语言就不在一个数量级上。《C++语言的设计和演化》一书中说，作者设计出来后没多久，基本没有做宣传，就有无数人给他打电话，用户数量飙升。作为一个新出的语言，即使是Go也没有如此的待遇，这就是继承了C的好处。&lt;/p&gt;
&lt;p&gt;    有好处就有包袱，C++兼容C，出现的包袱也很大。想做GC？想使用智能指针？那就没法兼容C（具体不细说）。此外里面有无数的问题是因为“需要兼容C”而变成一个四不像的。再后来，为了在语言上更进一步，Java继承和吸收了C++的部分语法。这给Java带来好处，也带来问题。&lt;/p&gt;
&lt;p&gt;    继承一个东西的好处，就会带来一定的包袱。这个也同时体现在Zope社区和Python社区里面。Zope3把2直接推倒重来，导致了用户纷纷出走（当然还有别的原因）。从而出现目前Python Web框架满天飞，各自为战的局面。而Python3则是不完全兼容Python2，导致目前上面的可用库依然不足。在Python3.2的时候，几乎是被迫的做了一些前向兼容，来换取用户可接受的过渡。同样，前几天我在说Django的演进的时候，也说过。如果我要做一个jinja版本的Django出来，大家接受度如何？当然，这不代表你无法在Django中使用jinja，不过发行版中不会作为标配。&lt;/p&gt;
&lt;p&gt;    还有什么语言继承和革新的事情？大家不妨想想。自己做的时候，对照一下，谨慎取舍。&lt;/p&gt;</description>
	<pubDate>Sat, 31 Dec 2011 18:03:01 +0000</pubDate>
</item>
<item>
	<title>@delphij: 用 fcgiwrap 来跑 Movable Type</title>
	<guid>tag:blog.delphij.net,2011://2.2144</guid>
	<link>https://blog.delphij.net/2011/12/-fcgiwrap-movab.html</link>
	<description>&lt;p&gt;我的 blog 在之前一直是用 &lt;a href=&quot;http://httpd.apache.org/&quot;&gt;Apache HTTPD&lt;/a&gt; 来作为 CGI 引擎来跑 &lt;a href=&quot;http://www.movabletype.com/&quot;&gt;Movable Type&lt;/a&gt;。在迁移到北美之前，使用两个域名/IP来分别运行静态页面 (lighttpd) 和 CGI 内容。后来因为全面转向 &lt;a href=&quot;http://www.nginx.com/&quot;&gt;nginx&lt;/a&gt;，在迁移过程中改成了使用一个域名、使用 nginx 在前面跑静态页，并作为反向代理来连接后端的 Apache 1.3.x 实例（先前是 Apache 2.2.x，由于这个实例只用来跑 CGI，所以采用了较低版本的 Apache 以节省资源）。&lt;/p&gt;

&lt;p&gt;之前一直有完全停用 Apache HTTPD 的想法，不过一直没有时间去实作。由于 Apache 1.3.x 早已是不再维护的分支，近期发现的 &lt;a href=&quot;http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-3368&quot;&gt;CVE-2011-3368&lt;/a&gt; 虽然和我的用法完全没有关系，但 &lt;a href=&quot;http://www.FreeBSD.org/&quot;&gt;FreeBSD&lt;/a&gt; 的 &lt;a href=&quot;http://www.freebsd.org/cgi/cvsweb.cgi/ports/www/apache13/&quot;&gt;port&lt;/a&gt; 已经被标记为 &quot;FORBIDDEN&quot; 状态，于是最近找时间学习了一下如何在 nginx 上跑这些 cgi。现在，这台服务器已经完全停用 Apache HTTPD 了。&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.nginx.org/&quot;&gt;nginx&lt;/a&gt; 有很多跑 CGI 的办法，但是没有一种是原生的。官方推荐的方法是使用 thttpd，然而大概看了看代码之后发现 thttpd 虽然代码量很少，但不支持使用 Unix socket 连接，而且我只要能支持 FastCGI 接口就好，并不真的需要封好 HTTP，所以改为用 fcgiwrap (ports/www/fcgiwrap)。&lt;/p&gt;

&lt;p&gt;fcgiwrap 没有什么特别的配置。 FreeBSD 上提供了一个 rc.d 脚本，直接拿来用。&lt;/p&gt;

&lt;p&gt;对应的 rc.conf.local 配置如下：&lt;/p&gt;

&lt;pre&gt;
fcgiwrap_enable=&quot;YES&quot;
fcgiwrap_socket=&quot;unix:/var/run/www/fcgiwrap.sock&quot;
fcgiwrap_user=&quot;www&quot;
fcgiwrap_group=&quot;www&quot;
&lt;/pre&gt;

&lt;p&gt;这里没有使用通常的 /var/run/fcgiwrap.sock， 而是单独建立了一级目录 (/var/run/www/），其 owner 用户和组均为 www。上述配置令 rc.d 系统在启动时使用 www 身份，如果不单独建立目录，则系统会无法创建对应的 socket 文件。&lt;/p&gt;

&lt;p&gt;fcgiwrap 信任来自 Web 服务器的路径。下面是告诉 nginx 如何透过 FastCGI 接口传递这些参数：&lt;/p&gt;

&lt;pre&gt;
	location ~ ^/mt(/[^/]*)(/.*)?$ {
		root &amp;lt;此处填写具体的cgi-bin/mt目录&amp;gt;/;
		fastcgi_split_path_info (^/mt/[^/]*)(.*)$;
		include fastcgi_params;
		fastcgi_param GATEWAY_INTERFACE CGI/1.1;
		fastcgi_param SCRIPT_FILENAME $document_root$1;
		fastcgi_param PATH_INFO $fastcgi_path_info;
		fastcgi_param PATH_TRANSLATED $document_root$2;
		fastcgi_pass unix:/var/run/www/fcgiwrap.sock;
	}
&lt;/pre&gt;

&lt;p&gt;去掉原先的代理配置，启动 fcgiwrap，然后稍作测试即可。&lt;/p&gt;</description>
	<pubDate>Fri, 30 Dec 2011 09:15:38 +0000</pubDate>
</item>
<item>
	<title>@delphij: 转发一条新浪微博，关于蒙牛</title>
	<guid>tag:blog.delphij.net,2011://2.2143</guid>
	<link>https://blog.delphij.net/2011/12/post-609.html</link>
	<description>&lt;p&gt;&lt;a href=&quot;http://weibo.com/1497390470/xDVcti67c&quot;&gt;来自&lt;/a&gt;新浪微博：王小山：同意的请转，郑重承诺：拒绝蒙牛一切产品，从我做起，从现在做起：不为蒙牛打工，不使用蒙牛产品，告诉别人蒙牛是垃圾企业，不接蒙牛订单，不接蒙牛广告，不买有蒙牛广告的报纸，不看蒙牛赞助的节目，微博辩论再不说对方&quot;脑残&quot;，只说&quot;喝蒙牛长大的吧&quot;。&lt;/p&gt;

&lt;p&gt;我们也许没有办法改变监管体制，但我们至少可以拒绝那些有问题的企业。监管部门不让它们倒闭，消费者就必须让它们倒闭！请爱惜自己的家人和生命。&lt;/p&gt;</description>
	<pubDate>Thu, 29 Dec 2011 11:00:21 +0000</pubDate>
</item>
<item>
	<title>@delphij: 密码阴谋论</title>
	<guid>tag:blog.delphij.net,2011://2.2141</guid>
	<link>https://blog.delphij.net/2011/12/post-608.html</link>
	<description>&lt;p&gt;大家都喜欢阴谋论，所以今天说个关于密码的。话说，假如你拿到了一个大网站的密码数据库，然后恰好这个数据库里面的密码又都是明文，但这个数据有点旧了，怎么样才能立即得到其中的活跃用户的密码呢？&lt;/p&gt;

&lt;p&gt;假设你可以控制若干家网络公司所使用的网络基础设施，例如事先装了一些监控非法活动的防火墙的话，方法就很简单了：公布这个数据库，或者公布至少其中的一部分，然后做简单的监听就可以了。这个过程不但可以知道他们的新密码是什么，而且可以知道旧密码是否是对的，还可以知道他们的安全习惯如何，要知道，假如没有这个事件，绝大多数人可能正靠着他们的简单密码睡大觉。&lt;/p&gt;

&lt;p&gt;当然，攻击者显然还会注意到，这些网站，以及很多其他网站，多数还都没有对用户做最起码的保护，即使用 https 来保护登录过程。&lt;/p&gt;
        &lt;p&gt;一个显然的预防措施是，每个网站都用不同的、随机生成的密码。最差情况下，丢失一个明文密码的代价仅限于那个网站。&lt;/p&gt;

&lt;p&gt;把密码记在心里是预防密码表被盗走的最好途径。但是记不住怎么办呢？最近几年的研究表明，把这些密码记到纸上是一个还凑合的折衷方案。把密码（显然，不包括与之对应的网站和用户名）抄写在一张作弊条上，放在钱包里；另外留一张放在家里。这种方法要好过密码管理器，原因是很多人并不知道自己被种了木马，而密码管理器可以在受害者毫不知情的情况下把密码表如数交给攻击者，而钱包丢了这种事情通常的人很快都会注意到并及时采取措施。&lt;/p&gt;

&lt;p&gt;作为互联网产品的产品经理还应该考虑什么呢？以下是我想到的几个可以考虑的方面，仅作抛砖引玉：&lt;/p&gt;

&lt;p&gt;第一个，也是非常非常重要的，就是凡是跟用户隐私有关的东西都做最大限度的防护。例如，用户的个人信息只应保存在特定的一组服务器上，用户的密码应该使用带salt的hash存放而无论如何不存明文或加密的明文数据，以及凡是需要显示用户隐私信息，例如用户的真实姓名、地址或者好友关系等等的时候，以及要求用户提交隐私信息的地方都采用 https，注意需要 https 保护的不仅是处理提交的服务器，也同时包括提交表单、图片、CSS以及全部相关脚本所在的全部服务器。&lt;/p&gt;

&lt;p&gt;第二个，是尽可能避免让用户经常进行登录操作。例如，在用户登录时产生两个信任状，其中一个过期时间非常长（假如用户客户端是安全的，这个过期时间可以是一个月甚至一年），而另一个过期时间则较短（几分钟到十几分钟）。使用前一个来向用户展示那些不太涉及隐私的内容（例如查看公开的活动列表、推荐的产品目录、检查是否有新消息以及消息的数量等），而后一个则用来展示需要涉及隐私或确认的内容（例如查看消息列表、处理好友关系、确认订单等）。因为用户每次输入密码都可能是一次安全风险，而且过多要求输入密码会令用户反感。另外，采用统一的集中认证机制，如 OpenID 等，也是值得提倡的方法。&lt;/p&gt;

&lt;p&gt;第三个，是对可疑活动的监视和对用户的提醒。针对北美市场的互联网产品，可以设计在用户使用不同的 IP 登录时进行提醒；针对中国市场的互联网产品，可以在用户采用不同的桌面系统登录时进行提醒。&lt;/p&gt;

&lt;p&gt;第四个，是不要只用密码来做验证，例如，可以集成 Google Authenticator 或类似的东西。&lt;/p&gt;

&lt;p&gt;最后，也是老生常谈的问题，是对登录的速率限制。同一个客户端或同一个用户名在一段时间内做身份验证的速率必须做限制和锁定操作。这个做法的主要目的是防止密码穷举，而对于没有异常行为的客户端或用户要求输入验证码是十分反人类的行为，应尽量避免。&lt;/p&gt;</description>
	<pubDate>Thu, 29 Dec 2011 02:37:19 +0000</pubDate>
</item>
<item>
	<title>@shell909090: 大家帮我验证一下证书</title>
	<guid permalink="False">http://shell909090.com/blog/?p=2046</guid>
	<link>http://shell909090.com/blog/2011/12/%e5%a4%a7%e5%ae%b6%e5%b8%ae%e6%88%91%e9%aa%8c%e8%af%81%e4%b8%80%e4%b8%8b%e8%af%81%e4%b9%a6/</link>
	<description>&lt;p&gt;    今天一个朋友和我聊天的时候，问我，是不是hosts不安全。我说，都不安全。翻墙的话，必须对翻墙服务器的拥有者相当信任才可以。不但要相信人品，而且要相信技术，相信服务器不会被入侵。使用gae的话，服务器要自己组建，否则你无法确定组建者是否会修改代码，加入监控代码再上传。hosts引入的问题是，你自己对自己进行了一遍dns毒化，如果目标本身是错的，你就傻乎乎的跳到了一个攻击者的机器上，而且你的行为使得域名核查不能阻止你犯错——他们也认为这个机器拥有你要去的domain。&lt;/p&gt;
&lt;p&gt;    不过有意思的是他给出的一个例子：&lt;br /&gt;&lt;a href=&quot;https://199.59.149.208/&quot;&gt;https://199.59.149.208/&lt;/a&gt;&lt;br /&gt;    这是用于访问twitter的一个hosts。&lt;br /&gt;&lt;a href=&quot;https://twitter.com/&quot;&gt;https://twitter.com/&lt;/a&gt;&lt;br /&gt;    问题是，两者的授权是不一样的。我在《&lt;a href=&quot;http://shell909090.com/blog/2011/04/%E8%AE%BA%E4%B8%8D%E5%90%8C%E7%B3%BB%E7%BB%9F%E5%92%8C%E5%AE%A2%E6%88%B7%E7%AB%AF%E7%9A%84%E8%AF%81%E4%B9%A6%E7%AE%A1%E7%90%86/&quot;&gt;论不同系统和客户端的证书管理&lt;/a&gt;》里面说过，如果你访问google的时候发现证书是cnnic签署的，你是否觉得可怕。而这次，我发现hosts的证书是GeoTrust签署的，但是我访问twitter的证书是VeriSign签署的。
&lt;div&gt;
&lt;p&gt;    一家网络公司会找两个不同的供应商签名么？我不清楚。chrome的自动验证对这个无效（所以很危险），因为域名和ip对不上。我试过用openssl验证，但是debian的openssl有个bug，我用CApath无法验证任何证书，包括真实的twitter证书。所以我也无法解答这个问题。从IP上看，这个IP到确实是Twitter的。&lt;/p&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;NetRange:       199.59.148.0 &amp;#8211; 199.59.151.255&lt;/div&gt;
&lt;div&gt;CIDR:           &lt;a href=&quot;http://199.59.148.0/22&quot;&gt;199.59.148.0/22&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;OriginAS:       AS13414&lt;/div&gt;
&lt;div&gt;NetName:        TWITTER-NETWORK&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;    不过这不说明任何问题，完全有可能在路由器上把这一地址段定义到了其他设备上，从而实现man in middle。关键是证书——谁可以帮我验证一下这本证书是否有效？&lt;/div&gt;&lt;/p&gt;</description>
	<pubDate>Wed, 28 Dec 2011 09:53:05 +0000</pubDate>
</item>
<item>
	<title>@shell909090: 密码三文的补充</title>
	<guid permalink="False">http://shell909090.com/blog/?p=2044</guid>
	<link>http://shell909090.com/blog/2011/12/%e5%af%86%e7%a0%81%e4%b8%89%e6%96%87%e7%9a%84%e8%a1%a5%e5%85%85/</link>
	<description>&lt;p&gt;    前两天写了两篇关于密码的文章，其实没说什么，都是程序员的常识和经历。实话说比较有意思的是大家的反应。
&lt;div&gt;    一个是，大家为什么纷纷盯上了第一条？我在写的时候，主要考虑的最多的是第五条，就是网站本身方便盗窃其他网站资料，或者为网站本身提供便利。具体可以看某个投诉知乎的帖子。但是来的人几乎无一例外，都在和我讨论第一条。我不知道理由是什么，大家都觉得政府这么值得怀疑么？实际上，除非政府觉得你有资格收集密码，否则基本没有听说密码必须明文存放的潜规则。你想想，你在国内搭建一个小论坛，需要备份明文密码么？&lt;/div&gt;
&lt;div&gt;    上级要求明文密码的过程大概是怎么发生的？我听一个朋友聊天的时候说到，网管部门要他们系统上某个用户的密码原文，还必须是原文。当然，作为管理部门，是不需要解释原因的。他们表示，密码都是md5之后的。做不成，对方也没有什么表示。后来老板说，设计系统的时候，密码就用明文吧。从这个闲扯中反推，我大概能窥见事情是怎么发生的。不过神奇的是，这个简单的事情，怎么会发展成“网管部门有保存明文密码的要求”的，我描述的太模糊了？&lt;/div&gt;
&lt;div&gt;    另一个是无所谓的忧虑。我发现很多过来的搜索都是“哪家银行明文保存密码”，还有朋友加我gtalk问我google是否安全。实话说我觉得大家太多虑了，而且考虑方向还错了。与其考虑谁明文保存密码，不如先无良的假定“你们都是坏人，密码都是明文”。然后再想，我的钱是不是还安全？我的系统是不是还安全？我要不要关注这个安全？你指望对方设计的时候使用了hash，多重hash，salt，还不如指望自己的密码强度足够，而且符合使用规范。&lt;/div&gt;
&lt;div&gt;    密码是什么？从信息学角度说，密码是某个密码空间中的一个随机值。你和服务器约定，提供这个随机值，服务器就验证你的身份。从这个角度说，每两个实体间验证身份都需要一个独立的随机数，而且这个随机数空间还必须够大。现在的主要问题，是大部分人对这个值的选择太过有规律，太过简单，而且更危险的，对所有场合使用同一个值。如果真的需要使用同一个密钥，除非你的密码体系是公钥体系。否则即使是challenge-response模式，也有差分攻击这个问题。&lt;/div&gt;
&lt;div&gt;    另外顾虑google的那位朋友就有点神经过敏了。当年google退出中国的理由是什么？被攻击。作为一个被攻击后，事情没人知道的情况下，反应这么大的公司，无论如何比其他闷声不响的公司更加重视安全，也应当更加安全吧？你们知道索尼的网站也有密码泄露么？你们知道国内网站在这次之前有多少入侵事件么？在事情没有曝光前主动反应的，google是最大，最严重的一家。如果他不可信，我觉得要找另一家可信的公司就更困难了。&lt;/div&gt;&lt;/p&gt;</description>
	<pubDate>Tue, 27 Dec 2011 02:01:11 +0000</pubDate>
</item>
<item>
	<title>@delphij: idprio和rtprio</title>
	<guid>tag:blog.delphij.net,2011://2.2142</guid>
	<link>https://blog.delphij.net/2011/12/idpriortprio.html</link>
	<description>&lt;p&gt;记一笔，没啥特别。&lt;/p&gt;

&lt;p&gt;Unix 系统的分时调度中，nice值（通过 &lt;a href=&quot;http://www.freebsd.org/cgi/man.cgi?query=nice&amp;sektion=1&quot;&gt;nice(1)&lt;/a&gt; 来控制）是管理员告诉调度器的一个参数，这个参数令内核在考虑就绪进程优先级时，根据其值适当增大或减少执行绪的动态优先级。很明显，如果采用抢占式调度，如果执行绪等待时间较长，或者由于某种原因获得了优先级奖励（例如I/O导致的等待），即使有更重要的任务需要执行，内核还是会将这个执行绪调度进来并进行执行；反之，如果执行绪使用的 CPU 很多（计算密集型任务，如压缩等等），即使这个执行绪进行的就是最重要的任务，它仍然可能被置入休眠状态。&lt;/p&gt;

&lt;p&gt;在 &lt;a href=&quot;http://www.FreeBSD.org/&quot;&gt;FreeBSD&lt;/a&gt; 的及时调度 (real-time scheduling) 实现中，增加了32个'及时(realtime)'优先级和32个'闲时调度(idle)'优先级。用户态进程可以通过 &lt;a href=&quot;http://www.freebsd.org/cgi/man.cgi?query=rtprio&amp;sektion=2&quot;&gt;rtprio(2)&lt;/a&gt; 或 rtprio_thread(2) 系统调用来为进程或线程指定这些优先级。这些优先级不会动态调整，故在抢占式调度中可以一直获得时间片，或只有在系统闲时才获得时间片。&lt;/p&gt;

&lt;p&gt;为了方便管理员使用，FreeBSD提供了与之对应的 &lt;a href=&quot;http://www.freebsd.org/cgi/man.cgi?query=rtprio&amp;sektion=1&quot;&gt;rtprio(1)&lt;/a&gt; 和 &lt;a href=&quot;http://www.freebsd.org/cgi/man.cgi?query=idprio&amp;sektion=1&quot;&gt;idprio(1)&lt;/a&gt; 命令。出于显然的安全考虑，rtprio 和减少 nice 值一样需要超级用户权限，而 idprio 默认也需要超级用户权限（目前，持锁执行绪可能由于优先级太低而被抢断，从而导致死锁），但可以通过将 security.bsd.unprivileged_idprio 设为 1 来允许非特权用户使用它。&lt;/p&gt;

&lt;p&gt;典型的用法包括：&lt;/p&gt;

&lt;p&gt;将 Xorg 设为 realtime 优先级，以改善其响应。这个命令必须以 root 身份运行。&lt;/p&gt;

&lt;p&gt;&lt;i&gt;副作用：如果 Xorg 陷入死循环，将没有机会令其终止。&lt;/i&gt;&lt;/p&gt;

&lt;pre&gt;# rtprio 31 -`pgrep Xorg`&lt;/pre&gt;

&lt;p&gt;以 idle 优先级运行 make buildworld。需要以 root 身份运行或将 sysctl security.bsd.unprivileged_idprio 设为 1。&lt;/p&gt;

&lt;pre&gt;# idprio 31 make buildworld&lt;/pre&gt;

&lt;p&gt;对于单机运行的网站来说，也可以用类似的方法来做后台的日志分析处理。&lt;/p&gt;</description>
	<pubDate>Mon, 26 Dec 2011 06:50:18 +0000</pubDate>
</item>
<item>
	<title>@shell909090: geek们在圣诞夜玩什么</title>
	<guid permalink="False">http://shell909090.com/blog/?p=2042</guid>
	<link>http://shell909090.com/blog/2011/12/geek%e4%bb%ac%e5%9c%a8%e5%9c%a3%e8%af%9e%e5%a4%9c%e7%8e%a9%e4%bb%80%e4%b9%88/</link>
	<description>&lt;p&gt;    24号，几个geek跑到我新家里面来玩，frank，ltn，thomas迟了一点，不过还是来了。gary跑来坐了五分钟。实话说，家里没这么热闹过，谢谢你们。
&lt;div&gt;    一帮geek在圣诞夜玩什么呢？首先是诈金花，我好像赢了一点——不过记得不是很清楚。我和猫咪不会打，ltn和frank会，老妈打了一阵就去烧饭了。然后是一顿很不错的晚餐——谢谢老妈。晚餐过后，我们开始摆弄数码相机，拍各种照片。我弹了一把吉他，好久不弹，都不会了。然后继续诈金花，同时电视里面在放哆啦A梦——用一台主机上的虚拟机里面的chrome放，这大概是整个客厅里面唯一符合geek聚会的东西。过了一会我累了，猫咪也困了，就中场休息，猫咪洗澡睡觉。&lt;/div&gt;
&lt;div&gt;    真正的geek聚会是在十点左右，猫咪睡觉/thomas到场后开始的。我们开始玩——愤怒的小鸟。不过我们不是打电脑游戏，而是用椅子摆了一个真实的物理模型，然后摆上我送给喵喵的猪头，和frank送我们的小鸟。每人五次，用小鸟打猪头。当然，猪头前面一般都是有一把椅子阻挡的。OK，这个——算不算Geek聚会的正常内容？&lt;/div&gt;
&lt;div&gt;    感觉geek就是一帮长不大的小孩，有点意思但是父母说不能玩的东西都要凑在一起玩一玩。不过以前多数是写程序，或者组装个硬件进行编程之类的事情。现在只是改成了组装愤怒的小鸟现场版而已。现场我们也没人在意战绩了，反正就是玩呗。&lt;/div&gt;
&lt;div&gt;    然后是例行的德州扑克大战——在weibo平台上面。我们原来在thoma家就是一帮人一起玩德州扑克的，不过现在地方没那时候大，来的人也不够多，所以不够热闹。我用电脑接到电视上玩，而其他人就各自用自己带来的电脑。四个人聚在一起互相打牌——这个有必要见面再打么？&lt;/div&gt;
&lt;div&gt;    然后？我困了，所以就收拾东西睡觉了。&lt;/div&gt;
&lt;div&gt;    第二天早上起来，我和喵喵就开始烧早餐——小馄饨。实话说这个简直外挂，不是我们自己包的，不用我们收拾。只是简单的找个锅子，烧热水，放下去，然后加冷水。不过有纪念意义的是，这勉强算是我和喵喵第一次一起做饭，也是第一次在新家烧饭。吃过早饭，大家继续德州扑克。猫咪用我的帐号输了好多，用会自己帐号就开始赢钱。可见根本没用心给我打——可恶。中午吃过点东西下午就去shlug活动了。&lt;/div&gt;
&lt;div&gt;    这次活动非常的吊诡，大家知道shlug的主题分享历来是比较正统，但是后面聊天就离题万里，OT到不知道哪里去了。今天我们分享的是bigdata，结果——我们会后讨论，OT了五六次，内容倒是很有趣，涉及了普朗克时间，玻尔兹曼常数，人类进化历史，中国和世界古文明史，世界宗教和基督教史，特种半导体技术，基因表达过程，蛋白质折叠计算。最牛的不是我们讨论了什么，而是每次都绕回到bigdata上面。只能说，今天的选题实在是太广了点。&lt;/div&gt;
&lt;div&gt;    好吧，一篇流水帐，没什么好多说的。geek每天的生活大概就和普通人一样。gary的车要去修，chaos要担心自家宝宝，ltn闹了肚子（不知道是不是和晚饭有关）第二天还要考试，thoma的老婆怀孕，圣诞夜还得陪着不能玩——哦，对了，她的预产期是明年，希望能生一个漂亮的小宝宝。&lt;/div&gt;
&lt;div&gt;    Merry Christmas，大家圣诞快乐。顺便——Happy new year。&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;PS: 照片我就不发了，大家看看这个得了。&lt;/div&gt;
&lt;div&gt;&lt;a href=&quot;http://shell909090.3322.org/shell/IMG_20111225_004833.jpg&quot;&gt;http://shell909090.3322.org/shell/IMG_20111225_004833.jpg&lt;/a&gt; &lt;/div&gt;&lt;/p&gt;</description>
	<pubDate>Sun, 25 Dec 2011 16:21:14 +0000</pubDate>
</item>
<item>
	<title>@xupeng: No SOPA! 将我的域名从 Godaddy 转出</title>
	<guid>http://blog.xupeng.me/2011/12/23/no-sopa-transfer-my-domains-out-of-godaddy</guid>
	<link>http://blog.xupeng.me/2011/12/23/no-sopa-transfer-my-domains-out-of-godaddy/</link>
	<description>&lt;p&gt;近来美国在尚未通过的 &lt;a href=&quot;http://en.wikipedia.org/wiki/Stop_Online_Piracy_Act&quot;&gt;SOPA&lt;/a&gt; 法案上产生了巨大争议，该法案最邪恶的地方在于，它使得 ISP 和版权方有权利因为某网站上有一点侵权内容而“拔其网线” - 使其域名无法解析，此权利也很容易被滥用。&lt;/p&gt;

&lt;!-- more --&gt;


&lt;p&gt;此举最大的获益者可能是日益衰落不思进取的传统出版、娱乐等行业，而代表先进技术生产力的互联网和互联网企业则遭受极大威胁，这是以损害创新为代价、以知识产权保护为名来庇护濒死的产业模式，实在是饮鸩止渴，阻碍信息传播和技术进步。&lt;/p&gt;

&lt;p&gt;我的域名一直都是在 Godaddy 注册的，而 Godaddy 站在了 &lt;a href=&quot;http://en.wikipedia.org/wiki/Stop_Online_Piracy_Act&quot;&gt;SOPA&lt;/a&gt; 支持者行列，颇让人意外，其实公开表示支持的公司还挺多的，比如 &lt;a href=&quot;http://judiciary.house.gov/issues/Rouge%20Websites/SOPA%20Supporters.pdf&quot;&gt;这里&lt;/a&gt; 就有一个不完全列表，但令人感到欣慰的是，我喜欢或者因其而受益的美国公司或组织全都是坚定的 SOPA 反对者，比如：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.google.com&quot;&gt;Google&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.facebook.com&quot;&gt;Facebook&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/&quot;&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.wikipedia.org&quot;&gt;Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.quora.com/&quot;&gt;Quora&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.linode.com/?r=cd5198f9daf6a668424aea5534f74baf343f4759&quot;&gt;Linode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/&quot;&gt;Github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.opendns.com/&quot;&gt;OpenDNS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&amp;#8230;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;等等等等。&lt;/p&gt;

&lt;p&gt;鉴于此，我打算将我在 Godaddy 的域名全部 transfer 到别的域名注册商，name.com 和 namecheap.com 都是不错的选择，做了一些比较之后，我打算将域名 transfer 到 name.com，之所以选择 name.com，主要是因为 name.com 也算是一个比较老牌的注册商/代理商了，另外也是因为 name.com 的价格比较公道。&lt;/p&gt;

&lt;p&gt;Transfer 的详细步骤就不重复了，互联网上已经有很多详细的流程解析，比如：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.jeffepstein.me/post/14629857835/a-step-by-step-guide-to-transfer-domains-out-of-godaddy&quot;&gt;Transfer 到 namecheap&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Transfer 到 name.com 可以参考上面链接的 Godaddy 部分和 &lt;a href=&quot;http://www.name.com/faq/transfer-into-name.com&quot;&gt;这里&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;不同的域名注册商/代理商的 Transfer 步骤大同小异，大致的必要步骤是这样：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;从转出方获取域名授权码（Authorization Key / EPP Key)&lt;/li&gt;
&lt;li&gt;在转入方填写要 transfer 的域名和对应的 EPP key&lt;/li&gt;
&lt;li&gt;等待转入方向域名的 Administrative Contact email 发送验证邮件，收到邮件后根据提示确认&lt;/li&gt;
&lt;li&gt;等待转入方开始 transfer，之后可能需要到转出方处授权允许转出&lt;/li&gt;
&lt;li&gt;等待 transfer 完成，这个步骤需要几个小时到几天不等，耐心等待就好&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;需要注意的是：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;域名需要是两个月之前注册的，比如 name.com 就不能 tranfser 两个月内新注册的域名&lt;/li&gt;
&lt;li&gt;域名不能被锁定，也就是说 whois 信息中显示的状态里没有 clientTransferProhibited，可以先在转出方那里解锁&lt;/li&gt;
&lt;li&gt;你能够通过 whois 信息中显示的 Administrative Contact email 接收邮件&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;有一些 transfer 域名的小提示和建议：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;利用一些 coupon 节省开支，比如 name.com 可以使用 &lt;code&gt;NODADDY&lt;/code&gt; 这个 coupon 节省 10% 的 transfer 费用&lt;/li&gt;
&lt;li&gt;有的域名注册商会将转出方处设定的域名记录迁移过去，这样的话整个域名的迁移是平滑的，不至于有不可解析的时间&lt;/li&gt;
&lt;li&gt;或者预先在转入方设定要使用的域名服务器，比如我使用的是 Linode 的 DNS 服务，我先在 name.com 处填写 Linode 的 DNS server，这样也可以做到平滑迁移&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;另外，还有一个费用和域名有效期的问题，比如之前我的 xupeng.me 到期时间是 2013/10/29，我需要支付一年的 transfer 费用，transfer 完成之后，域名的有效时间延期一年到 2014/10/29。&lt;/p&gt;

&lt;p&gt;更新（2011-11-24 08:36）：很高兴一早就看到了 Godaddy 不再支持 SOPA 的消息！一点微薄的行动有了效果，说不定我花两个小时迁出几个域名是压垮 Godaddy 的最后一根稻草 :) 就 Godaddy 支持 SOPA 这件事本身而言，从 Godady 转不转出域名都对个人都没什么大不了的影响， 转出只代表一种立场，代表眼里揉不得沙子的态度，用自己的实际行动投出微薄的一个反对票，使得反对者更多，最终使立法失败！&lt;/p&gt;</description>
	<pubDate>Fri, 23 Dec 2011 15:49:00 +0000</pubDate>
</item>
<item>
	<title>@shell909090: 关于今天六点到十点间无法访问的事情</title>
	<guid permalink="False">http://shell909090.com/blog/?p=2040</guid>
	<link>http://shell909090.com/blog/2011/12/%e5%85%b3%e4%ba%8e%e4%bb%8a%e5%a4%a9%e5%85%ad%e7%82%b9%e5%88%b0%e5%8d%81%e7%82%b9%e9%97%b4%e6%97%a0%e6%b3%95%e8%ae%bf%e9%97%ae%e7%9a%84%e4%ba%8b%e6%83%85/</link>
	<description>&lt;p&gt;别瞎猜了，我下班前写密码的文章时，想起自己的keepass里面有不少密码过期了，然后就更新了这些密码。结果把我的虚拟主机密码更新后，忘记在config.php里面跟着更新密码，然后网站就挂了。&lt;/p&gt;
&lt;p&gt;非常抱歉。&lt;/p&gt;</description>
	<pubDate>Fri, 23 Dec 2011 14:24:26 +0000</pubDate>
</item>
<item>
	<title>@shell909090: 网络安全——你需要知道的东西</title>
	<guid permalink="False">http://shell909090.com/blog/?p=2038</guid>
	<link>http://shell909090.com/blog/2011/12/%e7%bd%91%e7%bb%9c%e5%ae%89%e5%85%a8-%e4%bd%a0%e9%9c%80%e8%a6%81%e7%9f%a5%e9%81%93%e7%9a%84%e4%b8%9c%e8%a5%bf/</link>
	<description>&lt;p&gt;    首先，我也不是专家，如果里面有什么错漏，欢迎补充。补充和转载请注明我的blog: &lt;a href=&quot;http://shell909090.com/blog/&quot; target=&quot;_blank&quot;&gt;http://shell909090.com/blog/&lt;/a&gt;，我会根据你的发言在上面直接修改，没同步过去可不赖我。
&lt;div&gt;    要安全的使用网络/服务，你所需要注意的头两个问题就是你的安全级别和客户端的安全级别。对于零级密码，你随便在什么客户端上输入，都没有关系的。但是网银之类的最高级别密码，你不能在不可信机器上输入。什么叫不可信？别人的机器，你要相信这个人的技术和人品。自己的机器，你要在上面装了杀毒软件，没有执行过各种奇怪的程序/小游戏。这才叫可信的终端。如果你的密码在别人机器上用了，回来马上修改密码（不要在对方那里修改，没意义）。最好的方法，就是找一台旧电脑，专门装一个系统，装杀毒，用来使用网银和各种安全应用。别用深度定制版的操作系统，别人用过就重装。&lt;/div&gt;
&lt;div&gt;    当然，大多数的人都觉得，这样好麻烦啊。好吧，你可以无视这条规则——只要你对下面的各种病毒隔离和恢复措施做的够到位，对自己的技术够自信——至少我还没有这个自信。或者你可以认为我在危言耸听，彻底无视我的建议。大部分的情况下，你都是对的。这些事情都是徒劳的白做工。不过很低的概率下，你会中招——自己考虑。&lt;/div&gt;
&lt;div&gt;    其次，不要使用不可信的服务/产品。这条的执行力度自己考虑。一家公司，曾经做过流氓插件，你用不用他的产品？一家公司，曾经被央视曝光，你用不用他的产品？一家企业，敢于劫持客户的数据，将内容替换成自己的广告，你用不用他的服务？很多时候，我们都是别无选择，只能听天由命。不过当你有的选择的时候，尽量使用名声比较好的公司的产品。也许你觉得——这个不重要。好吧，Who care是最大的无力。&lt;/div&gt;
&lt;div&gt;    接下来，你要注意你的个人信息。被各个地方窃取使用个人信息已经很无奈了，你自己再爆出去就是无语了。你有没有在开心上公布手机号？有没有公布自己生日？有没有写自己的邮箱地址？有没有说过自己的家庭地址？这些信息都会被用于社会工程攻击，例如伪装你朋友的邮箱给你的邮箱写信，说借我二百。。。别笑，从开心上很容易收集这样的数据，伪装和发送也很自动。&lt;/div&gt;
&lt;div&gt;    后面一点对一些普通人可能比较困难——你要区分什么是可以信任的，什么是不可信的。下面的事情你权当笑话去听，是否照做自己判断。&lt;/div&gt;
&lt;div&gt;1.来电号码是不可信的，来电无法验证身份，短信和电子邮件也不行。如果你的一个朋友来电或者发消息说让你干什么事情，认证身份的最低办法是打回去。更加通用和安全的方法是共同知识验证——哎，大学的时候，我们隔壁宿舍摔断胳膊那哥们当时干啥摔断胳膊来着？伪装者怎么知道TM那倒霉孙子胳膊是怎么断的？通常人人上也不会说这个吧——除非丢的正好是人人帐号。&lt;/div&gt;
&lt;div&gt;2.传票是邮寄到家的，公安局找你都是上门或者通过街道。如果有人电话给你说是某法院/公安局，你不妨要他的电话和部门名称，然后打114查号，再打过去。通常情况下，不管也行——真有问题他们会上门找你的。&lt;/div&gt;
&lt;div&gt;3.网站什么都不能说明，即使那个网站里面有所谓的标识。例如qq.c0m（假如这个注册的出来的话）不代表腾讯，这个上面有人说你中奖一点意义都没有。即使来源真的是&lt;a href=&quot;http://qq.com&quot; target=&quot;_blank&quot;&gt;qq.com&lt;/a&gt;，那也不代表事情是真的。同样，靠谱的方法是要他的号码和部门，114查证后打过去。&lt;/div&gt;
&lt;div&gt;4.400电话打过去都不可信，你要是打一个400电话，和打一个民居没什么区别。对方有个声音很好听的小姐接听，还有——请稍等，我为您转接一位同事——也一点意义都没有。号码来自百度也没意义。&lt;/div&gt;
&lt;div&gt;5.用114电话比用百度的好处是，百度给钱就可以瞎排，这个都上央视了。114目前我还不知道有什么竞价排名的东西，所以你找一个电话多数都是靠谱的。注意，这个不绝对。&lt;/div&gt;
&lt;div&gt;6.手机这东西少借给别人，尤其是不熟悉的人。里面多个窃听器发信器你都不知道是谁干的。现实中没那么玄乎，也就是拿你的卡号申请动态令牌，申请前找你借五分钟手机而已。&lt;/div&gt;
&lt;div&gt;7.软件怎么判别是否可信？通常来说，敢开源的都是比较可信的，毕竟里面干了些什么大家都看的到。闭源的软件和服务就看你是否信的过这家公司了。&lt;/div&gt;
&lt;div&gt;8.对于别人推荐的玩意，尤其是朋友推荐的玩意，你最好确定一下确实是本人推荐的。即使是，我也保留的打开——技术上说，就是专门找台机器来运行。 &lt;/div&gt;
&lt;div&gt;9.有的时候，要敏感。你打给一家订票网站，他们需要你的身份证和信用卡号，给不给？实话说，这是个风险，而且不小。很多人的问题不是评判失误，而是根本没意识到这样做的风险。要知道，目前一代身份证还没有完全废弃，万一对方拿你的身份证号伪造了一张身份证，然后申请重置密码之类的事情。虽然能不能成两说，但是这两个号码同时泄露给一家网站总归是个风险。同样的还有携程——去年我曾经向他们的客户经理投诉，他们的电话语音系统居然要我人工报卡号，身份证之类的。我说如果是电话输入系统还好说，人工操作万一你的接线员记下来怎么办？这个你能保证么？今年大家打携程电话去看看？虽然我没有完全信任携程，但是电话系统比人工系统的安全性总是高那么一点点——除非他们故意在设计时捣糨糊，明明是电话录入系统，还是能让操作员看到全部卡号。&lt;/div&gt;
&lt;div&gt;    其实万千方案归结到后来都是八个字，多听多看，谨小慎微。会来看这篇blog的都是多听多看的，那么只要谨小慎微就好了。哪怕这谨小慎微有的时候显得有点小人和扭曲——不敢用别人的电脑上自己的帐号，不敢打开别人给的软件，不给别人玩自己的手机。到底多谨慎，看你自己觉得自己多重要。要是觉得一人吃饱全家不饿，就算全国密码泄露也与你无关。如果你觉得自己还是有点身家，有些该坚持的问题上还是要坚持一下。&lt;/div&gt;
&lt;div&gt;    最后说一点无奈的事情。即使你上面的事情全部做到，有很多事情还是无可奈何。例如携程的问题，他们有一个业务是只需要输入卡号后四位就可以订票，很明显，这是记录过全部的卡号才可以做到的事情。如果他们的数据库泄漏，攻击者是否就可以直接从中划帐呢？外推考虑这个问题，你会发现所有输入过信用卡号的公司，无论他们是否可信，你都要假定他们保存了你的卡号信息。所以事情就只能信赖银行的信用卡系统，包括大笔消费警告，未经手消费复核，先行赔付等等。只有消费后能够复核的信用卡公司，才是可以信赖的公司。&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;PS:&lt;/div&gt;
&lt;div&gt;    另外做一点广告。全国各家涉密公司，如果你们不希望你们的管理员/操作员随意接触高级管理帐号，希望能够审查谁接触过用户账户信息，你可以用我们的系统。&lt;a href=&quot;http://www.shterm.com/&quot;&gt;http://www.shterm.com/&lt;/a&gt;。我们目前做的是堡垒机密码托管，除了一个最高管理者外，管理员都不知道自己使用账户的密码是多少。同时，访问过用户账户信息会留下无法清除的记录，事后可以审查。&lt;/div&gt;
&lt;div&gt;    &lt;b&gt;注意：普通用户上这套系统没用！&lt;/b&gt;&lt;/div&gt;&lt;/p&gt;</description>
	<pubDate>Fri, 23 Dec 2011 04:00:41 +0000</pubDate>
</item>
<item>
	<title>@delphij: 作弊条：几个不太常用的git库管操作</title>
	<guid>tag:blog.delphij.net,2011://2.2140</guid>
	<link>https://blog.delphij.net/2011/12/git-1.html</link>
	<description>&lt;p&gt;配合 svn 使用 git 时可能会遇到许多问题，例如两个人分别做了 git svn clone，然后希望合并到同一个 git 库中。如何做合并呢？假定两个库分别是 old, new，将这两个库对应的分支和对应的源分支 (svn/*) 通过 .git/config 分别复制到不同的分支名字下面，例如 svn/releng/8.2 和 old-svn/releng/8.2。假定需要合并的分支是 old/my8.2，则做以下操作：&lt;/p&gt;

&lt;pre&gt;
git checkout my8.2 # 签出一份工作副本
git rebase old-svn/releng/8.2 # 更新到原始上游的最新状态
git rebase --onto svn/releng/8.2 old-svn/releng/8.2 # 用新库作为基础重新rebase；
git push origin my8.2 # 将结果push回代码库
&lt;/pre&gt;

&lt;p&gt;把本地新建分支推到上游：&lt;/p&gt;

&lt;pre&gt;
git push origin 分支名
&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;问题：首次push时会收到 git post-receive remote: fatal: Invalid revision range 0000000000000000000000000000000000000000..XXXXXXXXXXX，不过并不影响push本身。这个错误是由于post-receive的hook里面引用了git提供的旧版本，但查了一下似乎没有很好的办法知道这个分支的上游是谁？（基本逻辑应该大致是：和库中已经存在的所有其他分支进行比较并找到公共版本与本分支HEAD距离最近的一个，返回那个版本号）。&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;删除远程代码库中的分支：&lt;/p&gt;

&lt;pre&gt;
git push origin :分支名
&lt;/pre&gt;</description>
	<pubDate>Fri, 16 Dec 2011 09:04:54 +0000</pubDate>
</item>
<item>
	<title>@xupeng: 迁移到 Octopress</title>
	<guid>http://blog.xupeng.me/2011/12/14/migrate-to-octopress</guid>
	<link>http://blog.xupeng.me/2011/12/14/migrate-to-octopress/</link>
	<description>&lt;p&gt;用了三年多 Wordpress，由于实在很懒，没有写过多少东西，但跑在 &lt;a href=&quot;http://www.linode.com/?r=cd5198f9daf6a668424aea5534f74baf343f4759&quot;&gt;Linode VPS&lt;/a&gt; 上的 Wordpress 却一直占用了很多资源，几个 &lt;a href=&quot;http://php-fpm.org/&quot;&gt;PHP-FPM&lt;/a&gt; 进程加上 MySQL 就用掉了将近 400MB 内存，却没有什么访问量，觉得很不划算，再加上 Wrodpress 越来越臃肿，就想把它换成一个静态内容发布系统。&lt;/p&gt;

&lt;!-- more --&gt;


&lt;p&gt;简单看了一下，很快就找到了 &lt;a href=&quot;http://octopress.org/&quot;&gt;Octopress&lt;/a&gt;，一眼就看上了，花了半个小时试用，还是很符合我的使用习惯的：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;配置简单，简单修个几个配置就能使用&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://daringfireball.net/projects/markdown/&quot;&gt;Markdown&lt;/a&gt; 语法，VIM + Terminal 就能完成内容书写与发布&lt;/li&gt;
&lt;li&gt;定制简单，plugin 看起来也不复杂，不过写 plugin 要学一点 ruby&lt;/li&gt;
&lt;li&gt;默认的模版就很漂亮，也很便于阅读&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;花了几个小时把 Wordpress 里旧的文章导出、导入到 Octopress，手工编辑了部分不像样的文章，一个焕然一新的静态发布 blog 就基本可用了，在这个过程中我主要参考了这些文档和文章：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://octopress.org/docs/&quot;&gt;http://octopress.org/docs/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://felipecypriano.com/2011/09/16/why-ive-migrated-to-octopress/&quot;&gt;http://felipecypriano.com/2011/09/16/why-ive-migrated-to-octopress/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://mattgemmell.com/2011/09/12/blogging-with-octopress/&quot;&gt;http://mattgemmell.com/2011/09/12/blogging-with-octopress/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;把这些读一遍就能顺利完成迁移和部署，所以就不重复步骤了。&lt;/p&gt;

&lt;p&gt;问题也是有的，比如插件过少，甚至原作者都没有提供 Tag Cloud 支持，可能也有 bug，比如我试用时使用的 base URL 是 &lt;code&gt;http://o.xupeng.me&lt;/code&gt;，迁移完毕换成正式的 URL &lt;code&gt;http://blog.xupeng.me&lt;/code&gt; 后，重新生成的静态页面和 feed 内的 URL 会在新旧两个 URL 之间随机变化，导致 &lt;a href=&quot;http://ifttt.com/&quot;&gt;ifttt&lt;/a&gt; 认为我 blog 上的文章全都发生了变化，向我的 twitter 上发了一大堆信息，我删除了 cache 目录之后这个问题没有再出现过。&lt;/p&gt;

&lt;p&gt;不算是一个完美的系统，不过基本上能够满足我的需求，之后有空再补上缺少的东西吧。&lt;/p&gt;</description>
	<pubDate>Wed, 14 Dec 2011 14:23:00 +0000</pubDate>
</item>
<item>
	<title>@xupeng: 2.6.38 / 2.6.39 + XFS 的性能极差</title>
	<guid>http://blog.xupeng.me/2011/12/11/poor-performance-with-xfs-2-6-38-and-2-6-39</guid>
	<link>http://blog.xupeng.me/2011/12/11/poor-performance-with-xfs-2-6-38-and-2-6-39/</link>
	<description>&lt;p&gt;线上的 MySQL 服务器一直都在使用 XFS 文件系统，性能和稳定性都表现良好，使用的内核版本是 2.6.29，经过时间和访问压力的验证，表现也不错。&lt;/p&gt;

&lt;p&gt;前一段时间在测试几款 SSD 产品，考虑到 XFS 在内核 2.6.38 之后才加入了对 FITRIM 的支持（&lt;a href=&quot;http://xfs.org/index.php/FITRIM/discard&quot;&gt;ref1&lt;/a&gt;  &lt;a href=&quot;http://xfs.org/index.php/Support_discarding_of_unused_sectors&quot;&gt;ref2&lt;/a&gt;），就在 2.6.38 和 2.6.39 上对 SSD 做了测试，测试结果却让人大跌眼镜，XFS 在 2.6.38 和 2.6.39 之上的性能差到完全不能接受。&lt;/p&gt;

&lt;!-- more --&gt;


&lt;p&gt;我在内核 2.6.29 和 2.6.39 下使用 &lt;a href=&quot;http://freecode.com/projects/fio&quot;&gt;fio&lt;/a&gt; 分别对 raw device、XFS 和 ext4 做了一个简单的 IO 测试，测试参数是这样的：&lt;/p&gt;

 &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&quot;line-number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;&lt;span class=&quot;line&quot;&gt;fio --filename&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;-TO-TEST-FILE --direct&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1 --rw&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;randrw --bs&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;16k &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    --size&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;50G --numjobs&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;16 --runtime&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;120 --group_reporting &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    --name&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt; --rwmixread&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;90 --thread --ioengine&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;psync
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;


&lt;p&gt;大意是：使用 non-buffered I/O，16 个并发 IO 线程，做 16KB 块大小的随机读写混合测试，读写比为 9:1&lt;/p&gt;

&lt;p&gt;下面是 2.6.29 下的测试结果：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.xupeng.me/downloads/ext4-xfs-perf/2.6.29-raw.txt&quot;&gt;2.6.29 + raw device&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.xupeng.me/downloads/ext4-xfs-perf/2.6.29-xfs.txt&quot;&gt;2.6.29 + XFS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.xupeng.me/downloads/ext4-xfs-perf/2.6.29-ext4.txt&quot;&gt;2.6.29 + ext4&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;可以看到，ext4, XFS 和 raw device 的 IOPS 都在 12000 上下，考虑到测试之间会有误差，基本可以认为三者的性能一样。&lt;/p&gt;

&lt;p&gt;下面是 2.6.39 下的测试结果：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.xupeng.me/downloads/ext4-xfs-perf/2.6.39-raw.txt&quot;&gt;2.6.39 + raw device&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.xupeng.me/downloads/ext4-xfs-perf/2.6.39-xfs.txt&quot;&gt;2.6.39 + XFS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.xupeng.me/downloads/ext4-xfs-perf/2.6.39-ext4.txt&quot;&gt;2.6.39 + ext4&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;ext4 和 raw device 的 IOPS 约为 12900，比在 2.6.29 下略有提升，但是 XFS 的性能就有点惨不忍睹了，竟然只有不到 4000。&lt;/p&gt;

&lt;p&gt;尝试了很多种不同的 XFS 格式化、mount 参数，IOPS 都只是在 4000 左右徘徊，还没有找到解决方案，目前在部分服务器上尝试使用了 ext4，进一步监测 ext4 的性能和稳定性，或许未来会在数据库服务器上全部使用 ext4。&lt;/p&gt;

&lt;p&gt;更新：在 XFS 邮件列表咨询之后，确认了这是 XFS 的已知 bug：&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;commit 686da49e5aa50117d8d824c579c3fd9e0318fbc6&lt;br /&gt;Author: Dave Chinner &lt;br /&gt;Date:   Thu Dec 1 17:27:39 2011 -0600&lt;/p&gt;&lt;p&gt;    xfs: don&amp;#8217;t serialise direct IO reads on page cache checks&lt;br /&gt;    &lt;br /&gt;    commit 0c38a2512df272b14ef4238b476a2e4f70da1479 upstream.&lt;br /&gt;    &lt;br /&gt;    There is no need to grab the i_mutex of the IO lock in exclusive&lt;br /&gt;    mode if we don&amp;#8217;t need to invalidate the page cache. Taking these&lt;br /&gt;    locks on every direct IO effective serialises them as taking the IO&lt;br /&gt;    lock in exclusive mode has to wait for all shared holders to drop&lt;br /&gt;    the lock. That only happens when IO is complete, so effective it&lt;br /&gt;    prevents dispatch of concurrent direct IO reads to the same inode.&lt;br /&gt;    &lt;br /&gt;    Fix this by taking the IO lock shared to check the page cache state,&lt;br /&gt;    and only then drop it and take the IO lock exclusively if there is&lt;br /&gt;    work to be done. Hence for the normal direct IO case, no exclusive&lt;br /&gt;    locking will occur.&lt;br /&gt;&lt;/p&gt;&lt;strong&gt;Dave Chinner&lt;/strong&gt; &lt;cite&gt;&lt;a href=&quot;http://www.spinics.net/lists/xfs/msg08688.html&quot;&gt;www.spinics.net/lists/xfs/&amp;hellip;&lt;/a&gt;&lt;/cite&gt;&lt;/blockquote&gt;


&lt;p&gt;3.0.11, 3.1.5 和 3.2-rc1 中已经修复。XFS 用户在升级内核时需要注意，升级到修复后的版本，并做充分的性能测试。&lt;/p&gt;</description>
	<pubDate>Sat, 10 Dec 2011 16:00:00 +0000</pubDate>
</item>
<item>
	<title>@xupeng: SCGI与线程</title>
	<guid>http://blog.xupeng.me/2011/12/08/scgi-and-threading</guid>
	<link>http://blog.xupeng.me/2011/12/08/scgi-and-threading/</link>
	<description>&lt;p&gt;最近在写一个配置推送客户端，结构如下图：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://blog.xupeng.me/downloads/2011/12/cfgreceiver.png&quot; title=&quot;cfgreceiver architecture&quot; alt=&quot;cfgreceiver architecture&quot; /&gt;&lt;/p&gt;

&lt;p&gt;每一个应用服务进程会起一个额外的线程，与 ZooKeeper 保持连接，需要变更配置时，将新配置更新到 ZooKeeper，ZooKeeper 将配置推送到所有的客户端，客户端收到配置之后，即时更新进程内的配置信息，并将更新配置成功与否、延时、错误等信息反馈到 redis，以这样的方式做到不重启服务更新配置。&lt;/p&gt;

&lt;!-- more --&gt;


&lt;p&gt;同时也会有一个独立的客户端与 ZooKeeper 保持连接，收到 ZooKeeper 推送的配置之后，将配置写回并提交到 Puppet 配置仓库中，这样仍然保持只在一个地方修改配置的习惯。&lt;/p&gt;

&lt;p&gt;这个推送客户端的第一个应用场景是更新线上的 MySQL 配置，线上服务是 Quixote + SCGI，由于在 SCGI server fork 子进程之前就已经 import 了部分自有库，其中包括这个配置推送客户端的使用者，因此，这个客户端必须是 lazy 的，只能在 fork 发生之后才能启动线程、建立与 ZooKeeper 和 redis 的连接。&lt;/p&gt;

&lt;p&gt;将这个客户端与 Quixote + SCGI 服务进行联调时，奇怪的事情发生了，配置发生变更时，客户端并没有立刻收到 ZooKeeper 的推送，而是等到下一次用户请求到达时才会收到，起初以为是线程根本就没有在工作，后来发现，线程也并不是完全不工作，而是阻塞在了某个地方，当有用户请求到达时，线程才会接着执行。这就意味着，如果一个进程闲置了比较长的时间，ZooKeeper 会认为客户端已失去响应，从而断开连接，而客户端重连 ZooKeeper 也只会发生在下一次请求到来之后，这是个很别扭很诡异的问题。&lt;/p&gt;

&lt;p&gt;去掉目前使用的 Quixote 包装，写了一个最简单的 Quixote app，发现同样的问题依然存在，这排除了自有 Quixote 包装的问题。接下来又写了一个裸的 SCGI app：&lt;/p&gt;

 &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&quot;line-number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;6&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;7&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;8&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;9&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;10&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;11&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;12&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;13&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;14&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;15&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;c&quot;&gt;#!/usr/bin/env python&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;c&quot;&gt;# t.py&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sys&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;time&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;threading&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;threading&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;n&quot;&gt;daemon&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stderr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'sleeping'&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;            &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stderr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'id:&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; time:&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;




 &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&quot;line-number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;6&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;7&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;8&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;9&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;10&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;11&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;12&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;13&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;14&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;15&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;16&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;c&quot;&gt;#!/usr/bin/env python&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;c&quot;&gt;# s.py&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sys&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;scgi&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scgi_server&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scgi_server&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SCGIHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;produce_cgilike&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bodysize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_alive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stderr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'start thread: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Content-Type: text/plain&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\r\n\r\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;n&quot;&gt;scgi_server&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SCGIServer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'0.0.0.0'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9002&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;serve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;


&lt;p&gt;这样的一个服务仍然有上面提到的问题，每有一次用户访问，就会输出一行 &amp;#8220;id:xxx time:xxx&amp;#8221;，然后输出一行 &amp;#8220;sleeping&amp;#8221;，之后就阻塞在了 time.sleep(1) 处（起码看起来是阻塞在了这里）。至此，也可以排除 Quixote 的问题，问题应该出在 SCGI 这里，向 &lt;a href=&quot;http://www.douban.com/people/hongqn/&quot;&gt;hongqn&lt;/a&gt; 请教之后，最终定位到了问题所在。&lt;/p&gt;

&lt;p&gt;在 SCGIHandler.serve 方法中：&lt;/p&gt;

 &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&quot;line-number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;code class=&quot;python&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent_fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# indicates that child is ready&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;passfd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;recvfd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent_fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pre&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;


&lt;p&gt;passfd.recvfd 是一个阻塞读，它的代码是这样的：&lt;/p&gt;

 &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&quot;line-number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;6&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;7&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;8&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;9&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;10&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;11&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;12&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;13&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;14&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;15&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;code class=&quot;c&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;nf&quot;&gt;passfd_recvfd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sockfd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyArg_ParseTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;i:revcfd&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sockfd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recv_fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sockfd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;n&quot;&gt;PyErr_SetFromErrno&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyExc_IOError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyInt_FromLong&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;


&lt;p&gt;fd = recv_fd(sockfd) 是一个阻塞读，在开始阻塞读之前没有释放 GIL ，于是就导致了整个解释器阻塞，这也与之前问题的症状吻合。将代码作如下修改，在开始阻塞读之前释放 GIL，可以解决这个问题：&lt;/p&gt;

 &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&quot;line-number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;6&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;7&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;8&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;9&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;10&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;11&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;12&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;13&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;14&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;15&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;16&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;17&lt;/span&gt;
&lt;span class=&quot;line-number&quot;&gt;18&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;code class=&quot;c&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;nf&quot;&gt;passfd_recvfd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyObject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sockfd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyArg_ParseTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;i:revcfd&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sockfd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;n&quot;&gt;Py_BEGIN_ALLOW_THREADS&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recv_fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sockfd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;n&quot;&gt;Py_END_ALLOW_THREADS&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;n&quot;&gt;PyErr_SetFromErrno&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyExc_IOError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyInt_FromLong&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;


&lt;p&gt;当然了，还需要做进一步的测试和观察，看一下打这样的 patch 之后会不会有其他的副作用。&lt;/p&gt;

&lt;p&gt;参考：&lt;a href=&quot;http://docs.python.org/release/2.6.7/c-api/init.html#thread-state-and-the-global-interpreter-lock&quot;&gt;http://docs.python.org/release/2.6.7/c-api/init.html#thread-state-and-the-global-interpreter-lock&lt;/a&gt;&lt;/p&gt;</description>
	<pubDate>Wed, 07 Dec 2011 16:00:00 +0000</pubDate>
</item>
<item>
	<title>@khsing: 驾照和租车</title>
	<guid>http://blog.khsing.net/?p=457</guid>
	<link>https://blog.khsing.net/2011/11/driving-license-and-rental-car.html</link>
	<description>&lt;p&gt;经过半年的驾校学习，赶在一年结束以前我终于是拿到了天朝的驾驶执照。3月报的名，4月科目一考完，5月份开始上车学习，10月科目二考试完事，11月科目三考试结束，在我看来这是一个漫长的过程。&lt;/p&gt;
&lt;p&gt;在拿到驾照的第一天，蠢蠢欲动的心情难以抑制，于是在神舟租车下了单订了一个标致207。第一天上路，堵车是难免的，熄火数次，被后面鸣笛多次，送老婆回来的时候还走错了路在健翔桥上桥去了八达岭高速。第二天主要是下了两次地库，中午出库的时候在出口熄火、小溜车把后面的宝马吓的倒退。晚上出地库的时候，在收费处把前面的宝马给小追尾了一次，这是没刹住车，没有处理经验一时有点惊慌失措。打了一圈电话，才搞清楚，给交警报警，给保险公司保险，属于小事故，自行解决一下走保险完事了。第三天和同事去吃饭，三环堵车一路。&lt;/p&gt;
&lt;p&gt;总结下来，我这驾车技术还是不行滴。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;起步不行，不够平缓，经常熄火。&lt;/li&gt;
&lt;li&gt;坡起不行，经常熄火，偶尔溜车。&lt;/li&gt;
&lt;li&gt;停车不行，倒车位置不好，左右不均，需要多次调整。实地的侧方停车还没有机会试验。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;经验是&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;起步的时候还是要适当的给点油，不象教练场不要给油&lt;/li&gt;
&lt;li&gt;手动档，左脚的位置怎么也不能离开离合，即使在上破时也不能，放在离合上是右脚在紧张时踩刹车的一个参考，不至于一脚踩到离合上。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;当然这个经验和车应该有不小的关系，需要和自己的车磨合磨合。&lt;/p&gt;
&lt;p&gt;租车的经验是，&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;新手还是要买那个不计免赔的保险。&lt;/li&gt;
&lt;li&gt;提车的时候要注意车身的损伤情况，要在租车协议上写的清楚。&lt;/li&gt;
&lt;li&gt;神舟租车是满箱油走，满箱油回。提车要检查油表，如果没满，一定要在租车协议上注明。&lt;/li&gt;
&lt;li&gt;如果出事了会多收租金，一般是1到2天。&lt;/li&gt;
&lt;li&gt;提车时还要注意车内应该放有车的保险协议，最好是还要有快速处理单。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;出了事故的处理流程是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;报警，拿到快速处理单。责任清楚时候警察可能会让自己写个快速处理单完事，不清楚的时候警察来下责任认定书。&lt;/li&gt;
&lt;li&gt;保险，看看车的保险公司是哪一个。给保险公司打电话，说明情况，提供双方车辆的车牌号和车型号就好了。重要的是要拿到保险号&lt;/li&gt;
&lt;li&gt;拍照&lt;/li&gt;
&lt;li&gt;到租车公司门店提供这些材料。复印相关证件，这时候双方车辆都要到场。&lt;/li&gt;
&lt;li&gt;等保险公司的指定或者客户指定的定损地点定损修车&lt;/li&gt;
&lt;li&gt;要先垫刷1500到3000左右的一个预售权，等修过车了，保险公司的赔付到了再返还。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;BTW: 新手上路还是要多注意，多小心，后车鸣笛的时候不要太紧张。别出事，自己心烦，而且还给人家添麻烦。虽然有保险赔付，但是双方的时间都是耗不起。你撞人家，人家比你还要烦的多。&lt;/p&gt;</description>
	<pubDate>Sat, 26 Nov 2011 05:45:53 +0000</pubDate>
</item>
<item>
	<title>@delphij: netmap进 -CURRENT</title>
	<guid>tag:blog.delphij.net,2011://2.2138</guid>
	<link>https://blog.delphij.net/2011/11/netmap--current.html</link>
	<description>&lt;p&gt;近日， netmap 已经正式进入 -CURRENT (r227614)。目前联编带 netmap 的内核需要做下面的操作：&lt;/p&gt;

&lt;pre&gt;
% cd /usr/src/sys
% patch -p0  dev/netmap/head.diff
&lt;/pre&gt;

&lt;p&gt;然后在内核联编配置中加入：&lt;/p&gt;

&lt;pre&gt;
device netmap
&lt;/pre&gt;

&lt;p&gt;目前，这个补丁包括了对 Intel 万兆以太网适配器 ixgbe(4)、千兆以太网适配器 igb(4) 和 em(4) 以及 Realtek 千兆以太网适配器 re(4) 的支持。由于 netmap 的设计，对其他驱动的修改也相当简单，只需增加大约 15 行左右的代码即可。&lt;/p&gt;

&lt;p&gt;在 src/tools/tools/netmap 中提供了一系列用户态的例子，包括一个简化的 libpcap 实现（不完整，但足以支持 tcpdump 运行）、一个用户态网桥、用户态高速收发包测试，以及使用 &lt;a href=&quot;http://read.cs.ucla.edu/click/click&quot;&gt;Click&lt;/a&gt; 的例子（需要 netmap 的那个 libpcap 实现）。&lt;/p&gt;</description>
	<pubDate>Mon, 21 Nov 2011 08:01:22 +0000</pubDate>
</item>
<item>
	<title>@delphij: clang静态分析工具作弊条</title>
	<guid>tag:blog.delphij.net,2011://2.2137</guid>
	<link>https://blog.delphij.net/2011/11/clang.html</link>
	<description>&lt;p&gt;静态分析是一种辅助的代码品质提高手段，简而言之静态分析大致是走一个类似编译的过程（或者走完生成副产品），然后给出代码中可能存在的问题。&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.FreeBSD.org/&quot;&gt;FreeBSD&lt;/a&gt; Ports Collection 中提供的 &lt;a href=&quot;http://www.freshports.org/lang/clang-devel/&quot;&gt;lang/clang-devel&lt;/a&gt; 内建了 clang 项目的静态分析工具。这个工具的用法非常简单，假设我们原先的联编命令是：&lt;/p&gt;

&lt;pre&gt;
make -j 4 all
&lt;/pre&gt;

&lt;p&gt;那么，配合clang静态分析工具来产生输出的命令便是：&lt;/p&gt;

&lt;pre&gt;
scan-build &lt;i&gt;-o /tmp/scan&lt;/i&gt; make -j 4 all
&lt;/pre&gt;

&lt;p&gt;以上， /tmp/scan 是输出目录。scan-build可以设置必要的环境变量来让make使用ccc-analyzer代替${CC}来完成编译工作，并把输出保存到指定目录的一个唯一的子目录中。下面，我们可以运行：&lt;/p&gt;

&lt;pre&gt;
scan-view --allow-all-hosts --no-browser --host &lt;u&gt;10.4.2.253&lt;/u&gt; &lt;i&gt;/tmp/scan/2011-11-17-1&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;上面的/tmp/scan/2011-11-17-1是scan-build在最后告诉我们的那个结果，而 10.4.2.253 是本机 IP 地址。用浏览器访问 http://10.4.2.253:8181 就可以看到编译过程中发现的问题了。&lt;/p&gt;

&lt;p&gt;需要说明的是，静态分析工具并不总是能给出理想的输出结果。开发者需要充分分析程序逻辑之后再做修改。&lt;/p&gt;</description>
	<pubDate>Fri, 18 Nov 2011 09:04:19 +0000</pubDate>
</item>
<item>
	<title>@limodou: uliweb·¢²¼0.0.1a7°æ±¾ÁË</title>
	<guid permalink="False">http://hi.baidu.com/limodou/blog/item/b0b3b21bc380ef048718bff4.html</guid>
	<link>http://hi.baidu.com/limodou/blog/item/b0b3b21bc380ef048718bff4.html</link>
	<description>&lt;p&gt;ÒÑ¾­ÔÚpypiÉÏ¿ÉÒÔ¿´µ½£¬²¢ÇÒ¿ÉÒÔÍ¨¹ýcode.googleºÍgithubÀ´ÏÂÔØ¡£Ê¹ÓÃeasy_install Ó¦¸ÃÒ²¿ÉÒÔ°²×°¡£&lt;/p&gt;&lt;p&gt;ÏÖÔÚsaeµÄÄÚ²â°æ±¾ÒÑ¾­ÄÚÖÃÁËuliwebµÄ°æ±¾£¬²¢ÇÒsqlalchemyÒ²°²×°ÁË£¬°æ±¾ÊÇ0.7.3¡£&lt;/p&gt;&lt;p&gt;ÎªÊ²Ã´°æ±¾ºÅÕâÃ´µÍ£¬ÒòÎªÎÒ¸Ð¾õ»¹²»ÊÇÌØ±ðµÄÂúÒâ£¬µÈÔÙÌí¼ÓÒ»Ð©ÐÂµÄ¹¦ÄÜÕùÈ¡Éý¼¶µ½0.0.1°É¡£×îÐÂÒªÌí¼ÓµÄ¹¦ÄÜ¼Æ»®:&lt;/p&gt;&lt;p&gt;Êý¾Ýµ¼Èëµ¼³ö‰ˆ¼Ó¶Ôcsv, excelµÄÖ§³Ö&lt;br /&gt;‰ˆ¼ÓÒ»¸öÊý¾Ý¿âÎ¬»¤µÄ½çÃæ£¬½«·ÅÔÚplugsÖÐ£¬ÒÔ±ã¿ÉÒÔÔÚsaeÉÏÊ¹ÓÃ&lt;/p&gt;&lt;p&gt;½«form, generic, dbuploadÎÄµµÐ´Íê&lt;/p&gt;&lt;p&gt;bug fix&lt;/p&gt;&lt;p&gt;ºóÃæ»¹ÒªÍê³ÉµÄ£º&lt;/p&gt;&lt;p&gt;plugsÏà¹ØµÄÎÄµµ&lt;/p&gt;&lt;p&gt;ormµÄ½øÒ»²½ÓÅ»¯&lt;/p&gt;&lt;p&gt;CRUDµÄ´úÂë¿ò¼ÜµÄÉú³É&lt;/p&gt;&lt;p&gt;forum¹¦ÄÜµÄ½øÒ»²½ÓÅ»¯&lt;/p&gt;&lt;p&gt;¿ª·¢Ò»¸öBlog app&lt;/p&gt;&lt;p&gt;rss feedÉú³ÉÖ§³Ö&lt;/p&gt;&lt;p&gt;develop¹¦ÄÜÊ¹ÓÃjqueryÖØÐ´&lt;/p&gt;&lt;p&gt;Óëin.jsµÄ¼¯³É&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;/p&gt; 
		
		&lt;br /&gt;&lt;b&gt;Àà±ð£º&lt;/b&gt;&lt;a href=&quot;http://hi.baidu.com/limodou/blog/category/Uliweb&quot;&gt;Uliweb&lt;/a&gt;&amp;nbsp;&lt;a href=&quot;http://hi.baidu.com/limodou/blog/item/b0b3b21bc380ef048718bff4.html#comment&quot;&gt;²é¿´ÆÀÂÛ&lt;/a&gt;</description>
	<pubDate>Tue, 15 Nov 2011 00:00:00 +0000</pubDate>
</item>
<item>
	<title>@limodou: uliweb×¼±¸·¢²¼ÐÂ°æ±¾ÁË</title>
	<guid permalink="False">http://hi.baidu.com/limodou/blog/item/a9054723bfa5964f9922ed75.html</guid>
	<link>http://hi.baidu.com/limodou/blog/item/a9054723bfa5964f9922ed75.html</link>
	<description>&lt;span&gt;°æ±¾½«ÊÇ0.0.1a7,²»¹ý»¹ÓÐÒ»Ð©Ã»ÅªÍêµÄ¡£&lt;/span&gt;&lt;span&gt;ÓÐÒ»Ð©±ä»¯»áÔì³ÉÓëÏÖÓÐµÄ³ÌÐò²»¼æÈÝµÄµØ·½£º&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;1. MiddlewareµÄÅäÖÃÐ´·¨±ä»¯&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;Ô­À´ÊÇÔÚGLOBALÏÂ£¬ÏÖÔÚ¶ÀÁ¢ÁË£¬ÏÖÔÚµÄÐ´·¨ÊÇ£º&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;[MIDDLEWARES]&lt;/span&gt;&lt;br /&gt;&lt;span&gt;name = 'middleware_class_path'[, order]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;ÎÄµµËµÃ÷£º&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;http://readthedocs.org/docs/uliweb/en/latest/middleware.html#id4&quot; target=&quot;_blank&quot;&gt;http://readthedocs.org/docs/uliweb/en/latest/middleware.html#id4&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;Ó°Ïì×î´óµÄ¿ÉÄÜ¾ÍÊÇapps/settings.iniÁË£¬&lt;/span&gt;&lt;span&gt;Èç¹ûÄãÓÃµ½ÊÂÎñ£¬¿ÉÄÜ»áÐ´transaction_&lt;/span&gt;&lt;span&gt;middleware£¬ÄÇÃ´¿ÉÄÜÒªÐÞ¸Ä¡£&lt;/span&gt;&lt;span&gt;ÆäËüµÄmiddleÒ»°ã¶¼ÔÚÄ³¸öappÏÂµÄsettings.&lt;/span&gt;&lt;span&gt;iniÖÐ¶¨ÒåºÃÁË£¬Ò»°ã²»ÓÃÔÙÖØ¸´¶¨Òå£¬ËùÒÔÓ°Ïì²»´ó¡£&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;2. appÒÀÀµ¶¨Òå±ä»¯¡£Ô­À´ÊÇÔÚappÏÂµÄconfig.&lt;/span&gt;&lt;span&gt;iniÖÐµÄ[DEFAULT]ÖÐ£¬ÏÖÔÚÐÞ¸ÄÎª[DEPENDS]&lt;/span&gt;&lt;span&gt;ÁË¡£&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;ÒÔÉÏÄÚÈÝ£¬&lt;/span&gt;&lt;span&gt;Ö»ÒªÊÇÉæ¼°µ½uliwebºÍplugsµÄapp¶¼ÒÑ¾­½øÐÐÁËÐÞ¸Ä&lt;/span&gt;&lt;span&gt;¡£Ö»ÓÐ×ÔÒÑ¶¨ÒåµÄappºÍsettingsÒªÊÖ¹¤ÐÞ¸ÄÒ»ÏÂ¡£&lt;/span&gt;&lt;p&gt;&lt;/p&gt; 
		
		&lt;br /&gt;&lt;b&gt;Àà±ð£º&lt;/b&gt;&lt;a href=&quot;http://hi.baidu.com/limodou/blog/category/Uliweb&quot;&gt;Uliweb&lt;/a&gt;&amp;nbsp;&lt;a href=&quot;http://hi.baidu.com/limodou/blog/item/a9054723bfa5964f9922ed75.html#comment&quot;&gt;²é¿´ÆÀÂÛ&lt;/a&gt;</description>
	<pubDate>Sat, 12 Nov 2011 00:00:00 +0000</pubDate>
</item>
<item>
	<title>@huangyi: warp静态文件服务器评测</title>
	<guid permalink="False">http://yi-programmer.com/blog/2011-11-12_wai-static-app.html</guid>
	<link>http://yi-programmer.com/blog/2011-11-12_wai-static-app.html</link>
	<description>&lt;div class=&quot;section&quot; id=&quot;id1&quot;&gt;
&lt;h2&gt;安装&lt;/h2&gt;
&lt;ol class=&quot;arabic&quot;&gt;
&lt;li&gt;&lt;p class=&quot;first&quot;&gt;安装GHC和Cabal，参考： &lt;a class=&quot;reference external&quot; href=&quot;http://book.realworldhaskell.org/read/installing-ghc-and-haskell-libraries.html&quot;&gt;http://book.realworldhaskell.org/read/installing-ghc-and-haskell-libraries.html&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class=&quot;first&quot;&gt;使用Cabal安装 &lt;a class=&quot;reference external&quot; href=&quot;https://github.com/yesodweb/wai/tree/master/warp&quot;&gt;Warp&lt;/a&gt; 服务器和 &lt;a class=&quot;reference external&quot; href=&quot;https://github.com/yesodweb/wai/tree/master/wai-app-static&quot;&gt;wai-app-static&lt;/a&gt; ，Cabal将自动下载安装依赖的一些库：&lt;/p&gt;
&lt;pre class=&quot;literal-block&quot;&gt;
cabal install warp wai-app-static
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class=&quot;first&quot;&gt;编写我们的静态文件服务器：&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;highlight None&quot;&gt;&lt;pre&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;kr&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Control.Applicative&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;kr&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Data.Maybe&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fromMaybe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;listToMaybe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;kr&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;System.Environment&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getArgs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;kr&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Network.Wai.Handler.Warp&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;kr&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Network.Wai.Application.Static&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;staticApp&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;                                      &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;defaultFileServerSettings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;IO&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;()&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;do&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;    &lt;span class=&quot;n&quot;&gt;port&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fromMaybe&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;3000&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;listToMaybe&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getArgs&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;    &lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;port&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;staticApp&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;defaultFileServerSettings&lt;/span&gt;
&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;id3&quot;&gt;
&lt;h2&gt;特性&lt;/h2&gt;
&lt;p&gt;一个完善的静态文件服务器：&lt;/p&gt;
&lt;ol class=&quot;arabic simple&quot;&gt;
&lt;li&gt;能以高阶函数的方式定制文件查找逻辑&lt;/li&gt;
&lt;li&gt;根据文件扩展名产生mimetype&lt;/li&gt;
&lt;li&gt;304响应，支持If-Modified-Since，支持If-None-Match匹配文件哈希值&lt;/li&gt;
&lt;li&gt;目录末尾自动添加'/' ，自动查找可配置的index文件等等。&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;id4&quot;&gt;
&lt;h2&gt;性能&lt;/h2&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;环境：Thinkpad X61, T8100 双核，Linux 2.6.38，GHC 7.2.1&lt;/li&gt;
&lt;li&gt;编译选项： &lt;tt class=&quot;docutils literal&quot;&gt;ghc &lt;span class=&quot;pre&quot;&gt;-O3&lt;/span&gt; &lt;span class=&quot;pre&quot;&gt;-threaded&lt;/span&gt; Main.hs&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;执行选项： &lt;tt class=&quot;docutils literal&quot;&gt;./Main +RTS &lt;span class=&quot;pre&quot;&gt;-N1&lt;/span&gt; &lt;span class=&quot;pre&quot;&gt;-qa&lt;/span&gt;&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;对照nginx：worker 1, sendfile on&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;因为我这个破本只有两个核，一个用来运行 &lt;cite&gt;ab&lt;/cite&gt; ，一个可以用来运行web server，所以上面都只配置一个worker进程。&lt;/p&gt;
&lt;p&gt;测试命令： &lt;tt class=&quot;docutils literal&quot;&gt;ab &lt;span class=&quot;pre&quot;&gt;-c&lt;/span&gt; 100 &lt;span class=&quot;pre&quot;&gt;-n&lt;/span&gt; 100000 &lt;span class=&quot;pre&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;pre&quot;&gt;http://localhost:3000/test.html&lt;/span&gt;&lt;/tt&gt;
测试6次，平均每秒请求数分别为：&lt;/p&gt;
&lt;pre class=&quot;literal-block&quot;&gt;
1 7174.23
2 6946.33
3 6120.31
4 6819.33
5 7373.51
6 6776.65
&lt;/pre&gt;
&lt;p&gt;对比nginx：&lt;/p&gt;
&lt;pre class=&quot;literal-block&quot;&gt;
1 13543
2 13601.69
3 13512.38
4 13654.39
5 13680.97
6 13630.64
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;warp-pong-test&quot;&gt;
&lt;h2&gt;warp pong test&lt;/h2&gt;
&lt;p&gt;顺便再测下warp，把静态文件app去掉，换上一个最简单的app：&lt;/p&gt;
&lt;div class=&quot;highlight None&quot;&gt;&lt;pre&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;cm&quot;&gt;{-# LANGUAGE OverloadedStrings #-}&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;kr&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Control.Applicative&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;kr&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Data.Maybe&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fromMaybe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;listToMaybe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;kr&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;System.Environment&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;getArgs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;kr&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Network.HTTP.Types&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;kr&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Network.Wai&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;kr&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Network.Wai.Handler.Warp&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;kr&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Blaze.ByteString.Builder&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fromByteString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;nf&quot;&gt;pong&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Application&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;nf&quot;&gt;pong&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;req&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ResponseBuilder&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;                      &lt;span class=&quot;n&quot;&gt;statusOK&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;                      &lt;span class=&quot;p&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Content-Type&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;text/plain&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;                      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fromByteString&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;pong&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;IO&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;()&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;do&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;    &lt;span class=&quot;n&quot;&gt;port&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fromMaybe&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;3000&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;listToMaybe&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getArgs&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;    &lt;span class=&quot;n&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;port&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pong&lt;/span&gt;
&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;相同条件下测试，平均每秒请求数为：&lt;/p&gt;
&lt;pre class=&quot;literal-block&quot;&gt;
1 22184.93
2 22232.89
3 22150.83
4 22189.02
5 22267.33
6 22125.08
&lt;/pre&gt;
&lt;p&gt;nginx的话，好像没有办法构造一个等价测试案例，我配置了一个最简单的server block：&lt;/p&gt;
&lt;pre class=&quot;literal-block&quot;&gt;
server {
    server_name localhost;
    location = / {
    }
}
&lt;/pre&gt;
&lt;p&gt;然后测试 &lt;a class=&quot;reference external&quot; href=&quot;http://localhost/&quot;&gt;http://localhost/&lt;/a&gt; 这个 404 的响应，结果跟上面nginx返回静态文件的结果类似。&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;id5&quot;&gt;
&lt;h2&gt;结论&lt;/h2&gt;
&lt;p&gt;warp pong 测试结果很惊人，看来 static app 还有不小的优化空间的。nginx主要是用来做个对照，没看过nginx代码，不一定公平。期待大家在不同环境下去测试测试，看结果如何。&lt;/p&gt;
&lt;/div&gt;</description>
	<pubDate>Sat, 12 Nov 2011 00:00:00 +0000</pubDate>
</item>
<item>
	<title>@delphij: 有关&quot;非正常终止&quot;</title>
	<guid>tag:blog.delphij.net,2011://2.2135</guid>
	<link>https://blog.delphij.net/2011/11/post-607.html</link>
	<description>&lt;p&gt;多年以前在 &lt;a href=&quot;http://www.usenix.org/&quot;&gt;USENIX&lt;/a&gt; HotOS 2003 论文集中看到了 &lt;a href=&quot;http://www.usenix.org/events/hotos03/tech/candea.html&quot;&gt;一篇&lt;/a&gt; 关于 &quot;Crash only software&quot; 的论文，当时有一些想法，但很多没有认真地实践。最近做的东西用到的这方面的设计方法比较多，总结一下写出来。&lt;/p&gt;

&lt;p&gt;在设计系统时，很多时候我们会花很多的精力去考虑正常终止的情况，对于希望尽可能少出现 downtime 的系统来说，这很可能是不必要的。&lt;/p&gt;

&lt;p&gt;简而言之，程序有两种终止方式，正常的和不正常的；正常的终止是可预期的，非正常终止不一定发生在什么时候----因为程序设计缺陷、系统管理员杀掉、硬件故障如电源出现问题，等等。&lt;/p&gt;

&lt;p&gt;很多时候处理正常终止所需的代价要比非正常终止来的更大。例如在正常的 OS 关机过程中，内核需要通知所有的服务进程退出（这一点目前还是必要的，因为不是所有的程序都设计了从非正常停机中恢复）、通知其他节点自己下线了、甚至某些早期的 Windows 版本还会关闭网络连接，等等，最后还要把内存中到目前为止还没写盘的数据刷到磁盘上，然后再停止运行。而恢复时，则往往会有一些技术来帮助系统尽快地恢复到可以运行的状态，许多时候，在崩溃后引导系统和在正常关闭后引导系统所需的时间是非常接近的。&lt;/p&gt;

&lt;p&gt;这造成了一个很奇怪的现象：一方面，我们花费了相当多的时间精力去撰写正常关机所需的代码，而另一方面，这些代码的存在往往会导致系统恢复的时间变得更慢一些。（这篇论文写于 2003 年，其中举了一些实际的例子，如 RedHat 8 正常重启所需要的时间是104秒，而非正常重启则只需75秒；JBoss 3.0分别是47秒对39秒，Windows XP则是61秒对48秒）。还有就是，增加的这些复杂的代码对于长时间运行的系统实际上是很少用到的，系统能够正常地持续运行的时间越长，这些代码就越少会执行到。&lt;/p&gt;

&lt;p&gt;因此，对于很多互联网应用来说，既然有那么多的可能性导致异常终止没办法避免，更好的设计就应该是程序中只去考虑非正常终止的问题。程序把启动过程也作为异常终止之后的恢复来实现，而正常终止直接让程序崩溃就可以了，主要的精力应该放到&quot;让恢复过程变得更快和更可靠&quot;以及&quot;让程序运行的过程中任何一个点发生的异常终止都不会导致恢复出现问题&quot;两件事上。&lt;/p&gt;

&lt;p&gt;&lt;b&gt;如何实现&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;原文中列举了一些实现策略，下面是我自己的一些总结：&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;需要持久保存的状态由专用的组件来管理，避免在应用逻辑中直接操作；&lt;/li&gt;
	&lt;li&gt;持久化组件只考虑存储的一致性，可以采取 Copy-on-write 和异步写操作之前先同步写日志等方法来改善恢复速度；&lt;/li&gt;
	&lt;li&gt;分布式系统中，对方未确认数据已经到了可靠的地方，就不要认为处理已经完成；远程调用皆设超时并做对应处理；调用者同时也作为监督者，在认为服务出现问题时可发起重启服务的请求；&lt;/li&gt;
	&lt;li&gt;组件之间尽量隔离（当然这也是面向对象设计的相当基本的要求），避免接口以外的直接交互；&lt;/li&gt;
	&lt;li&gt;对资源使用进行限制，例如通过 OS 限制进程能够使用的内存和 CPU 时间以及实际运行的最长时间等等；&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;做到这些以后直接将正常停止改为 kill -9 即可。当然，尽量避免程序 bug 导致的崩溃仍然是非常重要的。&lt;/p&gt;</description>
	<pubDate>Thu, 10 Nov 2011 07:23:47 +0000</pubDate>
</item>
<item>
	<title>@limodou: sphinx i18nµÄÖ§³Ö</title>
	<guid permalink="False">http://hi.baidu.com/limodou/blog/item/bf72d4395118ceef3a87ceb3.html</guid>
	<link>http://hi.baidu.com/limodou/blog/item/bf72d4395118ceef3a87ceb3.html</link>
	<description>&lt;p&gt;Ê¹ÓÃSpninxÊÇÖ§³Öi18nµÄ£¬ÎÄµµÔÚ&lt;a href=&quot;http://sphinx.pocoo.org/latest/intl.html&quot; target=&quot;_blank&quot;&gt;ÕâÀï&lt;/a&gt;¡£&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span&gt;Ò»¡¢·­Òë&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;¾­¹ýÎÒµÄÊÔÑé£¬¾ßÌåµÄÃüÁî¾ÍÊÇ£º&lt;/p&gt;&lt;p&gt;sphinx-build&amp;nbsp;-b gettext -d ../locale/doctrees ./ ../locale/en&lt;/p&gt;&lt;p&gt;-b gettext ±íÊ¾ÒªÉú³Épot¸ñÊ½&lt;/p&gt;&lt;p&gt;-d ../locale/doctrees ºÃÏóÊÇ»º´æ&lt;/p&gt;&lt;p&gt;./ Ô´ÎÄ¼þÄ¿Â¼&lt;/p&gt;&lt;p&gt;../locale/en Êä³öÄ¿Â¼&lt;/p&gt;&lt;p&gt;Õâ¸öÃüÁîÊÇ¿¼ÂÇÒÔÏÂÄ¿Â¼½á¹¹£º&lt;/p&gt;&lt;p&gt;/project&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; /docs&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; #you are here&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; /locale&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; /en&lt;/p&gt;&lt;p&gt;ÄãÔÚdocsÄ¿Â¼ÏÂÀ´½øÐÐ²Ù×÷¡£Éú³Épotºó¾Í¿ÉÒÔ·­ÒëÁË¡£&lt;/p&gt;&lt;p&gt;ÒÔÉÏÃæÎªÀý£¬·­ÒëÍêµÄPOÎÄ¼þ·Åµ½ locale/en/LC_MESSAGES ÏÂ£¬Í¬Ê±Éú³ÉmoÎÄ¼þ¡£&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span&gt;¶þ¡¢Éú³ÉÎÄµµ&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;ÕâÑùmo×¼±¸Íê³É¡£ÏÂÃæÔÙ´ÎÍ¨¹ýÕý³£µÄ·­ÒëÀ´Éú³ÉÄ¿±ê½á¹û£¬Èçhtml¸ñÊ½ÎÄµµ¡£&lt;/p&gt;&lt;p&gt;Ê×ÏÈÒª¼ì²éconf.pyÖÐÊÇ·ñÓÐlocale_dirsµÄÅäÖÃ£¬Èç¹ûÃ»ÓÐ£¬ÔòÌí¼Ó½øÈ¥:&lt;/p&gt;&lt;p&gt;locale_dirs = ['../locale']&lt;/p&gt;&lt;p&gt;ÕâÀï¿ÉÒÔÌí¼Ó¶à¸ö¡£È»ºó£¬»òÕßÖ±½ÓÐÞ¸Äconf.pyÖÐµÄlanaguageµÄÖµÎªÄ¿±êÓïÑÔ£¬»òÕßÔÚ±àÒëÊ±ÔÚÃüÁîÐÐÀ´Ö¸¶¨£¬Èç£º&lt;/p&gt;&lt;p&gt;sphinx-build -b html -d ../html/doctrees -D language=zh_CN ./ ../html&lt;/p&gt;&lt;p&gt;ÕâÀï²ÎÊý½âÊÍÒ»ÏÂ£º&lt;/p&gt;&lt;p&gt;-b html ½«Éú³Éhtml¸ñÊ½ÎÄµµ&lt;/p&gt;&lt;p&gt;-d ../html/doctrees »º´æÄ¿Â¼£¬ÕâÀïºÍlocaleÒª²»Í¬£¬²»È»»á±¨´í&lt;/p&gt;&lt;p&gt;-D language=zh_CN ÔÚÃüÁîÐÐÖ¸¶¨ÐÞ¸ÄÅäÖÃÖÐµÄlanaugeµÄÖµ£¬ÕâÀïÎªzh_CN¡£&lt;/p&gt;&lt;p&gt;&lt;/p&gt; 
		
		&lt;br /&gt;&lt;b&gt;Àà±ð£º&lt;/b&gt;&lt;a href=&quot;http://hi.baidu.com/limodou/blog/category/Python&quot;&gt;Python&lt;/a&gt;&amp;nbsp;&lt;a href=&quot;http://hi.baidu.com/limodou/blog/item/bf72d4395118ceef3a87ceb3.html#comment&quot;&gt;²é¿´ÆÀÂÛ&lt;/a&gt;</description>
	<pubDate>Thu, 10 Nov 2011 00:00:00 +0000</pubDate>
</item>
<item>
	<title>@limodou: UliPad 4.1ÒÑ¾­·¢²¼</title>
	<guid permalink="False">http://hi.baidu.com/limodou/blog/item/17f00eb374b0aebbd8335a36.html</guid>
	<link>http://hi.baidu.com/limodou/blog/item/17f00eb374b0aebbd8335a36.html</link>
	<description>&lt;p&gt;Ò²Ã»Ê²Ã´ÌØ±ðµÄ¸üÐÂ£¬²»¹ý°ÑÒÔÇ°»ýÀÛµÄ¶«Î÷Éú³ÉÁËÒ»¸ö°æ±¾¡£&lt;/p&gt;&lt;p&gt;&lt;ol&gt;&lt;li&gt;Upgrade winpdb version to 1.4.8&lt;/li&gt;&lt;li&gt;Improve Edit-&amp;gt;Format-&amp;gt;Wrap Text functionality to suit for reStructuredText wrap&lt;/li&gt;&lt;li&gt;Made memo file configurable thanks to Helio Perroni Filho&lt;/li&gt;&lt;li&gt;Add Bash support thanks to Helio Perroni Filho&lt;/li&gt;&lt;li&gt;Add some useful methods to support scripts files. Such as emptytab, newtab, etc. thanks to Helio Perroni Filho&lt;/li&gt;&lt;li&gt;Add Lua support thanks to zhangchunlin&lt;/li&gt;&lt;li&gt;Improve python file detect according to #! /usr/bin/env python thanks to zhangchunlin&lt;/li&gt;&lt;li&gt;Add default color theme support, you can set it in Preference&lt;/li&gt;&lt;li&gt;Add Create Python Package menu in context menu of Directory Browser Window&lt;/li&gt;&lt;li&gt;Improve web2py plugin&lt;/li&gt;&lt;li&gt;Improve regex window, and when you set Unicode flag, it'll automatically convert \uXXXX to unichr&lt;/li&gt;&lt;li&gt;Fix strip tailing spaces bug&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&lt;span&gt;ÏÂÔØµØÖ·:&amp;nbsp;&lt;/span&gt;http://ulipad.googlecode.com/files/ulipad.4.1.zip&lt;/div&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;/p&gt; 
		
		&lt;br /&gt;&lt;b&gt;Àà±ð£º&lt;/b&gt;&lt;a href=&quot;http://hi.baidu.com/limodou/blog/category/Ulipad&quot;&gt;Ulipad&lt;/a&gt;&amp;nbsp;&lt;a href=&quot;http://hi.baidu.com/limodou/blog/item/17f00eb374b0aebbd8335a36.html#comment&quot;&gt;²é¿´ÆÀÂÛ&lt;/a&gt;</description>
	<pubDate>Wed, 09 Nov 2011 00:00:00 +0000</pubDate>
</item>
<item>
	<title>@khsing: 一个PHP文件的透过HTTP分发的错误</title>
	<guid>http://blog.khsing.net/?p=452</guid>
	<link>https://blog.khsing.net/2011/11/a-php-file-distribute-error.html</link>
	<description>&lt;p&gt;同事写一个服务安装脚步，有一个PHP的配置文件要在安装时分发，脚步里是用wget来获取这个文件的，不幸的是Apache加载了mod_php，所以分发的文件是那个PHP文件被mod_php解析过的结果，而这种情况下那个PHP文件的执行大多会导致500错误，被分发的文件要么是空要么是Apache的500错误内容或php display error的内容。&lt;/p&gt;
&lt;p&gt;服务安装后又匮乏验证机制，出现这种情况就不为人知，真正出事了才会发现。其实出这个问题是有一定历史原因的，原来配置文件的分发是走s3的，到了国内呢，s3服务变的不可用，同时受网络的限制也就不用s3了，采用HTTP的服务代替了s3，但是一些安装脚本的写法延续了s3时代的写法，只不过以前分发的都是conf之类的文件，这次是个php文件，所以出事了。&lt;/p&gt;
&lt;p&gt;避免这个问题的方法有很多，如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;提供文件分发的HTTP服务不加载解析模块&lt;/li&gt;
&lt;li&gt;配置文件的分发一律走文件分发机制，如puppet等。&lt;/li&gt;
&lt;/ul&gt;</description>
	<pubDate>Mon, 07 Nov 2011 03:57:09 +0000</pubDate>
</item>
<item>
	<title>@khsing: 十年9.11</title>
	<guid>http://blog.khsing.net/?p=316</guid>
	<link>https://blog.khsing.net/2011/09/%e5%8d%81%e5%b9%b49-11.html</link>
	<description>&lt;p&gt;9.11十周年过了好几天了。想想2001年的时候我还在高中，那天下午知道这个消息的时候还是很兴奋的，下课后就去网吧看相关新闻，现在想不大起来当时的心情了，可能有一些高兴，可能有一些伤感，也可能更多的是震撼。&lt;/p&gt;
&lt;p&gt;现在来看这件事的时候，我想当时美国人的心情和我们2008年遭遇5.12地震的心情是类似的，一个是人祸，一个是天灾。10年过去了，那一场袭击的策划者拉登已经被美国人给干掉了。以因果论来讲，拉登也算是有这一果。要说美国又因什么得的9.11这个果，那我还真想不明白。即便是有仇有很，那我觉得也是冤有头债有主，该找谁你找谁，别拿着手无寸铁的老百姓当枪使。我讨厌这些故意牵涉无辜的行为。这就和战场上赶着老百姓走在阵前是一个道理。&lt;/p&gt;
&lt;p&gt;美国通过十年的反恐战争，也许并不能避免美国再次受到袭击，但是美国政府是在向着保卫国民安全的目标前行，他们在努力的避免悲剧的再次发生。9.11的纪念活动看起来很简单，也很严肃，当然这也是一件严肃的事情，他们细细的统计了那场灾难的遇难者，他们也惩戒了行凶者。&lt;/p&gt;
&lt;p&gt;既然提到了5.12，那我也希望我们能细细的统计遇难者，能修建起不倒的校舍，希望十年后我们看到的不是遗憾，同样希望我们能严肃的对待严肃的事情。&lt;/p&gt;
&lt;p&gt;btw: 凤凰网这个“&lt;a href=&quot;http://news.ifeng.com/world/special/911shizhounian/jilupian.shtml&quot;&gt;再看中国人的美国观&lt;/a&gt;”专题做的不错。&lt;/p&gt;</description>
	<pubDate>Mon, 07 Nov 2011 02:16:18 +0000</pubDate>
</item>
<item>
	<title>@khsing: Steve Jobs is gone</title>
	<guid>http://blog.khsing.net/?p=325</guid>
	<link>https://blog.khsing.net/2011/10/steve-jobs-is-gone.html</link>
	<description>&lt;p&gt;Steven Paul Jobs (1955 – 2011) is gone while I am waiting for a bus. Thanks for his contribution for the world. R.I.P Steve Jobs. &lt;/p&gt;
&lt;p&gt;Buddha and God might need some Apple product.&lt;/p&gt;</description>
	<pubDate>Mon, 07 Nov 2011 02:15:58 +0000</pubDate>
</item>
<item>
	<title>@khsing: National day</title>
	<guid>http://blog.khsing.net/2011/10/national-day.html</guid>
	<link>https://blog.khsing.net/2011/10/national-day.html</link>
	<description>&lt;p&gt;推翻帝制的先驱们永垂不朽，为中华民族民主革命奋斗毕生的先烈们永垂不朽。&lt;/p&gt;</description>
	<pubDate>Mon, 07 Nov 2011 02:15:05 +0000</pubDate>
</item>
<item>
	<title>@khsing: mark RAID-10 vs 01</title>
	<guid>http://blog.khsing.net/?p=345</guid>
	<link>https://blog.khsing.net/2011/10/mark-raid-10vs01.html</link>
	<description>&lt;p&gt;&lt;a href=&quot;http://www.thegeekstuff.com/2011/10/raid10-vs-raid01/&quot;&gt;The Geek Stuff: RAID 10 vs RAID 01&lt;/a&gt;的内容，我MARK一下。遇到选Raid 10还是Raid 01的时候永远选Raid 10，因为Raid 10比01在容量和性能一致的情况下提供了更多的容错性。&lt;/p&gt;</description>
	<pubDate>Mon, 07 Nov 2011 01:57:29 +0000</pubDate>
</item>
<item>
	<title>@huangyi: 无题</title>
	<guid permalink="False">http://yi-programmer.com/blog/2011-11-03_.html</guid>
	<link>http://yi-programmer.com/blog/2011-11-03_.html</link>
	<description>&lt;p&gt;写 parser 的时候需要写这样的代码：&lt;/p&gt;
&lt;div class=&quot;highlight None&quot;&gt;&lt;pre&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;nf&quot;&gt;takeTill&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pred&lt;/span&gt;
&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;其中 &lt;cite&gt;pred&lt;/cite&gt; 是个判别函数，签名为： &lt;cite&gt;Char -&amp;gt; Bool&lt;/cite&gt; 。 &lt;cite&gt;takeTill&lt;/cite&gt; 的作用就是一直解析到 &lt;cite&gt;pred&lt;/cite&gt; 返回 &lt;cite&gt;True&lt;/cite&gt; 为止。&lt;/p&gt;
&lt;p&gt;比如你要解析到下一个 &lt;cite&gt;&amp;gt;&lt;/cite&gt; 或者 &lt;cite&gt;=&lt;/cite&gt; ，你就写：&lt;/p&gt;
&lt;div class=&quot;highlight None&quot;&gt;&lt;pre&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;nf&quot;&gt;takeTill&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inClass&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;gt;=&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;想解析到下一个空白字符为止，就写：&lt;/p&gt;
&lt;div class=&quot;highlight None&quot;&gt;&lt;pre&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;nf&quot;&gt;takeTill&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isSpace&lt;/span&gt;
&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;想解析各种空白字符呢，就在上面的基础上取个反：&lt;/p&gt;
&lt;div class=&quot;highlight None&quot;&gt;&lt;pre&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;nf&quot;&gt;takeTill&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isSpace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这个例子是想提醒大家 &lt;cite&gt;isSpace&lt;/cite&gt; 是个函数，所以这里需要进行函数组合，而不是直接调用 &lt;cite&gt;not&lt;/cite&gt; 。&lt;/p&gt;
&lt;p&gt;那我今天想说的是什么呢。现在我想解析到下一个 &lt;cite&gt;&amp;gt;&lt;/cite&gt; 或 &lt;cite&gt;=&lt;/cite&gt; 或空白字符为止，也就是说需要把前两个拼起来，直接写起来是这样的：&lt;/p&gt;
&lt;div class=&quot;highlight None&quot;&gt;&lt;pre&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;nf&quot;&gt;takeTill&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inClass&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;gt;=&amp;quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isSpace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;也不麻烦，只不过对于患有 &lt;a class=&quot;reference external&quot; href=&quot;http://www.douban.com/group/purecoding/&quot;&gt;代码洁癖&lt;/a&gt; 的我来说，视觉上还不太给力。于是，我继续重构如下：&lt;/p&gt;
&lt;div class=&quot;highlight None&quot;&gt;&lt;pre&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;nf&quot;&gt;takeTill&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inClass&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;gt;=&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isSpace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;多实现一个组合函数 &lt;cite&gt;||.&lt;/cite&gt; ：&lt;/p&gt;
&lt;div class=&quot;highlight None&quot;&gt;&lt;pre&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;把两个判别函数组合成一个新的判别函数。&lt;/p&gt;
&lt;p&gt;为了将它推广到其他的组合操作，我们进一步泛化一个通用函数，姑且取名叫 &lt;cite&gt;fn&lt;/cite&gt; 吧 ：&lt;/p&gt;
&lt;div class=&quot;highlight None&quot;&gt;&lt;pre&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;nf&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;nf&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;前面的 &lt;cite&gt;||.&lt;/cite&gt; 就成为：&lt;/p&gt;
&lt;div class=&quot;highlight None&quot;&gt;&lt;pre&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;大功告成，正当我准备好好欣赏一下最终的产物 &lt;cite&gt;fn&lt;/cite&gt; 的时候，却突然发现， &lt;cite&gt;fn&lt;/cite&gt; 的作用不就是把 &lt;cite&gt;b&lt;/cite&gt; 层面的二元函数提升到 &lt;cite&gt;(a -&amp;gt; b)&lt;/cite&gt; 层面么，正如 &lt;cite&gt;||&lt;/cite&gt; 和 &lt;cite&gt;||.&lt;/cite&gt; 都是或操作，只不过一个作用在 &lt;cite&gt;Bool&lt;/cite&gt; 值层面，一个作用在 &lt;cite&gt;a -&amp;gt; Bool&lt;/cite&gt; 判别函数层面。如此通用的概念，我意识到我很可能重造轮子了。&lt;/p&gt;
&lt;p&gt;于是我请 &lt;a class=&quot;reference external&quot; href=&quot;http://www.haskell.org/haskellwiki/Lambdabot&quot;&gt;lambdabot&lt;/a&gt; mm帮我诊断一下：&lt;/p&gt;
&lt;div class=&quot;highlight None&quot;&gt;&lt;pre&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;huangyi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pl&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lambdabot&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;liftM2&lt;/span&gt;
&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;果然，小mm告诉我， &lt;cite&gt;fn&lt;/cite&gt; 其实就是 &lt;cite&gt;liftM2&lt;/cite&gt; 。 &lt;cite&gt;liftM2&lt;/cite&gt; 是专门用来把二元函数提升到 &lt;cite&gt;Monad&lt;/cite&gt; 中去的，而 &lt;cite&gt;((-&amp;gt;) a)&lt;/cite&gt; 正是 &lt;cite&gt;Monad&lt;/cite&gt; 的实例。&lt;/p&gt;
&lt;div class=&quot;highlight None&quot;&gt;&lt;pre&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;kr&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;where&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;    &lt;span class=&quot;n&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;const&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;    &lt;span class=&quot;c1&quot;&gt;-- (&amp;gt;&amp;gt;=) :: (a -&amp;gt; b) -&amp;gt; (b -&amp;gt; a -&amp;gt; c) -&amp;gt; (a -&amp;gt; c)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;    &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;nf&quot;&gt;liftM2&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Monad&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;nf&quot;&gt;liftM2&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mb&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;do&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;    &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ma&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;    &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mb&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;    &lt;span class=&quot;n&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;`&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;其实只需要提升一下抽象层次的话，还不需动用 &lt;cite&gt;Monad&lt;/cite&gt; 这样的大杀器， &lt;cite&gt;Applicative&lt;/cite&gt; 也可以搞定。&lt;/p&gt;
&lt;div class=&quot;highlight None&quot;&gt;&lt;pre&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;kr&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Applicative&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;where&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;    &lt;span class=&quot;c1&quot;&gt;-- &amp;lt;$&amp;gt; :: (b -&amp;gt; c) -&amp;gt; (a -&amp;gt; b) -&amp;gt; (a -&amp;gt; c)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;    &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;    &lt;span class=&quot;c1&quot;&gt;-- (&amp;lt;*&amp;gt;) :: (a -&amp;gt; b -&amp;gt; c) -&amp;gt; (a -&amp;gt; b) -&amp;gt; (a -&amp;gt; c)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;    &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;用 &lt;cite&gt;Applicative&lt;/cite&gt; 的话，前面的 &lt;cite&gt;fn&lt;/cite&gt; 就等价于 &lt;cite&gt;liftA2&lt;/cite&gt; 了。&lt;/p&gt;
&lt;div class=&quot;highlight None&quot;&gt;&lt;pre&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;nf&quot;&gt;liftA2&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Application&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;line&quot; id=&quot;LC1&quot;&gt;&lt;span class=&quot;nf&quot;&gt;liftA2&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fa&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fb&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;$&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fa&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fb&lt;/span&gt;
&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;绕了一圈，最后还是没逃出Haskell最基本的框框。&lt;/p&gt;</description>
	<pubDate>Thu, 03 Nov 2011 00:00:00 +0000</pubDate>
</item>
<item>
	<title>@delphij: 关系代数中的除</title>
	<guid>tag:blog.delphij.net,2011://2.2134</guid>
	<link>https://blog.delphij.net/2011/10/post-606.html</link>
	<description>&lt;p&gt;简单记一笔，感谢 Stanford 的 &lt;a href=&quot;http://www.db-class.org/&quot;&gt;数据库入门&lt;/a&gt; 课程课后作业 (有人在 StackOverflow&lt;a href=&quot;http://stackoverflow.com/questions/7821695/how-to-find-all-pizzerias-that-serve-every-pizza-eaten-by-people-over-30&quot;&gt;提问&lt;/a&gt;)。复习一下。&lt;/p&gt;

&lt;p&gt;应用场景：找出一家能制作全部30岁以上人士需要的Pizza种类的Pizza店。&lt;/p&gt;

&lt;p&gt;在示范数据库中给出的四个关系：&lt;/p&gt;

&lt;pre&gt;
Person(name, age, gender)       // name is a key
Frequents(name, pizzeria)       // [name,pizzeria] is a key
Eats(name, pizza)               // [name,pizza] is a key
Serves(pizzeria, pizza, price)  // [pizzeria,pizza] is a key
&lt;/pre&gt;

&lt;p&gt;通过一些计算，我们可以得到两个投影：&lt;/p&gt;

&lt;p&gt;投影 A：&lt;/p&gt;

&lt;pre&gt;
Chicago Pizza | cheese  | cheese
Chicago Pizza | cheese  | supreme
Chicago Pizza | supreme | cheese
Chicago Pizza | supreme | supreme
Dominos       | cheese  | cheese
Dominos       | cheese  | supreme
&lt;/pre&gt;

&lt;p&gt;投影 B：&lt;/p&gt;

&lt;pre&gt;
cheese  | cheese
cheese  | supreme
supreme | cheese
supreme | supreme
&lt;/pre&gt;

&lt;p&gt;需要的结果是 A/B：&lt;/p&gt;

&lt;pre&gt;
Chicago Pizza
&lt;/pre&gt;

&lt;p&gt;有时，数据库系统并不直接提供关系除操作。这时可以用下面的方法替代：&lt;/p&gt;

&lt;p&gt;首先，生成所有 Pizza 店，以及所有 Pizza 类型的笛卡尔积，记为T：&lt;/p&gt;

&lt;p&gt;然后，计算该笛卡尔积和 Serves 上的投影R： π{pizzeria,pizza}(Serves) 之差：T-R。&lt;/p&gt;

&lt;p&gt;这样，T-R得到的结果便是不存在的 pizzeria,pizza 组合。从其中取 π{pizzeria}，然后从全部 pizzeria 中扣掉，即可得到希望的结果了。&lt;/p&gt;</description>
	<pubDate>Mon, 31 Oct 2011 05:25:04 +0000</pubDate>
</item>
<item>
	<title>@limodou: ¹ØÓÚÈçºÎÊ¹ÓÃUpload App½øÐÐÎÄ¼þÉÏ´«µÄÎÄµµ</title>
	<guid permalink="False">http://hi.baidu.com/limodou/blog/item/bf72d439fbafb4ef3b87ce09.html</guid>
	<link>http://hi.baidu.com/limodou/blog/item/bf72d439fbafb4ef3b87ce09.html</link>
	<description>²Î¼û http://readthedocs.org/docs/uliweb/en/latest/app_upload.html&lt;p&gt;&lt;/p&gt; 
		
		&lt;br /&gt;&lt;b&gt;Àà±ð£º&lt;/b&gt;&lt;a href=&quot;http://hi.baidu.com/limodou/blog/category/Uliweb&quot;&gt;Uliweb&lt;/a&gt;&amp;nbsp;&lt;a href=&quot;http://hi.baidu.com/limodou/blog/item/bf72d439fbafb4ef3b87ce09.html#comment&quot;&gt;²é¿´ÆÀÂÛ&lt;/a&gt;</description>
	<pubDate>Wed, 26 Oct 2011 00:00:00 +0000</pubDate>
</item>
<item>
	<title>@khsing: 放Amazon的成本</title>
	<guid>http://blog.khsing.net/?p=341</guid>
	<link>https://blog.khsing.net/2011/10/%e6%94%beamazon%e7%9a%84%e6%88%90%e6%9c%ac.html</link>
	<description>&lt;p&gt;&lt;a href=&quot;http://highscalability.com&quot;&gt;HS&lt;/a&gt;放了一个&lt;a href=&quot;http://highscalability.com/blog/2011/10/24/stackexchange-architecture-updates-running-smoothly-amazon-4.html&quot;&gt;StackExchange的构架更新&lt;/a&gt;，其中说到把服务放在Amazon上的成本是自己购买后的4倍。&lt;/p&gt;
&lt;p&gt;我厂也是Amazon的用户，关于我厂为什么用上了Amazon是有一个段子的。话说当年运维部门遇上用户大幅增加的时候一个礼拜都在加班，尽在机房过生活了，人手不够用到老大把自己怀孕的老婆都叫来插网线。后来另一个游戏在上线的时候发现运维部门的资源如此紧张，没办法就硬着头皮试了试Amazon，结果这一试让厂里后来的游戏都放到了Amazon上来了。这是2008年的事了，经过了这几年的成长，现在我厂也要回到自己的数据中心了，甚至已经在Amazon的产品也要回到数据中心了。&lt;/p&gt;
&lt;p&gt;似乎从这两个案子来看，Amazon是适合创业公司在初期资源不足，无暇顾及底层支持的一种选择，一旦业务的增长到了一个阶段，可以腾出手来做优化和成本缩减的时候，离开Amazon就是一个合理的选择了。&lt;/p&gt;
&lt;p&gt;关于我厂的故事，还是&lt;a href=&quot;http://hi.baidu.com/icej/blog/item/97ccd8fc8684cd9eb801a0fe.html&quot;&gt;猫说的多&lt;/a&gt;&lt;/p&gt;</description>
	<pubDate>Tue, 25 Oct 2011 08:36:51 +0000</pubDate>
</item>

</channel>
</rss>

