<?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>Just another WordPress site</description>
	<lastBuildDate>Mon, 09 Jan 2012 02:00:17 +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>Just another WordPress site</itunes:subtitle><item>
		<title>刷火车票的shell脚本</title>
		<link>http://feedproxy.google.com/~r/SomethingLastForever/~3/6nxqxGsWtQ8/</link>
		<comments>http://blog.ouyang.me/2012/01/script-to-order-train-ticket-2/#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>
<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/6nxqxGsWtQ8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ouyang.me/2012/01/script-to-order-train-ticket-2/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-2/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=script-to-order-train-ticket-2</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>终端显示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>
<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>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>
<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>
		<item>
		<title>博客迁移到亚马逊的云服务</title>
		<link>http://feedproxy.google.com/~r/SomethingLastForever/~3/mWoWaDUUj-g/</link>
		<comments>http://blog.ouyang.me/2011/12/blog-migrate-to-amazon-cloud/#comments</comments>
		<pubDate>Tue, 06 Dec 2011 09:25:08 +0000</pubDate>
		<dc:creator>oylbin</dc:creator>
				<category><![CDATA[system administration]]></category>

		<guid isPermaLink="false">http://blog.ouyang.me/?p=591</guid>
		<description><![CDATA[7月的时候买了godaddy最便宜的web hosting套餐，价格比dreamhost便宜一半多，但是服务差的很多（或者说是不适合中国用户大陆用户）。 最主要的原因：经常访问不了，据说这是因为国内的运营商会每天固定时间屏蔽godaddy机器的IP，虽然不是godaddy的错，但是让人不爽。 web管理的页面速度很慢，需要用翻墙代理才会顺畅点。 ssh登陆机器后，速度很慢，也没有外网，根本不能用来翻墙，而且对于终端命令有诸多限制，连建个crontab的权限都没有。 这个最便宜的web hosting默认只能搭建一个web app，需要懂一点服务器的运维才能自己手动搭建多个wordpress。 人生就是不停的战斗折腾，所以，我决定把博客迁移到亚马逊上面去。 亚马逊提供一年的免费服务，我申请了一个。 因为之前搭建过好几台aws机器的环境，所以编译nginx，php都很顺利。不过那个机器毕竟是free的，性能实在是搓，编译的时候，好慢好慢。 机器配置好之后，唯一遇到的一个问题是80端口不通。通过google amazon free tier 80 port， 虽然没找到直接的答案，但是从这个页面发现 端口权限是和security group相关的，然后就在管理页面的security里面找到了相关的设置。 把原来的博客文件，数据库打个包传过来，然后改了blog.ouyang.me的DNS指向，现在一切ok了，访问起来很畅快。]]></description>
			<content:encoded><![CDATA[<p>7月的时候买了godaddy最便宜的web hosting套餐，价格比dreamhost便宜一半多，但是服务差的很多（或者说是不适合<strike>中国用户</strike>大陆用户）。</p>
<ul>
<li>最主要的原因：经常访问不了，据说这是因为国内的运营商会每天固定时间屏蔽godaddy机器的IP，虽然不是godaddy的错，但是让人不爽。</li>
<li>web管理的页面速度很慢，需要用翻墙代理才会顺畅点。</li>
<li>ssh登陆机器后，速度很慢，也没有外网，根本不能用来翻墙，而且对于终端命令有诸多限制，连建个crontab的权限都没有。</li>
<li>这个最便宜的web hosting默认只能搭建一个web app，需要懂一点服务器的运维才能自己手动搭建多个wordpress。</li>
</ul>
<p>人生就是不停的<strike>战斗</strike>折腾，所以，我决定把博客迁移到亚马逊上面去。</p>
<p>亚马逊提供<a href="http://aws.amazon.com/free/">一年的免费服务</a>，我申请了一个。<br />
因为之前搭建过好几台aws机器的环境，所以编译nginx，php都很顺利。不过那个机器毕竟是free的，性能实在是搓，编译的时候，好慢好慢。</p>
<p>机器配置好之后，唯一遇到的一个问题是80端口不通。通过google <a href="https://www.google.com/search?q=amazon+free+tier+80+port&amp;hl=en">amazon free tier 80 port</a>，<br />
虽然没找到直接的答案，但是从<a href="http://stackoverflow.com/questions/6377686/aws-free-tier-instance-port-discrepancy-from-security-group-specifications">这个页面</a>发现<br />
端口权限是和security group相关的，然后就在<a href="https://console.aws.amazon.com/ec2/home">管理页面</a>的security里面找到了相关的设置。</p>
<p>把原来的博客文件，数据库打个包传过来，然后改了blog.ouyang.me的DNS指向，现在一切ok了，访问起来很畅快。</p>
<img src="http://feeds.feedburner.com/~r/SomethingLastForever/~4/mWoWaDUUj-g" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ouyang.me/2011/12/blog-migrate-to-amazon-cloud/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://blog.ouyang.me/2011/12/blog-migrate-to-amazon-cloud/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=blog-migrate-to-amazon-cloud</feedburner:origLink></item>
		<item>
		<title>博客数据迁移</title>
		<link>http://feedproxy.google.com/~r/SomethingLastForever/~3/IWA-5SIICyc/</link>
		<comments>http://blog.ouyang.me/2011/12/blog-data-migration/#comments</comments>
		<pubDate>Tue, 06 Dec 2011 01:16:32 +0000</pubDate>
		<dc:creator>oylbin</dc:creator>
				<category><![CDATA[system administration]]></category>

		<guid isPermaLink="false">http://blog.ouyang.me/?p=590</guid>
		<description><![CDATA[昨天想把以前的博客数据迁移回来，遇到了两个问题。 换域名 google一下 修改配置 UPDATE wp_options SET option_value = replace(option_value, 'http://www.old-domain.com', 'http://www.new-domain.com') 修改博客文章的链接和文章内容中的链接 UPDATE wp_posts SET guid = replace(guid, 'http://www.old-domain.com','http://www.new-domain.com'); UPDATE wp_posts SET post_content = replace(post_content, 'http://www.old-domain.com', 'http://www.new-domain.com'); 转乱码 旧博客数据是用mysqldump导出的一个sql文件，现在迁移数据就是直接把这个sql导入到新的数据库里面去。 但是从wordpress直接访问的时候，所有的中文都是乱码。 从命令行连接到数据库，用select命令选出博客内容，中文却能正常展示。 搜了一下，这个是比较常见的乱码问题。这篇博客里有相关的解释。 我旧的博客数据库，mysql server使用latin1的编码保存utf8编码的字节流，mysql server和博客的php程序通讯也使用的latin1的编码， 而博客最终在展示出页面的时候使用utf8编码输出文字，所以能正确的显示中文。 如果在wordpress中设置 define('DB_CHARSET', 'utf8'); mysql server和php通讯时使用utf8编码，就会出现乱码。 从命令行连接时，mysql client也是用latin1编码和mysql server通讯，而我的terminal则是使用utf8编码展示文字，所以也能正确的显示中文。 如果在命令行设置 set names utf8 mysql server和mysql client通讯时使用utf8编码，终端显示也就会出现乱码。 虽然旧的方式也能正常工作，但总归不是最正确的方法。我需要把新的数据库默认编码设置为utf8，保持一致。 解决的办法： 先把备份的sql文件再次使用latin1编码导入数据库，再次用mysqldump导出数据，同时在参数中指明默认的编码 [...]]]></description>
			<content:encoded><![CDATA[<p>昨天想把以前的博客数据迁移回来，遇到了两个问题。</p>
<h4>换域名</h4>
<p><a href="https://www.google.com/search?q=wordpress+%E6%95%B0%E6%8D%AE%E5%BA%93+%E4%BF%AE%E6%94%B9%E5%9F%9F%E5%90%8D">google一下</a></p>
<ol>
<li>
<p>修改配置</p>
<pre><code>UPDATE wp_options SET option_value = replace(option_value, 'http://www.old-domain.com', 'http://www.new-domain.com')
</code></pre>
</li>
<li>
<p>修改博客文章的链接和文章内容中的链接</p>
<pre><code>UPDATE wp_posts SET guid = replace(guid, 'http://www.old-domain.com','http://www.new-domain.com');
UPDATE wp_posts SET post_content = replace(post_content, 'http://www.old-domain.com', 'http://www.new-domain.com');
</code></pre>
</li>
</ol>
<h4>转乱码</h4>
<p>旧博客数据是用mysqldump导出的一个sql文件，现在迁移数据就是直接把这个sql导入到新的数据库里面去。</p>
<ul>
<li>但是从wordpress直接访问的时候，所有的中文都是乱码。</li>
<li>从命令行连接到数据库，用select命令选出博客内容，中文却能正常展示。</li>
</ul>
<p>搜了一下，这个是比较常见的乱码问题。<a href="http://www.oicto.com/mysql-latin1-utf-8/">这篇博客</a>里有相关的解释。</p>
<p>我旧的博客数据库，mysql server使用latin1的编码保存utf8编码的字节流，mysql server和博客的php程序通讯也使用的latin1的编码，<br />
而博客最终在展示出页面的时候使用utf8编码输出文字，所以能正确的显示中文。<br />
如果在wordpress中设置</p>
<pre><code>define('DB_CHARSET', 'utf8');
</code></pre>
<p>mysql server和php通讯时使用utf8编码，就会出现乱码。</p>
<p>从命令行连接时，mysql client也是用latin1编码和mysql server通讯，而我的terminal则是使用utf8编码展示文字，所以也能正确的显示中文。<br />
如果在命令行设置</p>
<pre><code>set names utf8
</code></pre>
<p>mysql server和mysql client通讯时使用utf8编码，终端显示也就会出现乱码。</p>
<p>虽然旧的方式也能正常工作，但总归不是最正确的方法。我需要把新的数据库默认编码设置为utf8，保持一致。<br />
解决的办法：</p>
<ul>
<li>
<p>先把备份的sql文件再次使用latin1编码导入数据库，再次用mysqldump导出数据，同时在参数中指明默认的编码</p>
<pre><code>mysql --default-character-set=latin1 -uroot oylbin_blog &lt; old.sql
mysqldump --default-character-set=latin1 -uroot oylbin_blog &gt; new.sql
</code></pre>
</li>
<li>
<p>打开new.sql，把开头注释中的</p>
<pre><code>/*!40101 SET NAMES latin1 */;
</code></pre>
<p>修改为</p>
<pre><code>/*!40101 SET NAMES utf8 */;
</code></pre>
</li>
<li>
<p>再将new.sql使用utf8编码导入数据库</p>
<pre><code>mysql --default-character-set=utf8 -uroot oylbin_blog &lt; old.sql
</code></pre>
</li>
</ul>
<p>现在的问题是解决了，但是，最根本的原因还是不是理解得很透彻，还是有些疑问：</p>
<ol>
<li>在旧的数据库里面，为什么调用<code>set names utf8</code>之后，终端就会出乱码呢？</li>
<li>
<p>在mysql命令行中，可以用下面的命令查看编码相关的变量信息：</p>
<pre><code>SHOW VARIABLES LIKE 'character\_set\_%'
</code></pre>
<p>这些参数的含义是什么，它们是怎样影响到整个编码处理的流程的呢？<br />
这个问题也找到<a href="http://www.herongyang.com/PHP-Chinese/PHP-MySQL-Viewing-Character-Set-Variables.html">一篇相关的博客文章</a>，但是还没有细看，等有空的时候再仔细研究一下。</p>
</li>
</ol>
<p>根据之前的解释，在default-character-set=latin1时，mysql client和mysql server通讯的时，server把client发送过来的query string都认为是latin1编码的。<br />
我就在想，如果有下面这样一个insert语句</p>
<pre><code>insert into table_name values(123,'中文字符串⋯⋯')
</code></pre>
<p>如果中文字符串里面，正巧有某个中文字符的utf8编码的某一个字节和单引号(0&#215;27)相同，那么这个query string被server端解析的时候应该会出现语法错误吧。<br />
于是我就看了一下<a href="http://en.wikipedia.org/wiki/UTF-8">utf8的编码规则</a>，发现除了ascii的前127个字符，其他字符在utf编码时，所有的字节高位第一个bit都必然是1，所以不存在某个中文字符的字节中出现0&#215;27的情况。于是我又看了一下<a href="http://en.wikipedia.org/wiki/GBK">GBK</a>，<a href="http://en.wikipedia.org/wiki/GB_18030">GB18030</a>，<a href="http://en.wikipedia.org/wiki/Big5">BIG5</a>的编码规则，发现都是类似的情况，在一个字符需要多字节表示时，第一个字节高位必然是1，而后续字节中，一般都是从0&#215;40开始编码，不会出现小于0&#215;40的字节情况，这真是一件神奇的事情。为什么编码规则要设计成这样呢？而这种设计又正巧让mysql server可以在server端和client端编码实际上不一致的情况下正常工作⋯⋯</p>
<img src="http://feeds.feedburner.com/~r/SomethingLastForever/~4/IWA-5SIICyc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.ouyang.me/2011/12/blog-data-migration/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.ouyang.me/2011/12/blog-data-migration/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=blog-data-migration</feedburner:origLink></item>
	<media:rating>nonadult</media:rating></channel>
</rss>

