<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2enclosuresfull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>blog.ouyang.me</title>
	
	<link>http://blog.ouyang.me</link>
	<description />
	<lastBuildDate>Sat, 11 Feb 2012 05:51:51 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/SomethingLastForever" /><feedburner:info uri="somethinglastforever" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><itunes:explicit>no</itunes:explicit><itunes:subtitle></itunes:subtitle><item>
		<title>切换代理的chrome插件</title>
		<link>http://feedproxy.google.com/~r/SomethingLastForever/~3/SFAgq7nERuc/</link>
		<comments>http://blog.ouyang.me/2012/02/chrome-extension-tunnel-switch/#comments</comments>
		<pubDate>Sat, 11 Feb 2012 04:14:50 +0000</pubDate>
		<dc:creator>oylbin</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[chrome]]></category>
		<category><![CDATA[ssh tunnel]]></category>

		<guid isPermaLink="false">http://blog.ouyang.me/?p=643</guid>
		<description><![CDATA[我一直用ssh tunnel翻墙，在firefox下用foxyproxy一直很正常。但是在chrome下就总是悲剧。 我的需求很简单，我需要三种上网模式，并能很方便的在几种模式下切换。 * 完全禁用代理 * 所有的请求都通过ssh tunnel代理 * 能根据网站url自动的决定是否使用ssh tunnel代理(我通过pac文件来实现) Chrome下有个Switchy插件，能够满足前两点需求，但是最后一点，无论是我使用pac文件，还是使用它自身的Auto Mode，都不好使。 前天花1个小时看了一下Switchy的源代码，没看出什么头绪。昨天索性就自己写了一个，发现其实挺简单的。 不得不说，google做的东西就是好，不光chrome本身做得好，连它提供的外部接口使用起来也是方便快捷。 主要参考了三篇文章，都是官网提供的： 入门级教程, 主要了解了开发插件的大致过程，比如怎样加载和更新插件。 关于browserAction的例子，主要了解如何处理插件图标的点击事件，如何给插件设置图标。 chome.proxy接口文档，文档中已经提供了足够丰富的如何设置代理样例代码。 我自己的插件基本上就是在browserAction的例子上改的，然后盗用了Switchy的三张图片。 除去图片一共就三个文件，也没多少代码，全贴出来。 实现的功能就是点击插件按钮时在三种上网模式下依次切换。 而我使用的pac文件的网址，以及ssh tunnel的地址和端口号，都是写死在代码里面的。 manifest.json { "name": "tunnel switch", "version": "1.0", "background_page": "background.html", "permissions": [ "tabs", "http://*/*", "proxy" ], "browser_action": { "name": "Click to change the proxy" }, "content_security_policy": "default-src 'self'" } background.html &#60;!doctype [...]]]></description>
			<content:encoded><![CDATA[<p>我一直用ssh tunnel翻墙，在firefox下用foxyproxy一直很正常。但是在chrome下就总是悲剧。</p>
<p>我的需求很简单，我需要三种上网模式，并能很方便的在几种模式下切换。</p>
<pre><code>* 完全禁用代理
* 所有的请求都通过ssh tunnel代理
* 能根据网站url自动的决定是否使用ssh tunnel代理(我通过pac文件来实现)
</code></pre>
<p>Chrome下有个Switchy插件，能够满足前两点需求，但是最后一点，无论是我使用pac文件，还是使用它自身的Auto Mode，都不好使。<br />
前天花1个小时看了一下Switchy的源代码，没看出什么头绪。昨天索性就自己写了一个，发现其实挺简单的。<br />
不得不说，google做的东西就是好，不光chrome本身做得好，连它提供的外部接口使用起来也是方便快捷。</p>
<p>主要参考了三篇文章，都是官网提供的：</p>
<ol>
<li>
<p><a href="http://code.google.com/chrome/extensions/getstarted.html">入门级教程</a>, 主要了解了开发插件的大致过程，比如怎样加载和更新插件。</p>
</li>
<li>
<p><a href="http://code.google.com/chrome/extensions/samples.html#0262260daf0c8f7b28feff2ef23b05e7abf9d1e0">关于browserAction的例子</a>，主要了解如何处理插件图标的点击事件，如何给插件设置图标。</p>
</li>
<li>
<p><a href="http://code.google.com/chrome/extensions/proxy.html">chome.proxy接口文档</a>，文档中已经提供了足够丰富的如何设置代理样例代码。</p>
</li>
</ol>
<p><a href="http://blog.ouyang.me/wp-content/uploads/2012/02/tunnel_switch.zip">我自己的插件</a>基本上就是在browserAction的例子上改的，然后盗用了Switchy的三张图片。<br />
除去图片一共就三个文件，也没多少代码，全贴出来。<br />
实现的功能就是点击插件按钮时在三种上网模式下依次切换。<br />
而我使用的pac文件的网址，以及ssh tunnel的地址和端口号，都是写死在代码里面的。</p>
<p><span id="more-643"></span></p>
<ol>
<li>
<p>manifest.json</p>
<pre><code>{
  "name": "tunnel switch",
  "version": "1.0",
  "background_page": "background.html",
  "permissions": [
    "tabs", "http://*/*", "proxy"
  ],
  "browser_action": {
      "name": "Click to change the proxy"
  },
  "content_security_policy": "default-src 'self'"
}
</code></pre>
</li>
<li>
<p>background.html</p>
<pre><code>&lt;!doctype html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;Background Page&lt;/title&gt;
    &lt;script src="background.js"&gt;&lt;/script&gt;
  &lt;/head&gt;
  &lt;body&gt;
  &lt;/body&gt;
&lt;/html&gt;
</code></pre>
</li>
<li>
<p>background.js</p>
<pre><code>var currentProxyType = 'pac';

function changeProxy(type){
    currentProxyType = type;
    if(type=='pac'){
        var config = {
          mode: "pac_script",
          pacScript: {
              url:"file:///Users/oylbin/oylbin/proxy.pac?"+(new Date).getTime(),
              mandatory:true
          }
        };
    }else if(type=='tunnel'){
        var config = {
            mode: "fixed_servers",
            rules: {
                singleProxy: {
                                  scheme: "socks5",
                                  host: "127.0.0.1",
                                  port: 8527
                              },
                bypassList: ["foobar.com"]
            }
        };
    }else{
        type='direct';
        var config = {
            mode: "direct"
        };
    }
    chrome.proxy.settings.set({value: config, scope: 'regular'},function() {});
    chrome.browserAction.setIcon({path:type+".png"});
}

function onIconClicked() {
    if(currentProxyType=='pac'){
        changeProxy('tunnel');
    }else if(currentProxyType=='tunnel'){
        changeProxy('direct');
    }else if(currentProxyType=='direct'){
        changeProxy('pac');
    }
}
chrome.browserAction.onClicked.addListener(onIconClicked);
changeProxy('pac');
</code></pre>
</li>
</ol>
<p>最后，提供一个我使用的proxy.pac文件的样例，如果要加网址规则，加到site_list 和 exp_list即可</p>
<pre><code>function FindProxyForURL(url, host)
{
    url = url.toLowerCase();
    host = host.toLowerCase();

    // whole site
    var site_list = [
        'bitsnoop.com'
        ,'blogger.com'
        ,'blogspot.com'
    ];

    var exp_list = [
     'http(s)?://(sites|groups|picasaweb|feedproxy|fusion)\.google\.com/.*',
     'http://www\.google\.com/(((search|url)\?)|analytics|calendar|profile).*',
     'http://[^/]*/search\\?q=cache.*'
    ];

    for(var index = 0;index&lt;site_list.length;index++){
         if(host==site_list[index] ||
             shExpMatch(host, "*." + site_list[index])){
            return "SOCKS5 127.0.0.1:8527";
         }
    }
    for(var index = 0;index&lt;exp_list.length;index++){
        var re = new RegExp(exp_list[index]);
        if(url.match(re)){
            return "SOCKS5 127.0.0.1:8527";
        }
    }
    return "DIRECT";
}
</code></pre>
<img src="http://feeds.feedburner.com/~r/SomethingLastForever/~4/SFAgq7nERuc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ouyang.me/2012/02/chrome-extension-tunnel-switch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<enclosure url="http://blog.ouyang.me/wp-content/uploads/2012/02/tunnel_switch.zip" length="7326" type="application/zip" /><media:content url="http://blog.ouyang.me/wp-content/uploads/2012/02/tunnel_switch.zip" fileSize="7326" type="application/zip" /><itunes:explicit>no</itunes:explicit><itunes:subtitle>我一直用ssh tunnel翻墙，在firefox下用foxyproxy一直很正常。但是在chrome下就总是悲剧。 我的需求很简单，我需要三种上网模式，并能很方便的在几种模式下切换。 * 完全禁用代理 * 所有的请求都通过ssh tunnel代理 * 能根据网站url自动的决定是否使用ssh tunnel代理(我通过pac文件来实现) Chrome下有个Switchy插件，能够满足前两点需求，但是最后一点，无论是我使用pac文件，还是使用它自身的Auto Mode，都不好使。 前天花1个小时看了一下Sw</itunes:subtitle><itunes:summary>我一直用ssh tunnel翻墙，在firefox下用foxyproxy一直很正常。但是在chrome下就总是悲剧。 我的需求很简单，我需要三种上网模式，并能很方便的在几种模式下切换。 * 完全禁用代理 * 所有的请求都通过ssh tunnel代理 * 能根据网站url自动的决定是否使用ssh tunnel代理(我通过pac文件来实现) Chrome下有个Switchy插件，能够满足前两点需求，但是最后一点，无论是我使用pac文件，还是使用它自身的Auto Mode，都不好使。 前天花1个小时看了一下Switchy的源代码，没看出什么头绪。昨天索性就自己写了一个，发现其实挺简单的。 不得不说，google做的东西就是好，不光chrome本身做得好，连它提供的外部接口使用起来也是方便快捷。 主要参考了三篇文章，都是官网提供的： 入门级教程, 主要了解了开发插件的大致过程，比如怎样加载和更新插件。 关于browserAction的例子，主要了解如何处理插件图标的点击事件，如何给插件设置图标。 chome.proxy接口文档，文档中已经提供了足够丰富的如何设置代理样例代码。 我自己的插件基本上就是在browserAction的例子上改的，然后盗用了Switchy的三张图片。 除去图片一共就三个文件，也没多少代码，全贴出来。 实现的功能就是点击插件按钮时在三种上网模式下依次切换。 而我使用的pac文件的网址，以及ssh tunnel的地址和端口号，都是写死在代码里面的。 manifest.json { "name": "tunnel switch", "version": "1.0", "background_page": "background.html", "permissions": [ "tabs", "http://*/*", "proxy" ], "browser_action": { "name": "Click to change the proxy" }, "content_security_policy": "default-src 'self'" } background.html &amp;#60;!doctype [...]</itunes:summary><itunes:keywords>programming, chrome, ssh tunnel</itunes:keywords><feedburner:origLink>http://blog.ouyang.me/2012/02/chrome-extension-tunnel-switch/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=chrome-extension-tunnel-switch</feedburner:origLink></item>
		<item>
		<title>mac os中针对ssd的优化</title>
		<link>http://feedproxy.google.com/~r/SomethingLastForever/~3/mwpdmBETj9w/</link>
		<comments>http://blog.ouyang.me/2012/02/ssd-tuning-in-max-os-x/#comments</comments>
		<pubDate>Sat, 11 Feb 2012 03:08:34 +0000</pubDate>
		<dc:creator>oylbin</dc:creator>
				<category><![CDATA[system administration]]></category>

		<guid isPermaLink="false">http://blog.ouyang.me/?p=639</guid>
		<description><![CDATA[打开trim 所谓trim，是指删除文件时通知SSD，这些文件已经删除，对应的block可以释放。这样可以避免下次再向这些block写入时的性能下降。 mac原装的SSD是支持trim的，但是自己装的SSD默认不会开启这个功能，有个叫trim enabler的工具可以做这件事情。 挂在ssd时加入noatime的参数 atime(access time)是inode中标记文件上一次访问时间的字段。默认情况下，每次访问（读或者写）一个文件时，操作系统都会更新该文件的atime值。 因为atime并不是一个很重要的数值，一般服务器性能优化的时候都会考虑加挂载磁盘的时候加上noatime参数，这样可以在一定程度上提升性能。 至于挂载SSD时设置这个参数有什么更多的好处，我也说不上，但总归没有坏处。 修改方式，使用sudo vifs修改 /etc/fstab 文件 UUID=BB30FFEF-7E28-3F02-AC9F-9B9888176D59 / hfs auto,rw,noatime 0 1 关闭mdworker, 它是spotlight用于建立文件索引的进程。我用quicksilver, 不用spotlight, 所以把它禁用掉。 sudo mdutil -a -i off 关闭待机时写入硬盘 在系统的电源管理设置中把&#8221;put hard disk to sleep when possible&#8221;选项关掉。]]></description>
			<content:encoded><![CDATA[<ol>
<li>
<p>打开trim</p>
<p>所谓trim，是指删除文件时通知SSD，这些文件已经删除，对应的block可以释放。这样可以避免下次再向这些block写入时的性能下降。<br />
mac原装的SSD是支持trim的，但是自己装的SSD默认不会开启这个功能，有个叫<a href="http://www.groths.org/?tag=enabler">trim enabler</a>的工具可以做这件事情。</p>
</li>
<li>
<p>挂在ssd时加入noatime的参数</p>
<p>atime(access time)是inode中标记文件上一次访问时间的字段。默认情况下，每次访问（读或者写）一个文件时，操作系统都会更新该文件的atime值。<br />
因为atime并不是一个很重要的数值，一般服务器性能优化的时候都会考虑加挂载磁盘的时候加上noatime参数，这样可以在一定程度上提升性能。<br />
至于挂载SSD时设置这个参数有什么更多的好处，我也说不上，但总归没有坏处。</p>
<p>修改方式，使用<code>sudo vifs</code>修改 /etc/fstab 文件</p>
<pre><code>UUID=BB30FFEF-7E28-3F02-AC9F-9B9888176D59 /     hfs auto,rw,noatime 0 1
</code></pre>
</li>
<li>
<p>关闭mdworker, 它是spotlight用于建立文件索引的进程。我用quicksilver, 不用spotlight, 所以把它禁用掉。</p>
<p>sudo mdutil  -a -i off</p>
</li>
<li>
<p>关闭待机时写入硬盘</p>
</li>
<li>
<p>在系统的电源管理设置中把&#8221;put hard disk to sleep when possible&#8221;选项关掉。</p>
</li>
</ol>
<img src="http://feeds.feedburner.com/~r/SomethingLastForever/~4/mwpdmBETj9w" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ouyang.me/2012/02/ssd-tuning-in-max-os-x/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ouyang.me/2012/02/ssd-tuning-in-max-os-x/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=ssd-tuning-in-max-os-x</feedburner:origLink></item>
		<item>
		<title>刷火车票的shell脚本</title>
		<link>http://feedproxy.google.com/~r/SomethingLastForever/~3/o-2q9GOCQuQ/</link>
		<comments>http://blog.ouyang.me/2012/01/script-to-order-train-ticket/#comments</comments>
		<pubDate>Mon, 09 Jan 2012 00:14:20 +0000</pubDate>
		<dc:creator>oylbin</dc:creator>
				<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://blog.ouyang.me/?p=627</guid>
		<description><![CDATA[要用这个脚本得懂点shell和web开发。 window下面需要装cygwin才有shell环境。 用法: 先把脚本存下来，比如起名叫order.sh。 登陆网站，取得当前登陆的cookie，填到脚本里面，这个也可以用firebug取，登陆网站之后，验证码页面请求的header里面都能看到cookie那一行。 cookie: JSESSIONID=6009B4610F436D8023126256FB598BDD; BIGipServerotsweb=2413035786.48160.0000 手动把里面的订票参数改掉。主要就是座位，日期，订票人，车次的信息。 车次的信息需要从网页源码或者页面请求参数里面取。比如从查询页面点击预定按钮进入预定页面时，会向这个页面发POST请求 https://dynamic.12306.cn/otsweb/order/querySingleAction.do?method=submutOrderRequest 用firebug能看到这些参数 train_no=240000K2670V station_train_code=K267 from_station_telecode=BXP from_station_name="北京西" to_station_telecode=LEQ to_station_name="澧县" start_time="12:10" end_time="09:01" 如果只订一个人的票，代码最下面还要把passenger_2相关的代码删掉 -d "passengerTickets=$seat_type,1,$id_card_name2,$cardtype2,$id_card_no2,$mobile_phone2,Y" \ -d "passenger_2_seat=$seat_type" \ -d "passenger_2_ticket=1" \ -d "passenger_2_name=$id_card_name2" \ -d "passenger_2_cardtype=$cardtype2" \ -d "passenger_2_cardno=$id_card_no2" \ -d "passenger_2_mobileno=$mobile_phone2" \ 从查询车次的页面随便搜一个车次，可以和你订票的车次没有任何关系，也不用同一天，只要能点预定按钮就行，然后点预定按钮进入预定页面。 这是技术上的原因。不好多解释。这个步骤主要是影响到脚本里面向下面这个页面发请求获取token参数。 https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=init 改完之后，打开下面的页面刷一个验证码出来 https://dynamic.12306.cn/otsweb/passCodeAction.do?rand=randp&#38;1234567890 比如验证码是9527，那么就执行 ./order.sh 9527 祈祷！ 几个重要的点： 每次提交时发生变化的参数只有2个: org.apache.struts.taglib.html.TOKEN 这个是每次生成页面表单的时候自动重新生成的，网站用它来防止用户重复提交订单。 [...]]]></description>
			<content:encoded><![CDATA[<p>要用这个脚本得懂点shell和web开发。<br />
window下面需要装<a href="http://www.cygwin.com">cygwin</a>才有shell环境。</p>
<p>用法:</p>
<ol>
<li>
<p>先把<a href="http://blog.ouyang.me/wp-content/uploads/2012/01/order.zip">脚本</a>存下来，比如起名叫order.sh。</p>
</li>
<li>
<p>登陆网站，取得当前登陆的cookie，填到脚本里面，这个也可以用firebug取，登陆网站之后，<a href="https://dynamic.12306.cn/otsweb/passCodeAction.do?rand=randp&amp;1234567890">验证码页面请求</a>的header里面都能看到cookie那一行。</p>
<pre><code>cookie: JSESSIONID=6009B4610F436D8023126256FB598BDD; BIGipServerotsweb=2413035786.48160.0000
</code></pre>
</li>
<li>
<p>手动把里面的订票参数改掉。主要就是座位，日期，订票人，车次的信息。<br />
车次的信息需要从网页源码或者页面请求参数里面取。比如从查询页面点击预定按钮进入预定页面时，会向这个页面发POST请求</p>
<pre><code>https://dynamic.12306.cn/otsweb/order/querySingleAction.do?method=submutOrderRequest
</code></pre>
<p>用firebug能看到这些参数</p>
<pre><code>train_no=240000K2670V
station_train_code=K267
from_station_telecode=BXP
from_station_name="北京西"
to_station_telecode=LEQ
to_station_name="澧县"
start_time="12:10"
end_time="09:01"
</code></pre>
<p><span style='color:red;'>如果只订一个人的票，代码最下面还要把passenger_2相关的代码删掉</span></p>
<pre><code>    -d "passengerTickets=$seat_type,1,$id_card_name2,$cardtype2,$id_card_no2,$mobile_phone2,Y" \
    -d "passenger_2_seat=$seat_type" \
    -d "passenger_2_ticket=1" \
    -d "passenger_2_name=$id_card_name2" \
    -d "passenger_2_cardtype=$cardtype2" \
    -d "passenger_2_cardno=$id_card_no2" \
    -d "passenger_2_mobileno=$mobile_phone2" \
</code></pre>
</li>
<li>
<p>从查询车次的页面随便搜一个车次，可以和你订票的车次没有任何关系，也不用同一天，只要能点预定按钮就行，然后点预定按钮进入预定页面。<br />
这是技术上的原因。不好多解释。这个步骤主要是影响到脚本里面向下面这个页面发请求获取token参数。</p>
<pre><code>https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=init
</code></pre>
</li>
<li>
<p>改完之后，打开下面的页面刷一个验证码出来</p>
<p>https://dynamic.12306.cn/otsweb/passCodeAction.do?rand=randp&amp;1234567890</p>
</li>
<li>
<p>比如验证码是9527，那么就执行</p>
<p>./order.sh 9527</p>
</li>
<li>
<p>祈祷！</p>
</li>
</ol>
<p>几个重要的点：</p>
<ol>
<li>
<p>每次提交时发生变化的参数只有2个:</p>
<ul>
<li>org.apache.struts.taglib.html.TOKEN 这个是每次生成页面表单的时候自动重新生成的，网站用它来防止用户重复提交订单。</li>
<li>randCode 验证码，神奇的是，如果不刷新验证码的页面，验证码可以反复使用。当然验证码是有有效期的，但是不知道多久，5分钟应该有吧。</li>
</ul>
</li>
<li>
<p>上面提到的第4步很重要，一旦某次预定成功之后，重新再预定别的车次之前需要重复执行这一步。</p>
</li>
</ol>
<p>shell脚本如下：</p>
<p><span id="more-627"></span></p>
<pre><code>#!/bin/bash

######################
# 需要手工修改的参数 #
######################

# 硬座 1 , 硬卧 3, 软卧 4
seat_type=3

# 乘车日期
train_date="2012-01-20"

# 1, 二代身份证; 2, 一代身份证; C, 港澳通行证; G, 台湾通行证; B, 护照;
cardtype1=1
id_card_no1="xxxxxxxxxxxxxxxxxx"
id_card_name1="xxxx"
mobile_phone1="xxxxxxxxxxx"

cardtype2=1
id_card_no2="xxxxxxxxxxxxxxxxxx"
id_card_name2="xxx"
mobile_phone2="xxxxxxxxxxx"

# 用firebug 从 headers里面取
COOKIE="JSESSIONID=6009B4610F436D8023126256FB598BDD; BIGipServerotsweb=2413035786.48160.0000"

# 从查询页面点击预定按钮进入预定页面时，会向这个页面发POST请求
# https://dynamic.12306.cn/otsweb/order/querySingleAction.do?method=submutOrderRequest
# 用firebug能看到这些参数
train_no=240000K2670V
station_train_code=K267
from_station_telecode=BXP
from_station_name="北京西"
to_station_telecode=LEQ
to_station_name="澧县"
start_time="12:10"
end_time="09:01"

######################
######################

# A, 网上支付; B, 售票点自取, 看网页源码，有这个选项，但是网页上没有提供选择界面，所以不确定选项B能不能用
reserve_flag=A

FORM_HTML=form.html.tmp
RESULT_HTML=result.html.tmp

while true
do
    echo "==================="
    echo "Try to get token..."
    echo "==================="
    curl -k -b "$COOKIE" \
        "https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=init" &gt; $FORM_HTML

    TOKEN=$(grep "org.apache.struts.taglib.html.TOKEN" $FORM_HTML | sed -e 's/.*value="\(.*\)".*/\1/')

    if test -z "$TOKEN"
    then
        #cat $FORM_HTML
        grep succde_fault.jpg $FORM_HTML
        echo "获取表单信息失败"
        echo "请确认cookie有效"
        echo "请确认通过车票查询页面点击预定进入预定页面并填写了相应的参数"
        continue
    fi

    if test -z "$1"
    then
        echo "请输入 https://dynamic.12306.cn/otsweb/passCodeAction.do?rand=randp&amp;1234567890 验证码:"
        read randCode
    else
        randCode=$1
    fi

    echo "========="
    echo "submit..."
    echo "========="
    curl -k -b "$COOKIE" \
        -d "org.apache.struts.taglib.html.TOKEN=$TOKEN" \
        -d "randCode=$randCode" \
        -d "orderRequest.train_date=$train_date" \
        -d "orderRequest.train_no=$train_no" \
        -d "orderRequest.station_train_code=$station_train_code" \
        -d "orderRequest.from_station_telecode=$from_station_telecode" \
        -d "orderRequest.to_station_telecode=$to_station_telecode" \
        -d "orderRequest.seat_type_code=" \
        -d "orderRequest.ticket_type_order_num=" \
        -d "orderRequest.bed_level_order_num=000000000000000000000000000000" \
        -d "orderRequest.start_time=$start_time" \
        -d "orderRequest.end_time=$end_time" \
        -d "orderRequest.from_station_name=$from_station_name" \
        -d "orderRequest.to_station_name=$to_station_name" \
        -d "orderRequest.cancel_flag=1" \
        -d "orderRequest.id_mode=Y" \
        -d "orderRequest.reserve_flag=$reserve_flag" \
        -d "passengerTickets=$seat_type,1,$id_card_name1,$cardtype1,$id_card_no1,$mobile_phone1,Y" \
        -d "passenger_1_seat=$seat_type" \
        -d "passenger_1_ticket=1" \
        -d "passenger_1_name=$id_card_name1" \
        -d "passenger_1_cardtype=$cardtype1" \
        -d "passenger_1_cardno=$id_card_no1" \
        -d "passenger_1_mobileno=$mobile_phone1" \
        -d "passengerTickets=$seat_type,1,$id_card_name2,$cardtype2,$id_card_no2,$mobile_phone2,Y" \
        -d "passenger_2_seat=$seat_type" \
        -d "passenger_2_ticket=1" \
        -d "passenger_2_name=$id_card_name2" \
        -d "passenger_2_cardtype=$cardtype2" \
        -d "passenger_2_cardno=$id_card_no2" \
        -d "passenger_2_mobileno=$mobile_phone2" \
        "https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=confirmPassengerInfoSingle" &gt; $RESULT_HTML

    success=$(grep successTicketNum $RESULT_HTML)
    if test -z "$success"
    then
        #grep "succde_fault.jpg" $RESULT_HTML
        cat $RESULT_HTML
    else
        # 人品大爆发，赶紧去网页支付
        # 预定成功之后，有效期应该是50分钟，需要在50分钟之内支付完毕.
        echo "$success"
        exit 0
    fi

    # var message = "对不起，由于您取消次数过多，今日将不能继续受理您的订票请求。1 月9 日您可继续使用订票功能。";
done
</code></pre>
<img src="http://feeds.feedburner.com/~r/SomethingLastForever/~4/o-2q9GOCQuQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ouyang.me/2012/01/script-to-order-train-ticket/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<enclosure url="http://blog.ouyang.me/wp-content/uploads/2012/01/order.zip" length="1919" type="application/zip" /><media:content url="http://blog.ouyang.me/wp-content/uploads/2012/01/order.zip" fileSize="1919" type="application/zip" /><itunes:explicit>no</itunes:explicit><itunes:subtitle>要用这个脚本得懂点shell和web开发。 window下面需要装cygwin才有shell环境。 用法: 先把脚本存下来，比如起名叫order.sh。 登陆网站，取得当前登陆的cookie，填到脚本里面，这个也可以用firebug取，登陆网站之后，验证码页面请求的header里面都能看到cookie那一行。 cookie: JSESSIONID=6009B4610F436D8023126256FB598BDD; BIGipServerotsweb=2413035786.48160.0000 手动把里面的</itunes:subtitle><itunes:summary>要用这个脚本得懂点shell和web开发。 window下面需要装cygwin才有shell环境。 用法: 先把脚本存下来，比如起名叫order.sh。 登陆网站，取得当前登陆的cookie，填到脚本里面，这个也可以用firebug取，登陆网站之后，验证码页面请求的header里面都能看到cookie那一行。 cookie: JSESSIONID=6009B4610F436D8023126256FB598BDD; BIGipServerotsweb=2413035786.48160.0000 手动把里面的订票参数改掉。主要就是座位，日期，订票人，车次的信息。 车次的信息需要从网页源码或者页面请求参数里面取。比如从查询页面点击预定按钮进入预定页面时，会向这个页面发POST请求 https://dynamic.12306.cn/otsweb/order/querySingleAction.do?method=submutOrderRequest 用firebug能看到这些参数 train_no=240000K2670V station_train_code=K267 from_station_telecode=BXP from_station_name="北京西" to_station_telecode=LEQ to_station_name="澧县" start_time="12:10" end_time="09:01" 如果只订一个人的票，代码最下面还要把passenger_2相关的代码删掉 -d "passengerTickets=$seat_type,1,$id_card_name2,$cardtype2,$id_card_no2,$mobile_phone2,Y" \ -d "passenger_2_seat=$seat_type" \ -d "passenger_2_ticket=1" \ -d "passenger_2_name=$id_card_name2" \ -d "passenger_2_cardtype=$cardtype2" \ -d "passenger_2_cardno=$id_card_no2" \ -d "passenger_2_mobileno=$mobile_phone2" \ 从查询车次的页面随便搜一个车次，可以和你订票的车次没有任何关系，也不用同一天，只要能点预定按钮就行，然后点预定按钮进入预定页面。 这是技术上的原因。不好多解释。这个步骤主要是影响到脚本里面向下面这个页面发请求获取token参数。 https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=init 改完之后，打开下面的页面刷一个验证码出来 https://dynamic.12306.cn/otsweb/passCodeAction.do?rand=randp&amp;#38;1234567890 比如验证码是9527，那么就执行 ./order.sh 9527 祈祷！ 几个重要的点： 每次提交时发生变化的参数只有2个: org.apache.struts.taglib.html.TOKEN 这个是每次生成页面表单的时候自动重新生成的，网站用它来防止用户重复提交订单。 [...]</itunes:summary><itunes:keywords>programming</itunes:keywords><feedburner:origLink>http://blog.ouyang.me/2012/01/script-to-order-train-ticket/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=script-to-order-train-ticket</feedburner:origLink></item>
		<item>
		<title>MTU导致scp假死的问题</title>
		<link>http://feedproxy.google.com/~r/SomethingLastForever/~3/4Xbd72t7BBw/</link>
		<comments>http://blog.ouyang.me/2011/12/mtu-cause-scp-hung-up/#comments</comments>
		<pubDate>Fri, 23 Dec 2011 02:42:07 +0000</pubDate>
		<dc:creator>oylbin</dc:creator>
				<category><![CDATA[system administration]]></category>

		<guid isPermaLink="false">http://blog.ouyang.me/?p=620</guid>
		<description><![CDATA[昨天遇到一个诡异的网络问题，让我郁闷了一会儿。 公司某台机器用svn，scp，git，rsync等各种方式向外网传数据时总是会假死。 比如svn提交， work@ubuntu:~/svn_repos$ svn ci Resources/anim/images/walk.png -mx Adding (bin) Resources/anim/images/walk.png Transmitting file data . 当输出最后那句话之后就死掉了，等很久都没有反应。Ctrl+C之后，提示如下： svn: Commit failed (details follow): svn: While preparing '/home/work/svn_repos/Resources/anim/images/walk.png' for commit svn: Caught signal 但是文本文件就能成功提交。第一反应是网络慢，或者svn的binary数据传输有问题。各种尝试，git，scp，rsync，现象都类似。 比如scp： work@ubuntu:~/svn_repos$ scp Resources/anim/images/walk.png work@example.com:~/ walk.png 100% 89KB 89.5KB/s 00:00 终端显示100%，然后就停住了。Ctrl+C都没用，只能kill进程。用-vvv开启详细日志，也看不出什么问题。 work@ubuntu:~/svn_repos$ scp -vvv Resources/anim/images/walk.png work@example.com:~/ ... ... debug1: Sending command: scp -v -t [...]]]></description>
			<content:encoded><![CDATA[<p>昨天遇到一个诡异的网络问题，让我郁闷了一会儿。<br />
公司某台机器用svn，scp，git，rsync等各种方式向外网传数据时总是会假死。</p>
<p>比如svn提交，</p>
<pre><code>work@ubuntu:~/svn_repos$ svn ci Resources/anim/images/walk.png  -mx
Adding  (bin)  Resources/anim/images/walk.png
Transmitting file data .
</code></pre>
<p>当输出最后那句话之后就死掉了，等很久都没有反应。Ctrl+C之后，提示如下：</p>
<pre><code>svn: Commit failed (details follow):
svn: While preparing '/home/work/svn_repos/Resources/anim/images/walk.png' for commit
svn: Caught signal
</code></pre>
<p>但是文本文件就能成功提交。第一反应是网络慢，或者svn的binary数据传输有问题。各种尝试，git，scp，rsync，现象都类似。<br />
比如scp：</p>
<pre><code>work@ubuntu:~/svn_repos$ scp  Resources/anim/images/walk.png work@example.com:~/
walk.png         100%   89KB  89.5KB/s   00:00
</code></pre>
<p><span id="more-620"></span></p>
<p>终端显示100%，然后就停住了。Ctrl+C都没用，只能kill进程。用-vvv开启详细日志，也看不出什么问题。</p>
<pre><code>work@ubuntu:~/svn_repos$ scp -vvv Resources/anim/images/walk.png work@example.com:~/

...
...
debug1: Sending command: scp -v -t ~/
debug2: channel 0: request exec confirm 1
debug2: fd 3 setting TCP_NODELAY
debug2: callback done
debug2: channel 0: open confirm rwindow 0 rmax 32768
debug3: Wrote 192 bytes for a total of 2391
debug2: channel 0: rcvd adjust 2097152
debug2: channel_input_status_confirm: type 99 id 0
debug2: exec request accepted on channel 0
Sending file modes: C0644 91624 walk.png
debug3: Wrote 64 bytes for a total of 2455
debug2: channel 0: rcvd ext data 27
Sink: C0644 91624 walk.png
debug2: channel 0: written 27 to efd 6
walk.png                                                            100%   89KB  89.5KB/s   00:00
debug3: Wrote 12924 bytes for a total of 15379
</code></pre>
<p>最后显示100%，最后还是会假死。</p>
<p>搜索 <a href="http://www.google.com/search?q=scp+hangs+at+100&amp;hl=en">scp hangs at 100</a>, <a href="http://www.google.com/search?q=scp+binary+file+hung+up&amp;hl=en">scp binary file hung up</a>，都没有找到什么有用的答案。</p>
<p>文本可以，binary不行，svn，git，scp，rsync各种工具现象都类似，而且只有这台机器有问题，我自己的机器做这些操作向远程传文件一切正常。从来没有遇到过这样怪异的问题，一时间有点焦头烂额的感觉。最后想，也许是文件大小的关系，建了一个50KB的文本文件尝试提交，发现也会假死，算是确认了这个想法。接下来的问题就是找到究竟是传多大的文件的时候会死掉。</p>
<p>这里用dd命令可以创建一个指定大小的文件。</p>
<pre><code># 建一个 1KB的文件
dd if=/dev/zero of=file_to_create bs=1 count=1024

# 建一个 1KB的文件
dd if=/dev/zero of=file_to_create bs=1k count=1

# 建一个 10MB的文件
dd if=/dev/zero of=file_to_create bs=1m count=10
</code></pre>
<p>通过二分查找，最终定位到文件大小是1390字节时可以scp成功，1391字节时就会假死。</p>
<p>1391是个什么奇怪的数字？再搜 <a href="http://www.google.com/search?q=scp+hung+up+1391&amp;hl=en">scp hung up 1391</a>，终于找到一篇<a href="http://unix.stackexchange.com/questions/14187/why-does-scp-hang-on-copying-files-larger-than-1405-bytes">Why does SCP hang on copying files larger than 1405 bytes?</a></p>
<blockquote>
<p>This definitely sounds like MTU problems (like Konerak pointed out), this is how I would test this:</p>
<pre><code>   ip link set eth0 mtu 1400
</code></pre>
<p>This temporally sets the allowed size for network packets to 1400 on the network interface eth0 (you might need to adjust the name). Your system will then split all packets above this size before sending it on to the network. If this fixes the scp command, you need to find the problem within the network or make this ugly fix permanent ; )</p>
</blockquote>
<p>再看看这台有问题的机器，发现默认的MTU是1500。</p>
<pre><code>work@ubuntu:~$ ip link
1: lo: &lt;LOOPBACK,UP,LOWER_UP&gt; mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
    link/ether 00:24:e8:2c:3d:76 brd ff:ff:ff:ff:ff:ff
</code></pre>
<p>照着上面的办法把MTU设置为1400，果然就好了！</p>
<p>应该是网络里某台路由的问题吧，也懒得去找了。话说这个因为MTU设置错误导致路由器丢包的问题，以前做课程项目的时候也遇到过，当时是在程序里自动切包解决的问题。</p>
<img src="http://feeds.feedburner.com/~r/SomethingLastForever/~4/4Xbd72t7BBw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ouyang.me/2011/12/mtu-cause-scp-hung-up/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ouyang.me/2011/12/mtu-cause-scp-hung-up/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=mtu-cause-scp-hung-up</feedburner:origLink></item>
		<item>
		<title>Mac下快速切换到Terminal的脚本</title>
		<link>http://feedproxy.google.com/~r/SomethingLastForever/~3/GU-_n6KFdUk/</link>
		<comments>http://blog.ouyang.me/2011/12/fast-switch-terminal-with-shortcut-in-mac-os/#comments</comments>
		<pubDate>Thu, 22 Dec 2011 05:15:55 +0000</pubDate>
		<dc:creator>oylbin</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[applescript]]></category>

		<guid isPermaLink="false">http://blog.ouyang.me/?p=616</guid>
		<description><![CDATA[脚本如下，github上也放了： -- 启动或者切换Terminal 的applescript脚本 -- 当使用快捷键触发脚本时: -- 如果不存在已经启动的Terminal，那么新启动一个Terminal -- 如果有已经启动的Terminal，且当前窗口不是Terminal，那么切换到Terminal -- 如果有已经启动的Terminal，且当前窗口是Terminal，那么在多个Terminal中循环切换 -- -- 可以在用quicksilver或者fastscript把这个脚本绑定到自己习惯的快捷键上面。 -- 我用的是 Option + c -- -- Terminal的设置里面，把window的title设置勾选上tty -- 这样可以保证每个terminal window的title都不一样 -- 这样脚本才能正常工作 -- Terminal 的 Window菜单中 窗口列表项 的起始 index global magic_index set magic_index to 21 on array_search(arr,i) repeat with idx from 1 to count of arr if item idx [...]]]></description>
			<content:encoded><![CDATA[<p>脚本如下，<a href="https://github.com/oylbin/oylbin/blob/master/mac/terminal.applescript">github上也放了</a>：</p>
<p><span id="more-616"></span></p>
<pre><code>-- 启动或者切换Terminal 的applescript脚本
-- 当使用快捷键触发脚本时:
--      如果不存在已经启动的Terminal，那么新启动一个Terminal
--      如果有已经启动的Terminal，且当前窗口不是Terminal，那么切换到Terminal
--      如果有已经启动的Terminal，且当前窗口是Terminal，那么在多个Terminal中循环切换
--
-- 可以在用quicksilver或者fastscript把这个脚本绑定到自己习惯的快捷键上面。
-- 我用的是 Option + c
--
-- Terminal的设置里面，把window的title设置勾选上tty
-- 这样可以保证每个terminal window的title都不一样
-- 这样脚本才能正常工作

-- Terminal 的 Window菜单中 窗口列表项 的起始 index
global magic_index
set magic_index to 21

on array_search(arr,i)
    repeat with idx from 1 to count of arr
        if item idx of arr is i then
            return idx
        end if
    end repeat
    return -1
end array_search

on bring_to_front(window_index)
    tell application "System Events"
        click menu item (magic_index + window_index) of menu "Window" of menu bar 1 of process "Terminal"
        tell application "Terminal" to activate
    end tell
end bring_to_front

on get_terminal_list()
    tell application "System Events"
        -- 如果没有正在运行的terminal进程，那么需要先activate
        tell application "Terminal" to activate
        tell process "Terminal"
            tell menu bar 1
                tell menu "Window"
                    set window_title_list to {}
                    set menu_list to get menu items
                    if menu_list's length &gt; magic_index then
                        set window_list to (items (magic_index+1) through (menu_list's length) of menu_list)
                        repeat with idx from 1 to count of window_list
                        set window_title_list's end to value of attribute "AXTitle" of item idx of window_list
                        end repeat
                    end if
                    return window_title_list
                end tell
            end tell
        end tell
    end tell
end get_terminal_list

on run_script()

    tell application "System Events"
        set app_before_activate to name of the first process whose frontmost is true
    end tell
    --say app_before_activate

    set all_terminal_window to get_terminal_list()
    --say all_terminal_window's length 

    if all_terminal_window's length = 0 then
        tell app "Terminal"
            do script ""
            activate
        end tell
    else
        -- window 0 是已经打开的所有Terminal窗口中最前面的一个
        set current_terminal_window to name of window 0 of application "Terminal"
        --say current_terminal_window
        set window_index to array_search(all_terminal_window,current_terminal_window)

        if app_before_activate is "Terminal" then
            set window_index  to window_index +1
            if window_index &gt; all_terminal_window's length then
                set window_index to 1
            end if
            bring_to_front(window_index)
        else
            bring_to_front(window_index)
        end if
    end if
end run

run_script()
</code></pre>
<img src="http://feeds.feedburner.com/~r/SomethingLastForever/~4/GU-_n6KFdUk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ouyang.me/2011/12/fast-switch-terminal-with-shortcut-in-mac-os/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ouyang.me/2011/12/fast-switch-terminal-with-shortcut-in-mac-os/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=fast-switch-terminal-with-shortcut-in-mac-os</feedburner:origLink></item>
		<item>
		<title>菜鸟问题</title>
		<link>http://feedproxy.google.com/~r/SomethingLastForever/~3/5rGnQhDBL1g/</link>
		<comments>http://blog.ouyang.me/2011/12/%e8%8f%9c%e9%b8%9f%e9%97%ae%e9%a2%98/#comments</comments>
		<pubDate>Thu, 22 Dec 2011 04:57:20 +0000</pubDate>
		<dc:creator>oylbin</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[cocos2dx]]></category>

		<guid isPermaLink="false">http://blog.ouyang.me/?p=614</guid>
		<description><![CDATA[下面是在cocos2dx的HelloWorld代码基础上做的小修改，直接在AppDelegate.cpp里面初始化场景，并展示出一张背景图片。 AppDelegate.cpp 片段 bool AppDelegate::applicationDidFinishLaunching(){ ... ... CCScene *pScene = CCScene::node(); CCSprite* sprite = CCSprite::spriteWithFile("HelloWorld.png"); CCSize size = CCDirector::sharedDirector()-&#62;getWinSize(); sprite-&#62;setPosition(ccp(size.width/2,size.height/2)); pScene-&#62;addChild(sprite); pDirector-&#62;runWithScene(pScene); return true; } 运行正常。于是，我改一下，把场景逻辑放入一个 LoadingScene 类里面去处理。 AppDelegate.cpp 片段 bool AppDelegate::applicationDidFinishLaunching(){ ... ... CCScene *pScene = LoadingScene::node(); pDirector-&#62;runWithScene(pScene); return true; } LoadingScene.h #ifndef __LOADING_SCENE_H__ #define __LOADING_SCENE_H__ #include "cocos2d.h" using namespace cocos2d; class LoadingScene : [...]]]></description>
			<content:encoded><![CDATA[<p>下面是在cocos2dx的HelloWorld代码基础上做的小修改，直接在AppDelegate.cpp里面初始化场景，并展示出一张背景图片。</p>
<p><span id="more-614"></span></p>
<p>AppDelegate.cpp 片段</p>
<pre><code>bool AppDelegate::applicationDidFinishLaunching(){
    ...
    ...

    CCScene *pScene = CCScene::node();
    CCSprite* sprite = CCSprite::spriteWithFile("HelloWorld.png");
    CCSize size = CCDirector::sharedDirector()-&gt;getWinSize();
    sprite-&gt;setPosition(ccp(size.width/2,size.height/2));
    pScene-&gt;addChild(sprite);

    pDirector-&gt;runWithScene(pScene);

    return true;
}
</code></pre>
<p>运行正常。于是，我改一下，把场景逻辑放入一个 LoadingScene 类里面去处理。</p>
<p>AppDelegate.cpp 片段</p>
<pre><code>bool AppDelegate::applicationDidFinishLaunching(){
    ...
    ...

    CCScene *pScene = LoadingScene::node();

    pDirector-&gt;runWithScene(pScene);

    return true;
}
</code></pre>
<p>LoadingScene.h</p>
<pre><code>#ifndef __LOADING_SCENE_H__
#define __LOADING_SCENE_H__

#include "cocos2d.h"
using namespace cocos2d;

class LoadingScene : public CCScene
{
public:
    LoadingScene();
};

#endif // __LOADING_SCENE_H__
</code></pre>
<p>LoadingScene.cpp</p>
<pre><code>#include "LoadingScene.h"
USING_NS_CC;

LoadingScene::LoadingScene(){
    CCScene::CCScene();

    CCSprite* pSprite;
    pSprite = CCSprite::spriteWithFile("HelloWorld.png");
    CCSize size = CCDirector::sharedDirector()-&gt;getWinSize();
    pSprite-&gt;setPosition(ccp(size.width/2,size.height/2));
    addChild(pSprite);
}
</code></pre>
<p>再执行的时候，就发现启动之后，HelloWorld.png图片会闪一下然后马上消失。<br />
我怀疑是不是我的写法不对，pSprite在启动后某个时间被释放掉了。<br />
于是各种尝试，把加背景图的逻辑放入init()方法，放入onEnter()方法，结果都是一样的现象。</p>
<p>纠结了一阵之后才想到做断点调试，然后发现，我写的构造函数根本没有被执行。下面这行代码根本不会触发LoadingScene的构造函数。</p>
<pre><code>CCScene *pScene = LoadingScene::node();
</code></pre>
<p>正确的写法应该是</p>
<pre><code>LoadingScene *pScene = new LoadingScene();
pScene-&gt;autorelease();
</code></pre>
<p>为什么构造函数没有被调用，开启程序的时候还是会闪现一下背景图片呢？<br />
那是因为每个程序本身就可以设置一个启动画面，而这个HelloWorld程序的启动画面正好就是HelloWorld.png</p>
<p>有些问题最开始让人很困惑，百思不得其解，可是等你弄明白原因之后，就会觉得很荒唐。<br />
真实的原因可能很简单，只是因为某种巧合，现象把你带入了歧途。</p>
<p>问题很弱智，但是我决定还是把它写下来。</p>
<img src="http://feeds.feedburner.com/~r/SomethingLastForever/~4/5rGnQhDBL1g" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ouyang.me/2011/12/%e8%8f%9c%e9%b8%9f%e9%97%ae%e9%a2%98/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ouyang.me/2011/12/%e8%8f%9c%e9%b8%9f%e9%97%ae%e9%a2%98/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=%25e8%258f%259c%25e9%25b8%259f%25e9%2597%25ae%25e9%25a2%2598</feedburner:origLink></item>
		<item>
		<title>适用于wordpress的nginx rewrite规则</title>
		<link>http://feedproxy.google.com/~r/SomethingLastForever/~3/ZGTGL1ej9Rg/</link>
		<comments>http://blog.ouyang.me/2011/12/nginx-rewrite-for-wordpress/#comments</comments>
		<pubDate>Wed, 14 Dec 2011 14:52:48 +0000</pubDate>
		<dc:creator>oylbin</dc:creator>
				<category><![CDATA[system administration]]></category>

		<guid isPermaLink="false">http://blog.ouyang.me/?p=606</guid>
		<description><![CDATA[此前的博客是搭建在dreamhost或者godaddy空间里面的，它们都是apache，然后使用.htacess来进行url rewrite。 现在博客换到自己的机器之后，原来类似于下面一样的地址已经无法访问到对应的文章了。 http://blog.ouyang.me/2011/12/blog-migrate-to-amazon-cloud/ 只能通过post_id的参数来访问 http://blog.ouyang.me/?p=591 所以，刚刚重新配置了一下nginx的rewrite规则，很简单，一条配置就搞定了 wordpress的设置里面，把Permalink的设置为 /%year%/%monthnum%/%postname%/ 修改nginx的配置，在server段里面配置 try_files $uri $uri/ /index.php?q=$uri&#38;$args; 参考链接： Finally using nginx&#8217;s &#8220;try_files&#8221; directive]]></description>
			<content:encoded><![CDATA[<p>此前的博客是搭建在dreamhost或者godaddy空间里面的，它们都是apache，然后使用.htacess来进行url rewrite。<br />
现在博客换到自己的机器之后，原来类似于下面一样的地址已经无法访问到对应的文章了。</p>
<pre><code>http://blog.ouyang.me/2011/12/blog-migrate-to-amazon-cloud/
</code></pre>
<p>只能通过post_id的参数来访问</p>
<pre><code>http://blog.ouyang.me/?p=591
</code></pre>
<p>所以，刚刚重新配置了一下nginx的rewrite规则，很简单，一条配置就搞定了</p>
<ol>
<li>
<p>wordpress的设置里面，把Permalink的设置为</p>
<p>/%year%/%monthnum%/%postname%/</p>
</li>
<li>
<p>修改nginx的配置，在server段里面配置</p>
<p>try_files $uri $uri/ /index.php?q=$uri&amp;$args;</p>
</li>
</ol>
<p>参考链接： <a href="http://michaelshadle.com/2009/03/19/finally-using-nginxs-try-files-directive">Finally using nginx&#8217;s &#8220;try_files&#8221; directive</a></p>
<img src="http://feeds.feedburner.com/~r/SomethingLastForever/~4/ZGTGL1ej9Rg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ouyang.me/2011/12/nginx-rewrite-for-wordpress/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ouyang.me/2011/12/nginx-rewrite-for-wordpress/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=nginx-rewrite-for-wordpress</feedburner:origLink></item>
		<item>
		<title>适用于几种IDE的gitignore文件</title>
		<link>http://feedproxy.google.com/~r/SomethingLastForever/~3/-fgq8Hrd_M4/</link>
		<comments>http://blog.ouyang.me/2011/12/gitignore-for-xcode-eclipse-visual-studio/#comments</comments>
		<pubDate>Wed, 14 Dec 2011 03:25:26 +0000</pubDate>
		<dc:creator>oylbin</dc:creator>
				<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://blog.ouyang.me/?p=598</guid>
		<description><![CDATA[项目需要同时用到xcode 4, eclipse+adt, visual studio 2008，IDE会生成很多不相干的文件，这些文件是不应该放到代码库里面去的。 所以网上搜罗了一下适用于几种IDE的gitignore文件 gitignore for visual studio projects and solutions git ignore file for xcode projects eclipse android and gitignore 记录一下: ########################## # xcode ########################## .DS_Store *.swp *~.nib build/ *.pbxuser *.perspective *.perspectivev3 *.mode1v3 *.mode2v3 xcuserdata/ ########################## # eclipse android ########################## # built application files *.apk *.ap_ # files for the dex [...]]]></description>
			<content:encoded><![CDATA[<p>项目需要同时用到xcode 4, eclipse+adt, visual studio 2008，IDE会生成很多不相干的文件，这些文件是不应该放到代码库里面去的。<br />
所以网上搜罗了一下适用于几种IDE的gitignore文件</p>
<ul>
<li><a href="http://stackoverflow.com/questions/2143956/gitignore-for-visual-studio-projects-and-solutions">gitignore for visual studio projects and solutions</a></li>
<li><a href="http://stackoverflow.com/questions/49478/git-ignore-file-for-xcode-projects">git ignore file for xcode projects</a></li>
<li><a href="http://stackoverflow.com/questions/3325736/eclipse-android-and-gitignore">eclipse android and gitignore</a></li>
</ul>
<p>记录一下:</p>
<p><span id="more-598"></span></p>
<pre><code>##########################
#  xcode
##########################
.DS_Store
*.swp
*~.nib

build/

*.pbxuser
*.perspective
*.perspectivev3

*.mode1v3
*.mode2v3

xcuserdata/

##########################
#  eclipse android
##########################

# built application files
*.apk
*.ap_

# files for the dex VM
*.dex

# Java class files
*.class

# generated files
bin/
gen/

# Local configuration file (sdk path, etc)
local.properties

##########################
#  visual studio 2008
##########################
[Tt]humbs.db

*.[Oo]bj
*.user
*.aps
*.pch
*.vspscc
*.vssscc
*_i.c
*_p.c
*.ncb
*.suo
*.tlb
*.tlh
*.bak
*.[Cc]ache
*.ilk
*.log
*.lib
*.sbr
*.sdf
*.opensdf
*.unsuccessfulbuild
ipch/
obj/
[Bb]in
[Dd]ebug*/
[Rr]elease*/
Ankh.NoLoad
TestResults/

##########################
#  other
##########################
.svn
~$*
*.log
*.7z
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip
</code></pre>
<img src="http://feeds.feedburner.com/~r/SomethingLastForever/~4/-fgq8Hrd_M4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ouyang.me/2011/12/gitignore-for-xcode-eclipse-visual-studio/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ouyang.me/2011/12/gitignore-for-xcode-eclipse-visual-studio/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=gitignore-for-xcode-eclipse-visual-studio</feedburner:origLink></item>
		<item>
		<title>centos系统时区和时间设置</title>
		<link>http://feedproxy.google.com/~r/SomethingLastForever/~3/FIKoz7eu21o/</link>
		<comments>http://blog.ouyang.me/2011/12/time-zone-setting-in-centos-with-ntpdate/#comments</comments>
		<pubDate>Tue, 13 Dec 2011 03:00:59 +0000</pubDate>
		<dc:creator>oylbin</dc:creator>
				<category><![CDATA[system administration]]></category>

		<guid isPermaLink="false">http://blog.ouyang.me/?p=597</guid>
		<description><![CDATA[时区设置，在/usr/share/zoneinfo目录下有各种时区的配置文件，将需要的配置文件复制或者软链到 /etc/localtime文件即可： cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 时间设置，可以用date命令： date -s "2011-11-11 11:11:11" 但一般还是用ntpdate来同步。一些机器可能没有预装ntp，需要先安装一下 sudo yum install ntp 然后执行 sudo /sbin/ntpdate cn.pool.ntp.org cn.pool.ntp.org是用于同步的服务器，如果是其他地区的机器，考虑到网络问题，可以选择最近的服务器，所有的服务器列表，可以在ntp.org的网站上找到。 用date命令或者ntpdate修改时间后，时间不会立刻同步到BIOS，如果马上重启机器，刚刚的时间设置就失效了。下面的命令可以马上将系统时间同步到BIOS： sudo /sbin/hwclock --systohc 而ntpdate提供了配置选项，在 /etc/sysconfig/ntpd 文件中 # Set to 'yes' to sync hw clock after successful ntpdate SYNC_HWCLOCK=yes 同时，如果是多个机器协同工作的，可能需要定期同步时间，把ntpdate写入crontab，每10分钟同步一次： 0-59/10 * * * * /sbin/ntpdate cn.pool.ntp.org &#124; logger -t NTP]]></description>
			<content:encoded><![CDATA[<p>时区设置，在/usr/share/zoneinfo目录下有各种时区的配置文件，将需要的配置文件复制或者软链到 /etc/localtime文件即可：</p>
<pre><code>cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
</code></pre>
<p>时间设置，可以用date命令：</p>
<pre><code>date -s "2011-11-11 11:11:11"
</code></pre>
<p>但一般还是用ntpdate来同步。一些机器可能没有预装ntp，需要先安装一下</p>
<pre><code>sudo yum install ntp
</code></pre>
<p>然后执行</p>
<pre><code>sudo /sbin/ntpdate cn.pool.ntp.org
</code></pre>
<p>cn.pool.ntp.org是用于同步的服务器，如果是其他地区的机器，考虑到网络问题，可以选择最近的服务器，所有的服务器列表，可以在<a href="http://www.pool.ntp.org/en/">ntp.org的网站</a>上找到。</p>
<p>用date命令或者ntpdate修改时间后，时间不会立刻同步到BIOS，如果马上重启机器，刚刚的时间设置就失效了。下面的命令可以马上将系统时间同步到BIOS：</p>
<pre><code>sudo /sbin/hwclock --systohc
</code></pre>
<p>而ntpdate提供了配置选项，在 /etc/sysconfig/ntpd 文件中</p>
<pre><code># Set to 'yes' to sync hw clock after successful ntpdate
SYNC_HWCLOCK=yes
</code></pre>
<p>同时，如果是多个机器协同工作的，可能需要定期同步时间，把ntpdate写入crontab，每10分钟同步一次：</p>
<pre><code>0-59/10 * * * * /sbin/ntpdate cn.pool.ntp.org | logger -t NTP
</code></pre>
<img src="http://feeds.feedburner.com/~r/SomethingLastForever/~4/FIKoz7eu21o" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ouyang.me/2011/12/time-zone-setting-in-centos-with-ntpdate/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ouyang.me/2011/12/time-zone-setting-in-centos-with-ntpdate/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=time-zone-setting-in-centos-with-ntpdate</feedburner:origLink></item>
		<item>
		<title>mac os下搭建cocos2d-x的开发环境</title>
		<link>http://feedproxy.google.com/~r/SomethingLastForever/~3/P31Y8DD7vuA/</link>
		<comments>http://blog.ouyang.me/2011/12/cocos2dx-development-mac-os/#comments</comments>
		<pubDate>Mon, 12 Dec 2011 14:00:59 +0000</pubDate>
		<dc:creator>oylbin</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[cocos2d-x]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[xcode]]></category>

		<guid isPermaLink="false">http://blog.ouyang.me/?p=596</guid>
		<description><![CDATA[做手机游戏的开发，用cocs2d-x的库，这样可以同时开发ios和android的版本。 这两天主要是搭建开发环境。参考了这篇文章。 ios下的开发比较简单，装好xcode之后，直接安装cocos2d-x的库 下载 http://cocos2d-x.googlecode.com/files/cocos2d-1.0.1-x-0.10.0.zip 解压后，进入解压目录运行: sudo ./install-templates-xcode.sh 会提示你选择要安装的template，我是xcode4，所以选4。 装完之后进入xcode，新建项目，就可以选择cocos2d-x了，自带的模板是包含hello world示例的，新建完毕之后可以直接运行，看到示例效果。 因为考虑到，以后我可能会使用vim开发，而不用庞大的xcode，所以，顺便试了一下命令行编译项目。进入项目路径，执行 xcodebuild 提示错误： === BUILD NATIVE TARGET helloworld OF PROJECT helloworld WITH THE DEFAULT CONFIGURATION (Release) === Check dependencies [BEROR]CodeSign error: code signing is required for product type &#8216;Application&#8217; in SDK &#8216;iOS 5.0&#8242; 这是因为本地缺少用于签名的证书，网上有一篇详细的文章介绍如何配置。 关于android的开发环境，根据android developer提供的文档一步步来就ok了。 安装eclipse 安装eclipse-adt 安装android sdk 安装ndk 开发环境搭好之后，再根据cocos2d-x官网提供的文档，教你如何把cocos2d-x的库中带的示例项目跑起来。 这里遇到两个问题。 因为我使用了最新的ndk [...]]]></description>
			<content:encoded><![CDATA[<p>做手机游戏的开发，用<a href="http://www.cocos2d-x.org">cocs2d-x</a>的库，这样可以同时开发ios和android的版本。</p>
<p>这两天主要是搭建开发环境。参考了<a href="http://www.supersuraccoon-cocos2d.com/zh/2011/08/10/cocos2d-x-iphone-androidide-installation-and-setup-under-mac-os/">这篇文章</a>。</p>
<p>ios下的开发比较简单，装好xcode之后，直接安装cocos2d-x的库</p>
<p>下载 </p>
<pre><code>http://cocos2d-x.googlecode.com/files/cocos2d-1.0.1-x-0.10.0.zip
</code></pre>
<p>解压后，进入解压目录运行:</p>
<pre><code>sudo ./install-templates-xcode.sh
</code></pre>
<p>会提示你选择要安装的template，我是xcode4，所以选4。 <br />
装完之后进入xcode，新建项目，就可以选择cocos2d-x了，自带的模板是包含hello  world示例的，新建完毕之后可以直接运行，看到示例效果。</p>
<p>因为考虑到，以后我可能会使用vim开发，而不用庞大的xcode，所以，顺便试了一下命令行编译项目。进入项目路径，执行</p>
<pre><code>xcodebuild
</code></pre>
<p>提示错误：</p>
<blockquote>
<p>=== BUILD NATIVE TARGET helloworld OF PROJECT helloworld WITH THE DEFAULT CONFIGURATION (Release) === <br />
  Check dependencies <br />
  [BEROR]CodeSign error: code signing is required for product type &#8216;Application&#8217; in SDK &#8216;iOS 5.0&#8242;</p>
</blockquote>
<p>这是因为本地缺少用于签名的证书，网上有<a href="http://mobiforge.com/developing/story/deploying-iphone-apps-real-devices">一篇详细的文章</a>介绍如何配置。</p>
<p>关于android的开发环境，根据<a href="http://developer.android.com/index.html">android developer</a>提供的文档一步步来就ok了。</p>
<ul>
<li>
<p>安装eclipse</p>
</li>
<li>
<p><a href="http://developer.android.com/sdk/eclipse-adt.html#installing">安装eclipse-adt</a></p>
</li>
<li>
<p><a href="http://developer.android.com/sdk/installing.html">安装android sdk</a></p>
</li>
<li>
<p><a href="http://developer.android.com/sdk/ndk/index.html">安装ndk</a></p>
</li>
</ul>
<p>开发环境搭好之后，再根据cocos2d-x官网提供的文档，教你如何把cocos2d-x的库中带的示例项目跑起来。</p>
<p>这里遇到两个问题。</p>
<ol>
<li>
<p>因为我使用了最新的ndk r7，再从命令行编译的时候会报错，是因为ndk r7的一个小改掉引起的，官网也同样提供了<a href="http://www.cocos2d-x.org/projects/cocos2d-x/wiki/Compilation_on_ndk-r7">解决方案</a>。</p>
</li>
<li>
<p>另外一个问题是，用eclipse打开示例项目之后，有错误提示：</p>
<blockquote>
<p>&#8230; must override a superclass method &#8230;</p>
</blockquote>
<p>这是因为eclipse默认的java compiler level是 1.5，在项目设定里面改成1.6就可以了。<a href="http://stackoverflow.com/questions/1678122/must-override-a-superclass-method-errors-after-importing-a-project-into-eclips">VIA</a></p>
</li>
</ol>
<p>在<a href="http://www.supersuraccoon-cocos2d.com/zh/2011/08/10/cocos2d-x-iphone-androidide-installation-and-setup-under-mac-os/">参考的博文</a>中还提到了<a href="http://gameit.ro/2011/08/creating-an-iphone-and-android-cocos2d-x-hybrid-project/">如何新建一个使用cocos2d-x的ios和android的混合项目</a>，有空再看看。</p>
<img src="http://feeds.feedburner.com/~r/SomethingLastForever/~4/P31Y8DD7vuA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ouyang.me/2011/12/cocos2dx-development-mac-os/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ouyang.me/2011/12/cocos2dx-development-mac-os/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=cocos2dx-development-mac-os</feedburner:origLink></item>
	<media:rating>nonadult</media:rating></channel>
</rss>

