<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Inspiration from life</title>
    <link>https://blog.chengbo.net</link>
    <description>Inspiration from life</description>
    <atom:link href="https://blog.chengbo.net/feed.xml" rel="self" type="application/rss+xml"/>
    <language>en-us</language>
    <lastBuildDate>Tue, 03 Mar 2026 13:17:00 +0000</lastBuildDate>
    
    <item>
      <title>惹怒战争部，反成大赢家？一场改变AI历史的底线保卫战</title>
      <link>https://blog.chengbo.net/2026/03/03/anthropic-openai-dow-contract-fallout.html</link>
      <guid isPermaLink="true">https://blog.chengbo.net/2026/03/03/anthropic-openai-dow-contract-fallout.html</guid>
      <pubDate>Tue, 03 Mar 2026 13:17:00 +0000</pubDate>
      <description>这是一场发生在2026年2月底的硅谷大戏。一边是手握重权的美国战争部（也就是原来的国防部），另一边是当今世界上最顶尖的两大AI巨头：Anthropic与OpenAI。 因为一份军方合同，两家公司做出了截然不同的选择。这不仅引发了美国政界与科技界的正面博弈，更在短短几天内引发了一场史无前例的“用户大迁徙”。 让我们沿着…</description>
      <content:encoded><![CDATA[<p>这是一场发生在2026年2月底的硅谷大戏。一边是手握重权的美国战争部（也就是原来的国防部），另一边是当今世界上最顶尖的两大AI巨头：Anthropic与OpenAI。</p>
<p>因为一份军方合同，两家公司做出了截然不同的选择。这不仅引发了美国政界与科技界的正面博弈，更在短短几天内引发了一场史无前例的“用户大迁徙”。</p>
<p>让我们沿着时间线，来看看这场由AI价值观引发的惊天逆转是如何发生的。</p>
<h3>2026年2月26日：不屈的底线与军方的威胁</h3>
<p>故事的起因要追溯到Anthropic与美国战争部（DoW）的内部博弈。Anthropic一直是美国政府的AI供应商，但他们为AI的军事应用划定了两条不可触碰的“红线”：<strong>绝不用于大规模国内监控（Mass domestic surveillance），绝不用于全自主武器（Fully autonomous weapons，不需要人类干预就可以自主搜索，识别并攻击目标的武器）</strong>。</p>
<p>然而，战争部不仅拒绝了这些安全屏障，要求获得“任何合法用途”的无限制访问权，甚至发出威胁：如果Anthropic不妥协，就将其标记为“供应链风险”（这是一个通常只针对敌对国家的标签，从未贴在一个美国公司头上），并动用《国防生产法》强制执行，这意味着Anthropic在本土不仅失去了军方订单，还面临被列入“科技黑名单”的生存危机。</p>
<p>面对军方施压，Anthropic CEO Dario Amodei在2月26日公开发表声明，态度极其强硬：“我们无法昧着良心答应他们的要求”。</p>
<h3>2026年2月27日：战争部长的怒火与用户的觉醒</h3>
<p>Anthropic的“不听话”彻底惹怒了战争部长 Pete Hegseth。他在社交平台X上火力全开，痛批Anthropic坚持安全限制的做法是“傲慢与背叛”。他严厉指责Anthropic及其CEO Dario Amodei在搞“虚伪的有效利他主义”（Effective altruism），并声称他们试图迫使美国军队屈服，是将“硅谷意识形态凌驾于美国人的生命和战场安全之上”。Hegseth强调，Anthropic的真正目的是试图对美国军队的行动决策行使“否决权”，这是军方绝对无法接受的。他指出，军队的命运只能由总司令和美国人民来决定，决不能被“未经选举的科技高管”或科技巨头的意识形态所左右。Hegseth正式下达指令，将Anthropic认定为国家安全的“供应链风险”，并下令切断美国军方及其所有承包商、合作伙伴与Anthropic的商业联系。</p>
<p>Anthropic并未退缩，他们在同日回应称这一决定“在法律上站不住脚”，并誓言将在法庭上抗争到底，同时向普通用户保证，商业版和个人版的Claude服务绝不受影响。</p>
<p>有趣的是，公众的眼睛是雪亮的。就在这一天，认同Anthropic立场的美国消费者开始用脚投票：Claude的日下载量激增了37%。</p>
<h3>2026年2月28日：OpenAI“接盘”，引爆公关灾难</h3>
<p>就在Anthropic被军方封杀的第二天，它的最大竞争对手OpenAI高调出场了。</p>
<p>OpenAI在2月28日宣布，他们已经与五角大楼达成了一项在机密环境中部署高级AI系统的协议。虽然OpenAI在公告中极力强调，他们的合同包含严格的屏障，同样禁止国内监控和全自主武器，并且采用了“全云端部署”和“人工审查”等比Anthropic更严密的保护措施，但公众并不买账。</p>
<p><strong>后果如海啸般袭来：</strong></p>
<ul>
<li><strong>卸载狂潮</strong>：当OpenAI与战争部合作的消息传出后，美国用户手机上的ChatGPT卸载量在2月28日当天如同火箭般飙升了295%（对比过去30天平均仅9%的日卸载率）。</li>
<li><strong>差评淹没</strong>：愤怒的消费者涌入应用商店，ChatGPT的1星差评在周六单日暴涨775%，5星好评则腰斩了一半。</li>
<li><strong>王者易主</strong>：与ChatGPT的惨淡形成鲜明对比，Claude不仅在28日当天的美国日下载量反超ChatGPT（激增51%），更是直接空降美国App Store免费榜的第一名。Claude不仅在美国爆火，还在比利时、加拿大、德国等六个海外国家登顶了iPhone免费榜第一。</li>
</ul>
<p>公众用极其强烈的反差，表达了对Anthropic拒绝妥协的赞赏，以及对OpenAI与军方合作的抵触。</p>
<h3>2026年3月1日-2日：甜蜜的烦恼与紧急补救</h3>
<p>大量用户的疯狂涌入，给Anthropic带来了“泼天的流量”。由于过去几天经历了“史无前例的需求”，Claude的服务器挂了。从3月2日早晨开始，Claude Chatbot、Claude Console以及Claude Code全线遭遇技术故障，直到当天下午才恢复正常运行。</p>
<p>另一边，眼看用户流失惨重，OpenAI不得不紧急进行危机公关。他们在3月2日对声明进行了更新，特意补充说明他们与战争部“共同增加了额外的条款”，白纸黑字地写明其工具“绝对不会被用于对美国人进行国内监控”，也不会被NSA（美国国家安全局）等情报机构使用，试图挽回公众的信任。然而在回答“为什么Anthropic不能达成协议而OpenAI能”的问题时，OpenAI说“不知道”。</p>
<p>ChatGPT的下载量在周日依然持续下跌了5%。</p>
<h3>总结</h3>
<p>这场风波堪称科技史上罕见的奇景。一次原本属于国家机器与商业公司之间的合同博弈，最终演变成了一场全民参与的“AI道德投票”。Anthropic凭借宁可舍弃巨额军方订单、背负“国家安全风险”罪名也要坚守底线的骨气，赢得了用户的疯狂追捧。而顺势接下合同的OpenAI，尽管一再解释其安全机制，却被迫咽下了卸载量暴增295%，口碑暴跌的苦果。这不仅改变了两大AI巨头的市场格局，也为未来AI技术与国家机器的合作划下了一道深深的警戒线。</p>
<h3>我个人的反应</h3>
<p>我也退订了ChatGPT而转投了Claude，在这个AI逐渐握有权力的时代，作为用户，我能做的只有给那个愿意说“不”的公司一张选票。抱歉了，OpenAI。</p>]]></content:encoded>
    </item>
    
    <item>
      <title>Create a remote command line environment with git vim tmux zsh mosh and docker</title>
      <link>https://blog.chengbo.net/2018/06/10/build-a-remote-command-line-environment-with-git-tmux-zsh-mosh-and-docker.html</link>
      <guid isPermaLink="true">https://blog.chengbo.net/2018/06/10/build-a-remote-command-line-environment-with-git-tmux-zsh-mosh-and-docker.html</guid>
      <pubDate>Sun, 10 Jun 2018 16:12:22 +0000</pubDate>
      <description>Sometimes I&#39;m halfway through writing code at the company and it&#39;s time to get out of work, the work isn&#39;t done and isn&#39;t pushed to the remote repository, so i…</description>
      <content:encoded><![CDATA[<p>Sometimes I'm halfway through writing code at the company and it's time to get out of work, the work isn't done and isn't pushed to the remote repository, so it's not convenient if I want to proceed at home. Or at home, I'm writing code on a PC, my kids want to play PC games for a while, it is also troublesome to switch to the Mac to continue my work.</p>
<p>So I came up with an idea to set up a remote working environment on my VPS. No matter where or even with only iPad, as long as there's internet and a SSH client, I can connect to it, proceed to code in the same environment as I left it.</p>
<p>This article is to share my remote text only command line environment created by git tmux zsh mosh and docker, as shown below.</p>
<p><img alt="vim tmux" src="/static/images/2018/06/vim-tmux.jpg" /></p>
<h2>Docker</h2>
<p>First of all, this environment should have a great portability. It takes a certain number of steps and time to set up this environment, so if the VPS provider is changed, I don't want to do these repetitive work again. So I created this environment in docker, the steps are written in <a href="https://github.com/chengbo/remote-dev/blob/master/Dockerfile">Dockerfile</a>, you can see more detail information if you are interested.</p>
<h2>Git</h2>
<p>Git is of course a must, not only the day-to-day development require it, but some of the tools in this environment need it to get the code to compile/install as well.</p>
<h2>Zsh &amp; Oh My ZSH</h2>
<p>Zsh is undoubtedly more advanced than Bash, with <a href="http://ohmyz.sh">Oh My ZSH</a> is even more powerful，it gives your better auto completion, navigation, git support and themes.</p>
<h2>Vim</h2>
<p>The most powerful text editor in the planet. I also have some plugins installed, makes it act like an IDE.</p>
<h2>Tmux</h2>
<p>Tmux is a screen multiplexer, similar to <a href="https://www.gnu.org/software/screen/">GNU Screen</a>. It gives you "tabs" for non-Vim related stuff like shell, git, unit test and so on. It also keep sessions when you switching between multiple projects.</p>
<h2>Tig</h2>
<p>This is a fantastic text-mode interface for git, it works just like <a href="https://www.sourcetreeapp.com/">SourceTree</a> on Mac. You can view logs, diff status, and anything you can think of.</p>
<p>It looks like below.</p>
<p><img alt="vim tmux" src="/static/images/2018/06/tig.jpg" /></p>
<h2>Mosh</h2>
<p><a href="https://mosh.org">Mosh</a> is similar to SSH, and works better on poor network conditions and mobile roaming connections. It has lower latency and keeps connected between different networks. You are gonna love it.</p>
<p><strong>Ubuntu server</strong><br />
Because the true color support is not in latest version 1.3.2, so you have to use below dev version to make Tmux and Vim theme works correctly.</p>
<pre><code>sudo add-apt-repository ppa:keithw/mosh-dev
sudo apt update
sudo apt install mosh
</code></pre>
<p><strong>Windows &amp; Chromebook Client</strong><br />
Install this <a href="https://chrome.google.com/webstore/detail/mosh/ooiklbnjmhbcgemelgfhaeaocllobloj">Chrome Extension</a>.</p>
<p><strong>Mac client</strong><br />
Because the true color support is not in latest version 1.3.2, so you have to use HEAD version to make Tmux and Vim theme work correctly.</p>
<pre><code>brew install --HEAD mosh
</code></pre>
<p><strong>iPad client</strong><br />
Install this <a href="https://itunes.apple.com/app/id1156707581">App</a>.</p>
<h2>Conclusion</h2>
<p>All above tools can work without a mouse, more productivity! Some of these tools settings highly depend on my <a href="https://github.com/chengbo/dotfiles">dotfiles</a>.</p>
<p>Although it is built for Python development, you can also change the configuration according to your needs and build your own remote command line environment.</p>]]></content:encoded>
    </item>
    
    <item>
      <title>Ubuntu上TensorFlow安装步骤</title>
      <link>https://blog.chengbo.net/2017/05/01/install-nvidia-cuda-cudnn-tensorflow-on-ubuntu-desktop-17-04.html</link>
      <guid isPermaLink="true">https://blog.chengbo.net/2017/05/01/install-nvidia-cuda-cudnn-tensorflow-on-ubuntu-desktop-17-04.html</guid>
      <pubDate>Mon, 01 May 2017 17:33:00 +0000</pubDate>
      <description>深度学习(Deep learning)目前挺火的，我也准备赶一下潮流，提升一下自己。正好长草GTX 1060很久了，一直没买，这次就趁着这次想要学习的机会咬牙割肉买了张，就算半途而废了，也可以玩玩游戏。1070等就不考虑了，钱包不够。 买回来把显卡装上，进Windows 10，装驱动，然后玩了一把星际争霸（一代），居…</description>
      <content:encoded><![CDATA[<p>深度学习(Deep learning)目前挺火的，我也准备赶一下潮流，提升一下自己。正好长草GTX 1060很久了，一直没买，这次就趁着这次想要学习的机会咬牙割肉买了张，就算半途而废了，也可以玩玩游戏。1070等就不考虑了，钱包不够。</p>
<p>买回来把显卡装上，进Windows 10，装驱动，然后玩了一把星际争霸（一代），居然没感觉比我之前用的Intel HD 4600有什么提升，差评，想退货了（玩笑）。</p>
<p>言归正传，深度学习有不少框架，我随便选了个TensorFlow来入门。根据<a href="https://www.tensorflow.org/install/">安装文档</a>，一步一步的装好，步骤记录如下：</p>
<h2>安装Ubuntu</h2>
<p>我安装的是最新的Ubuntu Desktop 17.04。<a href="https://www.ubuntu.com/download/desktop">下载</a>一个ISO文件做成启动U盘，然后跟着提示安装即可。</p>
<h2>安装NVIDIA驱动</h2>
<pre><code># add-apt-repository ppa:graphics-drivers/ppa
# apt update
# apt install nvidia-375
</code></pre>
<h2>安装CUDA® Toolkit 8.0</h2>
<p>去<a href="https://developer.nvidia.com/cuda-downloads">NVIDIA网站</a>下载安装包，选择Linux，x86_64，Ubuntu，16.04，deb (local)</p>
<pre><code># dpkg -i /path/to/your/file-just-downloaded.deb
# apt update
# apt install cuda
</code></pre>
<p>设置环境变量</p>
<pre><code>export PATH=/usr/local/cuda/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
export CUDA_HOME=/usr/local/cuda
</code></pre>
<p>也可以把上面的设置放到<code>~/.profile</code>里，永久生效。</p>
<h2>安装cuDNN</h2>
<p>去<a href="https://developer.nvidia.com/rdp/cudnn-download">NVIDIA网站</a>下载安装包，下载前需要登录，如果没有帐号，可以先注册一个，免费的。
选择
Download cuDNN v5.1 (Jan 20, 2017), for CUDA 8.0
cuDNN v5.1 Library for Linux
下载后</p>
<pre><code>$ tar -zxvf /path/to/your/file-just-downloaded.tgz
# cp cuda/include/*.h /usr/local/cuda/include
# cp cuda/lib64/* /usr/local/cuda/lib64
</code></pre>
<h2>安装libcupti-dev</h2>
<pre><code># apt install libcupti-dev
</code></pre>
<h2>安装virtualenv</h2>
<pre><code># apt install python-pip python-dev python-virtualenv
</code></pre>
<h2>安装TensorFlow</h2>
<pre><code>$ virtualenv --system-site-packages ~/tensorflow
$ cd ~/tensorflow
$ source bin/active
$ pip install tensorflow-gpu
</code></pre>
<h2>验证安装</h2>
<pre><code>$ python
&gt;&gt;&gt; import tensorflow as tf
&gt;&gt;&gt; hello = tf.constant('Hello, TensorFlow!')
&gt;&gt;&gt; sess = tf.Session()
&gt;&gt;&gt; print(sess.run(hello))
</code></pre>
<p>如果看到有输出Hello, TensorFlow!，就说明安装成功了。</p>]]></content:encoded>
    </item>
    
    <item>
      <title>虚拟机共享目录引起的权限问题</title>
      <link>https://blog.chengbo.net/2016/12/24/virtualbox-shared-folder-docker-permission-issue.html</link>
      <guid isPermaLink="true">https://blog.chengbo.net/2016/12/24/virtualbox-shared-folder-docker-permission-issue.html</guid>
      <pubDate>Sat, 24 Dec 2016 23:14:00 +0000</pubDate>
      <description>我在写代码的时候，不喜欢在mac上装相关依赖的组件，因为不同项目之间的依赖冲突有点麻烦，而且久而久之会污染我mac环境。所以我有一个VirtualBox，里面弄一个ubuntu的虚拟机，ssh进去安装，这个虚拟机可以随时抛弃，再重新建立。 但同时我又非常喜欢mac的GUI，所以我把开发目录在Host（mac）和Gue…</description>
      <content:encoded><![CDATA[<p>我在写代码的时候，不喜欢在mac上装相关依赖的组件，因为不同项目之间的依赖冲突有点麻烦，而且久而久之会污染我mac环境。所以我有一个VirtualBox，里面弄一个ubuntu的虚拟机，ssh进去安装，这个虚拟机可以随时抛弃，再重新建立。</p>
<p>但同时我又非常喜欢mac的GUI，所以我把开发目录在Host（mac）和Guest（ubuntu）之间建立共享（shared folder）。这样一来，我既可以拥有和生产环境一模一样的开发环境，也可以享受mac极好的GUI体验。</p>
<p>这样的开发方案一直很完美，直到有一天，发现了一个奇怪的问题……</p>
<p>我有一个docker的container运行在ubuntu里，这个container需要一个自定义的conf文件，由volume挂载进去。container启动后会自动往conf文件里添加一些内容。这个conf文件放在shared folder上，再volume进container。</p>
<p>当运行这个container的时候，我发现container在conf要写的内容死活写不进去。可是相同的代码，在mac上直接运行docker，则一切正常。</p>
<p>我花了好几个小时才找到原因：</p>
<ul>
<li>ubuntu的conf文件的权限是770</li>
<li>这个文件是<code>root:vboxsf</code></li>
<li>container运行的帐号没权限写vboxsf的文件</li>
</ul>
<p>那么解决方案就是，把文件改成<code>yourname:docker</code></p>
<p>可是直接用chown，改不了，所以换另外一个办法，不用VirtualBox的自动挂载，自己用命令手动挂</p>
<p>首先找出你的帐号的uid</p>
<pre><code class="language-bash">$ id -u $whoami
1000
</code></pre>
<p>再找docker的gid</p>
<pre><code class="language-bash">$ cut -d: -f3 &lt; &lt;(getent group docker)
999
</code></pre>
<p>挂上去，这里<code>dev</code>是我的挂载名字</p>
<pre><code class="language-bash">sudo mount -t vboxsf -o remount,gid=999,uid=1000,rw dev /media/sf_dev
999
</code></pre>
<p>这样重新启动ubuntu后，文件变成<code>yourname:docker</code>了，再运行container就没问题了。可是这种挂载方式重启ubuntu会丢，想要一直保持的话，用下面的方法</p>
<p>把下面的内容加到<code>/etc/modules</code>里</p>
<pre><code>vboxsf
</code></pre>
<p>把下面的内容加到<code>/etc/fstab</code>里</p>
<pre><code>dev /media/sf_dev vboxsf gid=999,uid=1000,rw 0 0
</code></pre>
<p>That is it.</p>]]></content:encoded>
    </item>
    
    <item>
      <title>新配了一台电脑</title>
      <link>https://blog.chengbo.net/2015/02/16/diy-i5-4690k-computer.html</link>
      <guid isPermaLink="true">https://blog.chengbo.net/2015/02/16/diy-i5-4690k-computer.html</guid>
      <pubDate>Mon, 16 Feb 2015 15:14:00 +0000</pubDate>
      <description>我 上次配PC已经是07年那会儿 了，当时就是为了玩WOW。后来电脑就买了台ThinkPad、一台MacBook Pro和一台ATOM下载机。再后来逐渐从WOW中AFK，再加上Apple革命，对PC的需求就越来越少了。 最近心里一直在长草，想回WOW怀怀旧，而且一直口水一些单机游戏（比如即将发布的PC版GTA 5），…</description>
      <content:encoded><![CDATA[<p>我<a href="http://blog.chengbo.net/2007/03/11/new-computer-new-os.html">上次配PC已经是07年那会儿</a>了，当时就是为了玩WOW。后来电脑就买了台ThinkPad、一台MacBook Pro和一台ATOM下载机。再后来逐渐从WOW中AFK，再加上Apple革命，对PC的需求就越来越少了。</p>
<p>最近心里一直在长草，想回WOW怀怀旧，而且一直口水一些单机游戏（比如即将发布的PC版GTA 5），所以一直也想配一台PC来玩玩。如今在美帝生活压力颇大，几乎没有余钱可供挥霍，所以老婆一直没有批预算。前不久主动分担了些家务，老婆龙心大悦，对花钱这事算默认了，所以才有了下面的这些。</p>
<p>很久没关注DIY了，在NGA硬件版潜水了几天，狠狠地恶补了下。参考<a href="http://bbs.ngacn.cc/read.php?tid=7088772">神贴</a>，再根据广大美帝人民的评价，稍微做了些调整，配置如下：</p>
<table>
<thead>
<tr>
<th style="text-align: left;">Type</th>
<th style="text-align: left;">Item</th>
<th style="text-align: left;">Price</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;"><strong>CPU</strong></td>
<td style="text-align: left;"><a href="http://pcpartpicker.com/part/intel-cpu-bx80646i54690k">Intel Core i5-4690K 3.5GHz Quad-Core Processor</a></td>
<td style="text-align: left;">$239.99 @ Tigerdirect</td>
</tr>
<tr>
<td style="text-align: left;"><strong>CPU Cooler</strong></td>
<td style="text-align: left;"><a href="http://pcpartpicker.com/part/cooler-master-cpu-cooler-rr212e20pkr2">Cooler Master Hyper 212 EVO 82.9 CFM Sleeve Bearing CPU Cooler</a></td>
<td style="text-align: left;">$34.99 @ Newegg</td>
</tr>
<tr>
<td style="text-align: left;"><strong>Motherboard</strong></td>
<td style="text-align: left;"><a href="http://pcpartpicker.com/part/asrock-motherboard-z97extreme6">ASRock Z97 EXTREME6 ATX LGA1150 Motherboard</a></td>
<td style="text-align: left;">$154.99 @ Newegg</td>
</tr>
<tr>
<td style="text-align: left;"><strong>Memory</strong></td>
<td style="text-align: left;"><a href="http://pcpartpicker.com/part/gskill-memory-f31866c9d16gxm">G.Skill Ripjaws X Series 16GB (2 x 8GB) DDR3-1866 Memory</a></td>
<td style="text-align: left;">$134.99 @ Newegg</td>
</tr>
<tr>
<td style="text-align: left;"><strong>Storage</strong></td>
<td style="text-align: left;"><a href="http://pcpartpicker.com/part/samsung-internal-hard-drive-mz7te120bw">Samsung 840 EVO 120GB 2.5" Solid State Drive</a></td>
<td style="text-align: left;">$69.99 @ Tigerdirect</td>
</tr>
<tr>
<td style="text-align: left;"><strong>Storage</strong></td>
<td style="text-align: left;"><a href="http://pcpartpicker.com/part/western-digital-internal-hard-drive-wd30efrx">Western Digital Red 3TB 3.5" 5400RPM Internal Hard Drive</a></td>
<td style="text-align: left;">$99.91 @ Tigerdirect</td>
</tr>
<tr>
<td style="text-align: left;"><strong>Case</strong></td>
<td style="text-align: left;"><a href="http://pcpartpicker.com/part/rosewill-case-challenger">Rosewill CHALLENGER ATX Mid Tower Case</a></td>
<td style="text-align: left;">$59.99 @ Newegg</td>
</tr>
<tr>
<td style="text-align: left;"><strong>Power Supply</strong></td>
<td style="text-align: left;"><a href="http://pcpartpicker.com/part/rosewill-power-supply-hive550">Rosewill Hive 550W 80+ Bronze Certified Semi-Modular ATX Power Supply</a></td>
<td style="text-align: left;">$59.99 @ Newegg</td>
</tr>
<tr>
<td style="text-align: left;"><strong>Monitor</strong></td>
<td style="text-align: left;"><a href="http://pcpartpicker.com/part/dell-monitor-m2gcr">Dell U2412M 60Hz 24.0" Monitor</a></td>
<td style="text-align: left;">$243.44 @ Newegg</td>
</tr>
</tbody>
</table>
<ul>
<li><em>其中两块硬盘是之前ATOM下载机在用的，自从HDC倒掉之后，这台下载机也就没开机了。显示器是前年买来给MacBook外接用的。</em></li>
<li><em>没有配独立显卡，反正最近也就玩玩WOW和Diablo，分辨率和特效低一些的话，HD 4600还是可以胜任的。将来等GTX 970便宜一些再下手。</em></li>
</ul>
<p>选i5而没有选i7或E3，是因为我不会多开游戏，而且没有处理渲染视频的需求，所以i7和E3的超线程技术对我来说没什么用。而且据说i7本来自身的频率就比较高了，能够超频的空间不大，还要再配一个高端的主板，要多花不少银子。i5随便超超就4.5GHz了，对于WOW这种CPU游戏来说，提升是巨大的。E3不能超频，超线程又用不到，对我来说没什么性价比，而且没有集显，必须立刻配一个独显，灵活性不高。</p>
<p>散热器是挑了个评价好的，销量高的，哥懒得去看什么CPU温度之类的，不过感觉这货体积巨大，散热效果应该不错吧，哈哈。</p>
<p>主板挑了个性价比高的品牌，做工确实不错哈，CPU供电貌似很NB，我也懒得研究是几相了。老婆看到这货，说，挺漂亮啊，比我之前的主板漂亮多了，你花了多少钱啊？哥赶紧解释，中档货而已，没花多少钱。。。</p>
<p>内存选了个1866的，据说频率对日常使用的影响，除了跑分，其它基本感受不出来，所以也就挑了个评价好的，销量高的。另外颜色和主板也配。纠结了下8G还是16G，双通道还是单条。最后考虑到是集显，还是双通道比较好，咬咬牙，上16吧，免得后悔。</p>
<p>120G的SSD，游戏不能装太多，稍微有些捉襟见肘。3T的红盘用在PC上，感觉有些不合适，不过先将就着吧。</p>
<p>机箱在70刀以内的范围内，挑了个评价好，销量高的中塔。做工还是不错，顶部、前部和后部各一个风扇，底部电源位也有进气口。免工具安装，基本不会划着手。可惜没有前置USB 3.0，不过还可以接受。</p>
<p>电源选了个标称550W，其中最重要的12V输出495W的，将来就算再加一个独显也足够我用了。这货是模块化设计，第一次接触这玩意儿，感觉挺新鲜的。</p>
<p>显示器很早买的，IPS屏，16:10的，据说色彩不错，不过我也分辨不出来，8ms的响应时间，中规中矩吧。</p>
<p>虽然之前自己配，和帮别人配过不少电脑，可是我只写单子，电脑都是由卖家装好的，自己从未动过手，每次打开机箱看到主板上那密密麻麻的接线就头大。在美帝就只能自己动手了，在youtube上看过一些教程，再研究下主板说明书，花了3个多小时，硬着头皮还是装好了。涂硅脂，上主板，走背线，完成后机箱看起来整洁有序，挺有成就感。</p>
<p>现在主板都是UEFI了，NB惨了，超频那叫一个傻瓜，点几次鼠标选个想超多少，保存重启就OK了。哥年纪大了，实在没的兴趣去研究电压到底加多少，极限频率是多少，这种傻瓜超频太对哥的胃口了，省心省力，安逸。</p>
<p>这次配完有个感触：<strong>现在的电脑，比之前的要贵很多</strong>。我不是说性价比，而是说，同样的档次，算当时的价格，现在的电脑要贵的多。我记得原来配一个700的CPU，700的主板，700的显卡，就算是中档了，可是现在100美元的CPU、主板、显卡，可算不上中档。电子产品只会越来越便宜，怎么这还越来越贵了呢？后来想想原因，可能是因为<strong>中档的门槛高了</strong>。以前DIY的低端市场，已经被便宜的笔记本，或者说iPhone，iPad抢走了。现今还要DIY的人群，是对性能有一定要求的。现在的低端，相当于原来的中端；现在的中端，相当于原来的高端；现在的高端，就相当于原来的超高端。从现在的板卡的做工就可以看出来，100美元的主板，基本都是全固态电容，N相供电，各式各样的颜色，漂亮的光线效果。100美元的显卡，漂亮的logo，光线，大风扇，N个外接接口。这在原来，是不可想象的，PC市场，销量尽管下滑，不过他们的利润有没有下滑，我就不知道了。</p>]]></content:encoded>
    </item>
    
    <item>
      <title>rebase之后如何避免使用git push -f来提交代码的规范流程</title>
      <link>https://blog.chengbo.net/2014/04/10/how-to-prevent-git-push-force.html</link>
      <guid isPermaLink="true">https://blog.chengbo.net/2014/04/10/how-to-prevent-git-push-force.html</guid>
      <pubDate>Thu, 10 Apr 2014 17:04:08 +0000</pubDate>
      <description>这篇blog的内容是我在segmentfault上的一个回答，转帖过来。 提问者提问的大意是，他们团队成员为了提交历史的干净整洁，所以经常会 git rebase ，但是这样在提交代码的时候，就会频繁的发现冲突，只能使用 git push -f 来强制提交，不知道是否合理。 以下是我的回答： git rebase 是…</description>
      <content:encoded><![CDATA[<p>这篇blog的内容是我在segmentfault上的一个回答，转帖过来。</p>
<p>提问者提问的大意是，他们团队成员为了提交历史的干净整洁，所以经常会<code>git rebase</code>，但是这样在提交代码的时候，就会频繁的发现冲突，只能使用<code>git push -f</code>来强制提交，不知道是否合理。</p>
<p>以下是我的回答：</p>
<p><code>git rebase</code>是对commit history的改写。当你要改写的commit history还没有被提交到远程repo的时候，也就是说，<strong>还没有与他人共享之前</strong>，commit history是你私人所有的，那么想怎么改写都可以。</p>
<p>而一旦被提交到远程后，这时如果再改写history，那么势必和他人的history长的就不一样了。<code>git push</code>的时候，git会比较commit history，如果不一致，commit动作会被拒绝，唯一的办法就是带上<code>-f</code>参数，强制要求commit，这时git会以committer的history覆写远程repo，从而完成代码的提交。虽然代码提交上去了，但是这样可能会造成别人工作成果的丢失，所以使用<code>-f</code>参数要慎重。</p>
<p><strong>楼主遇到的问题，就是改写了公有的commit history造成的。</strong>要解决这个问题，就要从提交流程上做规范。</p>
<p>举个正确流程的栗子：</p>
<p>假设楼主的team中有两个developer：tom和jerry，他们共同使用一个远程repo，并各自clone到自己的机器上，为了简化描述，这里假设只有一个branch：<code>master</code>。</p>
<p>这时tom机器的repo有两个branch
<code>master</code>, <code>origin/master</code>
而jerry的机器上也是有两个branch
<code>master</code>, <code>origin/master</code></p>
<p>均如下图所示</p>
<p><img alt="" src="//segmentfault.com/img/bVb0wO" /></p>
<p>tom和jerry分别各自开发自己的新feature，不断有新的commit提交到他们各自私有的commit history中，所以他们的master指针不断的向前推移，分别指向不同的commit。而又由于他们都没有<code>git fetch</code>和<code>git push</code>，所以他们的<code>origin/master</code>都维持不变。</p>
<p>jerry的repo如下</p>
<p><img alt="" src="//segmentfault.com/img/bVb0wQ" /></p>
<p>tom的repo如下，注意<code>T1</code>和上图的<code>J1</code>，分别是两个不同的commit</p>
<p><img alt="" src="//segmentfault.com/img/bVb0wR" /></p>
<p>这时Tom首先把他的commit提交的远程repo中，那么他本机<code>origin/master</code>指针则会前进，和<code>master</code>指针保持一致，如下</p>
<p><img alt="" src="//segmentfault.com/img/bVb0wT" /></p>
<p>远程repo如下</p>
<p><img alt="" src="//segmentfault.com/img/bVb0wS" /></p>
<p>现在jerry也想把他的commit提交到远程repo上去，运行<code>git push</code>，毫无意外的失败了，所以他<code>git fetch</code>了一下，把远程repo，也就是之前tom提交的<code>T1</code>给拉到了他本机repo中，如下</p>
<p><img alt="" src="//segmentfault.com/img/bVb0wU" /></p>
<p>commit history出现了分叉，要想把tom之前提交的内容包含到自己的工作中来，有一个方法就是<code>git merge</code>，它会自动生成一个commit，既包含tom的提交，也包含jerry的提交，这样就把两个分叉的commit重新又合并在一起。但是这个自动生成的commit会有两个parent，review代码的时候必须要比较两次，很不方便。</p>
<p>jerry为了保证commit history的线性，决定采用另外一种方法，就是<code>git rebase</code>。jerry的提交<code>J1</code>这时还没有被提交到远程repo上去，也就是他完全私有的一个commit，所以使用<code>git rebase</code>改写<code>J1</code>的history完全没有问题，改写之后，如下</p>
<p><img alt="" src="//segmentfault.com/img/bVb0wV" /></p>
<p>注意<code>J1</code>被改写到<code>T1</code>后面了，变成了<code>J1`</code></p>
<p><code>git push</code>后，本机repo</p>
<p><img alt="" src="//segmentfault.com/img/bVb0wW" /></p>
<p>而远程repo</p>
<p><img alt="" src="//segmentfault.com/img/bVb0wX" /></p>
<p>异常的轻松，一条直线，没有<code>-f</code></p>
<p>所以，在不用<code>-f</code>的前提下，想维持树的整洁，方法就是：在<code>git push</code>之前，先<code>git fetch</code>，再<code>git rebase</code>。</p>
<pre><code>git fetch origin master
git rebase origin/master
git push
</code></pre>
<p>强烈推荐阅读</p>
<ul>
<li><a href="http://nvie.com/posts/a-successful-git-branching-model/">a successful git branching model</a></li>
<li><a href="http://git-scm.com/book/zh/Git-%E5%88%86%E6%94%AF-%E5%88%86%E6%94%AF%E7%9A%84%E8%A1%8D%E5%90%88">Git-分支-分支的衍合</a></li>
</ul>]]></content:encoded>
    </item>
    
    <item>
      <title>Google chromecast伪开箱</title>
      <link>https://blog.chengbo.net/2013/08/23/google-chromecast-unboxing.html</link>
      <guid isPermaLink="true">https://blog.chengbo.net/2013/08/23/google-chromecast-unboxing.html</guid>
      <pubDate>Fri, 23 Aug 2013 20:59:08 +0000</pubDate>
      <description>这是一篇伪开箱，因为这个chromecast不是我买的，而是公司老大的，借我用段时间。Google刚发布这货的时候，老大就买了，再后来Google Play，Amazon，Bestbuy全线缺货，看样子挺火。 Chromecast是Google于今年7月24号发布的一个小型流媒体播放器，它可以把电脑、手机、平板上的W…</description>
      <content:encoded><![CDATA[<p>这是一篇伪开箱，因为这个chromecast不是我买的，而是公司老大的，借我用段时间。Google刚发布这货的时候，老大就买了，再后来Google Play，Amazon，Bestbuy全线缺货，看样子挺火。</p>
<p>Chromecast是Google于今年7月24号发布的一个小型流媒体播放器，它可以把电脑、手机、平板上的Web和视频内容同步到电视上播放。它接入WIFI后，插入电视的HDMI接口，播放同步过来的多媒体内容。相比之前发布的Google TV，它体积小巧，没有多余的功能，售价仅35刀。Google野心不死，就是想占领大家的客厅。</p>
<p>老婆喜欢在优酷上看美剧，所以我要用电脑的时候，只有一台Macbook就有点捉襟见肘了。之前我一直在纠结，到底是买一个chromecast，还是chromebook，又或Mac Mini。Mac Mini有点奢侈，chromebook的显示器就是多余，chromecast又担心不支持chrome Unblock Youku的插件，所以一直没下手。这次能先试用一下chromecast，真是一个非常不错的机会。</p>
<p>Chromecast的包装很简单，小小的白色盒子再加上一些蓝色的点缀，非常符合Google一向简约的风格。</p>
<p><img alt="" src="/static/images/2013/08/chromecast/01.jpg" /></p>
<p>背面上的四个图标表示Chromecast支持Chrome浏览器，Youtube，Netflix，Google Play。</p>
<p><img alt="" src="/static/images/2013/08/chromecast/02.jpg" /></p>
<p><img alt="" src="/static/images/2013/08/chromecast/03.jpg" /></p>
<p><img alt="" src="/static/images/2013/08/chromecast/04.jpg" /></p>
<p>Chromecast静静地躺在盒子里</p>
<p><img alt="" src="/static/images/2013/08/chromecast/05.jpg" /></p>
<p><img alt="" src="/static/images/2013/08/chromecast/06.jpg" /></p>
<p><img alt="" src="/static/images/2013/08/chromecast/07.jpg" /></p>
<p>使用Mini USB接口供电，包装里有附带一根USB转Mini USB线</p>
<p><img alt="" src="/static/images/2013/08/chromecast/08.jpg" /></p>
<p><img alt="" src="/static/images/2013/08/chromecast/09.jpg" /></p>
<p>安装好后，首先需要设置一下，安装<a href="https://chrome.google.com/webstore/detail/google-cast/boadgeojelhgndaghljhdicfkmllpafd">Chrome extension</a>或者<a href="https://play.google.com/store/apps/details?id=com.google.android.apps.chromecast.app">Android app</a>来设置，步骤很简单，跟着提示一步一步来即可。</p>
<p>经过一段时间的使用，我发现Android手机上的Youtube的同步播放很流畅，Chrome的Tab casting则有些延迟，而且对电脑的性能和WIFI要求比较高。只要我在电脑上运行大型软件，电视上的视频就会有些卡顿，而且若WIFI信号不好或者本身带宽不足的话，则也会有些卡顿。所以猜想，Android上只是把视频的地址信息同步到Chromecast，然后它自己去下载，播放。而Tab casting则是在电脑上渲染，然后镜像过去的。</p>
<p>Chromecast在Android上同步的话，功能也很弱，比如没法显示字幕，选择视频质量等。我播放了大概30多分钟，手机的电量没有明显的下降，手机也没有发烫，进一步印证了刚才手机不是镜像播放的猜想。</p>
<p>我个人感觉，Chromecast还不太完善，我可能不会考虑它了，不过想想它的售价，貌似也是物有所值，哎，看来还是要继续纠结下去了。</p>]]></content:encoded>
    </item>
    
    <item>
      <title>佳能430ex II闪光灯开箱</title>
      <link>https://blog.chengbo.net/2013/08/20/canon-430ex-ii-unboxing.html</link>
      <guid isPermaLink="true">https://blog.chengbo.net/2013/08/20/canon-430ex-ii-unboxing.html</guid>
      <pubDate>Tue, 20 Aug 2013 23:49:55 +0000</pubDate>
      <description>我又败家了，入了个佳能430ex II。美国物流速度奇快无比，11号下的单，过了9天居然就收到了，欣慰。。。 送过来的包裹 打开 Canon 430ex II和Invoice 打开包装，有闪光灯，说明书，保修卡，底座，袋子 背面 正面 红外线接收？？ 只有扩散板，木有眼神板了 灯头 灯头旋转按钮，按下去了才能转 操作…</description>
      <content:encoded><![CDATA[<p>我又败家了，入了个佳能430ex II。美国物流速度奇快无比，11号下的单，过了9天居然就收到了，欣慰。。。</p>
<p>送过来的包裹</p>
<p><img alt="" src="/static/images/2013/08/430ex_ii_unboxing/01.jpg" /></p>
<p>打开</p>
<p><img alt="" src="/static/images/2013/08/430ex_ii_unboxing/02.jpg" /></p>
<p>Canon 430ex II和Invoice</p>
<p><img alt="" src="/static/images/2013/08/430ex_ii_unboxing/03.jpg" /></p>
<p>打开包装，有闪光灯，说明书，保修卡，底座，袋子</p>
<p><img alt="" src="/static/images/2013/08/430ex_ii_unboxing/04.jpg" /></p>
<p>背面</p>
<p><img alt="" src="/static/images/2013/08/430ex_ii_unboxing/05.jpg" /></p>
<p>正面</p>
<p><img alt="" src="/static/images/2013/08/430ex_ii_unboxing/06.jpg" /></p>
<p>红外线接收？？</p>
<p><img alt="" src="/static/images/2013/08/430ex_ii_unboxing/07.jpg" /></p>
<p>只有扩散板，木有眼神板了</p>
<p><img alt="" src="/static/images/2013/08/430ex_ii_unboxing/08.jpg" /></p>
<p>灯头</p>
<p><img alt="" src="/static/images/2013/08/430ex_ii_unboxing/09.jpg" /></p>
<p>灯头旋转按钮，按下去了才能转</p>
<p><img alt="" src="/static/images/2013/08/430ex_ii_unboxing/10.jpg" /></p>
<p>操作盘，比600ex手感差些，操作也稍显繁琐</p>
<p><img alt="" src="/static/images/2013/08/430ex_ii_unboxing/11.jpg" /></p>
<p>旋转刻度</p>
<p><img alt="" src="/static/images/2013/08/430ex_ii_unboxing/12.jpg" /></p>
<p>闪光灯固定锁，好像一代是旋钮</p>
<p><img alt="" src="/static/images/2013/08/430ex_ii_unboxing/13.jpg" /></p>
<p>和热靴接触的地方是金属，好像一代是塑料的</p>
<p><img alt="" src="/static/images/2013/08/430ex_ii_unboxing/14.jpg" /></p>
<p>电池仓</p>
<p><img alt="" src="/static/images/2013/08/430ex_ii_unboxing/15.jpg" /></p>
<p>电池伺候</p>
<p><img alt="" src="/static/images/2013/08/430ex_ii_unboxing/16.jpg" /></p>
<p>点亮</p>
<p><img alt="" src="/static/images/2013/08/430ex_ii_unboxing/17.jpg" /></p>
<p>小试一张双闪</p>
<p><img alt="" src="/static/images/2013/08/430ex_ii_unboxing/18.jpg" /></p>
<p>最后，和大哥来张合影</p>
<p><img alt="" src="/static/images/2013/08/430ex_ii_unboxing/19.jpg" /></p>]]></content:encoded>
    </item>
    
    <item>
      <title>推荐我所用的Google Chrome扩展</title>
      <link>https://blog.chengbo.net/2013/08/14/my-chrome-extension-recommendation.html</link>
      <guid isPermaLink="true">https://blog.chengbo.net/2013/08/14/my-chrome-extension-recommendation.html</guid>
      <pubDate>Wed, 14 Aug 2013 16:34:20 +0000</pubDate>
      <description>Chrome是一个伟大的浏览器，若再加上适合自己使用的扩展，那更是如虎添翼。这里就介绍一些我正在使用的Chrome Extension： Block Yourself from Analytics 我的blog目前使用Google Analytics来监控网站的访问量，此扩展可以让Google Analytics忽略…</description>
      <content:encoded><![CDATA[<p>Chrome是一个伟大的浏览器，若再加上适合自己使用的扩展，那更是如虎添翼。这里就介绍一些我正在使用的Chrome Extension：</p>
<h3><a href="https://chrome.google.com/webstore/detail/fadgflmigmogfionelcpalhohefbnehm">Block Yourself from Analytics</a></h3>
<p><img alt="" src="https://lh4.googleusercontent.com/jMXXTkx_H46A4trAP-JAueaWApp4J3U6h4EC3pXJuXtCrY0JCBqpPQ7rcnhJ83IuVfn0d7FYdQ=s26-h26-e365-rw" /></p>
<p>我的blog目前使用Google Analytics来监控网站的访问量，此扩展可以让Google Analytics忽略自己的Page View。也支持定义URL规则，只有在规则中的URL才会忽略。</p>
<h3><a href="https://chrome.google.com/webstore/detail/jbmkekhehjedonbhoikhhkmlapalklgn">Change Colors</a></h3>
<p>有些网站的配色实在是废眼神，此扩展可以自定义页面的背景和字体颜色，并且会记住自定义内容，再次访问时会自动应用。</p>
<h3><a href="https://chrome.google.com/webstore/detail/gdbofhhdmcladcmmfjolgndfkpobecpg">Don't track me Google</a></h3>
<p><img alt="" src="https://lh6.googleusercontent.com/17mG-ne4D26pK5JtEMV2B3XX0FgqVZRGe2O0LClnd2-pFwoEVpMKuOk-d2LDYTCNNQ9uNesvq-0=s26-h26-e365-rw" /></p>
<p>Google的搜索结果页面，搜索结果链接会指向Google自身的URL，然后再导向目标页面。Google通过这个中间URL，来对用户的行为做记录分析。此扩展可去掉中间URL，让用户直接跳转到目标页面。其实我并不是怕Google监控我的隐私，只是在天朝，GFW大部分时间墙的是这个中间URL，若搜索了敏感关键字，用户就会挂在这个中间URL中，根本跳转不过去；去掉了中间URL的话，Google使用起来会顺畅的多。</p>
<h3><a href="https://chrome.google.com/webstore/detail/ookhcbgokankfmjafalglpofmolfopek">Google Calendar Checker (by Google)</a></h3>
<p><img alt="" src="https://lh6.googleusercontent.com/0bDjFZ_zTKqGauijFWPZJ2vPZ2pPjl75yPPtfQSwildZaCZml3BXWMt1CGDiK_Vd_9akzrbJ-w=s26-h26-e365-rw" /></p>
<p>此扩展会在Chrome右上角显示Google Calendar中最近的事件。点击它会打开Google Calendar。</p>
<h3><a href="https://chrome.google.com/webstore/detail/hmjkmjkepdijhoojdojkdfohbdgmmhki">Google Keep</a></h3>
<p>云笔记，笔记还支持图片，背景颜色。Android也有<a href="https://play.google.com/store/apps/details?id=com.google.android.keep">客户端</a>可以下载。</p>
<p><img alt="" src="https://lh6.googleusercontent.com/sK9Uzi8dP28TKEG7uTmDayBNP3r7wBsYgcCP5oSNOWCPm8JivUzuhG3IypkjzYS1pHWSnvEcYw=s50-h50-e365-rw" /></p>
<h3><a href="https://chrome.google.com/webstore/detail/mihcahmgecmbnbcchbopgniflfhgnkff">Google Mail Checker</a></h3>
<p>此扩展会在Chrome右上角显示Gmail中未读邮件数。点击它会打开Gmail收件箱页面。</p>
<p><img alt="" src="https://lh4.googleusercontent.com/vyqOFOXPuu0LGDUVmTHp1xhCHHJqkki00yMR_DqC84o7f8lRatpso5V1DpBCJJtGaQ8QzgrzwBU=s26-h26-e365-rw" /></p>
<h3><a href="https://chrome.google.com/webstore/detail/dmglolhoplikcoamfgjgammjbgchgjdd">Google Tasks (by Google)</a></h3>
<p><img alt="" src="https://lh5.googleusercontent.com/h-NHHzvQK5L6SpW3Qm0nsjobyqviWwwa2ciZ4CAWOEBWw1qVCuPgVVeEWQkyfqM8-dbE5O6s=s26-h26-e365-rw" /></p>
<p>简单方便的To Do List。</p>
<h3><a href="https://chrome.google.com/webstore/detail/hbdkkfheckcdppiaiabobmennhijkknn">PageRank Status</a></h3>
<p><img alt="" src="https://lh5.googleusercontent.com/IlmlcP1qs9_DAbME_MnY6bnoxPv0jMfd_puFEFhd1m-CqMY4ObvF4L20565tfkdiCr-WA8GDKQ=s26-h26-e365-rw" /></p>
<p>浏览网站时，我有一个习惯，就是查看它的Page Rank，这样我可以大概判断出此网站的权威性等。此扩展可在Chrome的右上角显示当前Tab页面的Page Rank，点击按钮还可在弹出窗口里查看更多的信息，比如各个搜索引擎的收录情况，Alexa流量排名等。</p>
<h3><a href="https://chrome.google.com/webstore/detail/proxy-switchysharp/dpplabbmogkhghncfbfdeeokoefdjegm">Proxy SwitchySharp</a></h3>
<p><img alt="" src="https://lh3.googleusercontent.com/uVGj5gUDoSHbsKIKoKDdOjR6o4qFM8DOhHKS8CbTgk-5OedO1lywq9PUMgxeW3adSgOX6ETRPfo=s26-h26-e365-rw" /></p>
<p>天朝上网很悲剧，国外“反动”网站动不动就被GFW墙掉。此扩展可以自定义规则，满足A规则的页面用Proxy 1，满足B规则的页面用Proxy 2，其它页面则不用Proxy而是直接访问。这样，既可以用Proxy翻墙，国内网站也不用到Proxy上转一圈再回来了。</p>
<h3><a href="https://chrome.google.com/webstore/detail/pnhechapfaindjhompbnflcldabbghjo">Secure Shell</a></h3>
<p><img alt="" src="https://lh4.googleusercontent.com/0MbVuyBkdOO65A5O51F3SmSLmP6lOjRjFnhn7qgo5yM7rdN2tWwumNldQybzXTk1WMBQhFs8jos=s50-h50-e365-rw" /></p>
<p>此扩展可以在Chrome中直接用SSH访问Linux，在Windows平台上的Chrome比较有用。</p>
<h3><a href="https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo">Tampermonkey</a></h3>
<p><img alt="" src="https://lh3.googleusercontent.com/NmiAEJaHC1ArlVWr01j-nu04BvxH8Ww84aFKqD1NdGqFULKQWhWmKNLRPI_k2LpKbcDtoojyIuc=s26-h26-e365-rw" /></p>
<p>此扩展可以说它是一个扩展的扩展，它可以加载第三方的脚本，来完成不同的功能。比如改变Facebook的背景颜色，天涯只看楼主等等。</p>
<h3><a href="https://chrome.google.com/webstore/detail/unblock-youku/pdnfnkhpgegpcingjbfihlkjeighnddk">Unblock Youku</a></h3>
<p><img alt="" src="https://lh3.googleusercontent.com/nHKvmiIhR6QZyYsmcSltIohs5yjCN3grxmlAJh6eb9azzv5hfTmJvQ-tHToo74076VrHO6qp4yc=s26-h26-e365-rw" /></p>
<p>优酷有些视频（比如很多美剧）只针对中国大陆用户访问，若身在墙外，又想看这些视频的话，装上此扩展再配合Tampermonkey，既突破了这个限制，又可以把优酷恶心的30秒广告屏蔽了。</p>]]></content:encoded>
    </item>
    
    <item>
      <title>Joshua tree国家公园</title>
      <link>https://blog.chengbo.net/2013/08/04/joshua-tree-national-park.html</link>
      <guid isPermaLink="true">https://blog.chengbo.net/2013/08/04/joshua-tree-national-park.html</guid>
      <pubDate>Sun, 04 Aug 2013 21:39:20 +0000</pubDate>
      <description>准备了一个月，终于等到了这次出游。下午3点30从家出发，总共开了130mi，终于到了公园的北入口，大概是5：50的样子，门口收费的人居然下班了，大开着门，没人收钱，我们只好大摇大摆的开进去，开始寻找camping的地点。 View Larger Map 把tent等搞定后，已是太阳落山之时，于是我们抗起相机去拍日落。…</description>
      <content:encoded><![CDATA[<p>准备了一个月，终于等到了这次出游。下午3点30从家出发，总共开了130mi，终于到了公园的北入口，大概是5：50的样子，门口收费的人居然下班了，大开着门，没人收钱，我们只好大摇大摆的开进去，开始寻找camping的地点。</p>
<iframe width="640" height="300" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="//maps.google.com/maps?f=d&amp;source=s_d&amp;saddr=1901+E+Amar+Rd%4034.027847,-117.905662&amp;daddr=North+Entrance+Station%4034.077146,-116.03657399999997&amp;hl=en&amp;geocode=FUc5BwIdAuf4-A%3BFdr5BwIdImwV-Q&amp;aq=&amp;sll=34.077146,-116.036574&amp;sspn=0.010433,0.016437&amp;mra=ls&amp;ie=UTF8&amp;t=m&amp;ll=34.024697,-116.97159&amp;spn=0.222347,1.870048&amp;output=embed"></iframe>
<p><small><a href="https://maps.google.com/maps?f=d&amp;source=embed&amp;saddr=1901+E+Amar+Rd%4034.027847,-117.905662&amp;daddr=North+Entrance+Station%4034.077146,-116.03657399999997&amp;hl=en&amp;geocode=FUc5BwIdAuf4-A%3BFdr5BwIdImwV-Q&amp;aq=&amp;sll=34.077146,-116.036574&amp;sspn=0.010433,0.016437&amp;mra=ls&amp;ie=UTF8&amp;t=m&amp;ll=34.024697,-116.97159&amp;spn=0.222347,1.870048" style="color:#0000FF;text-align:left">View Larger Map</a></small></p>
<p>把tent等搞定后，已是太阳落山之时，于是我们抗起相机去拍日落。沙漠里的日落很好看，只可惜稍微晚了点，太阳已经被山石给挡住了，只能拍一些晚霞，下面的这张照片就是这时拍的。</p>
<p><a href="http://www.flickr.com/photos/chengbo/sets/72157634931929005/with/9440884916/"><img alt="joshua tree national park" src="//farm4.staticflickr.com/3752/9440664624_1c4c0a9502_z.jpg" /></a></p>
<p>太阳完全落山之后，回营地吃东西，不知不觉星星就出来了，公园远离人类居住区，没有光污染，空气也特别的干净，再加上特意选了一个月亮小的周末，所以星星看的特别清楚，还有银河，朋友不说的话，我还以为那只是几片薄云。躺在地上，看着天上满头密密麻麻的星星，还有大片的银河，真是心旷神怡的感觉。只可惜忘了带快门线，无法用B门，所以星星和银河都没有拍下来，相当的郁闷。</p>
<p>星星看够了，睡觉吧，隔壁的老美邻居们素质奇低，闹到凌晨1点，早上7点又开始放音乐，害得我们一晚上都没休息好。</p>
<p>起床，收拾，吃东西。我们又去走trail，这沙漠风格的公园很有特色，太阳毒，天空蓝，石头山上光秃秃，偶尔的几颗植物也是濒临干死的那种状况。我们没走多远，水到是喝了不少。这种地方看看新鲜还是不错，但是应该不会来第二次了，我还是比较喜欢山清水秀的那种。</p>
<p>再去一个山顶远眺，哇塞，视野真好。据介绍的牌子上面说，在山顶可以看到美墨边境。。。这是我用手机在山顶拍的panorama。</p>
<p><a href="http://www.flickr.com/photos/chengbo/sets/72157634931929005/with/9440884916/"><img alt="joshua tree national park" src="//farm6.staticflickr.com/5534/9439391537_4350e4ea6a_z.jpg" /></a></p>
<p>下了山，走南门上10号高速回家，路上还顺路看了一个全是仙人掌的地方，那些仙人掌，居然都有很多被晒死了。。。</p>
<p>回家又开了2个小时，累死哥了。。</p>
<p><br /></p>]]></content:encoded>
    </item>
    
    <item>
      <title>把blog迁移到jekyll</title>
      <link>https://blog.chengbo.net/2013/08/02/good-bye-wordpress-hello-jekyll.html</link>
      <guid isPermaLink="true">https://blog.chengbo.net/2013/08/02/good-bye-wordpress-hello-jekyll.html</guid>
      <pubDate>Fri, 02 Aug 2013 13:38:00 +0000</pubDate>
      <description>自从上次看小舟的blog，说他 抛弃了wordpress ，我就开始心痒痒了。折腾是我的一大爱好，我用的blog平台，从最开始blogcn，到自建movable type，再到wordpress，现在又到jekyll了。 和wordpress不同的是，jekyll是一个使用ruby开发的静态文件生成程序，理论上它可以…</description>
      <content:encoded><![CDATA[<p><a href="http://jekyllrb.com/"><img alt="jekyll" src="//jekyllrb.com/img/logo-2x.png" /></a></p>
<p>自从上次看小舟的blog，说他<a href="http://xiaozhou.net/bye-wordpress-2013-07-22.html">抛弃了wordpress</a>，我就开始心痒痒了。折腾是我的一大爱好，我用的blog平台，从最开始blogcn，到自建movable type，再到wordpress，现在又到jekyll了。</p>
<p>和wordpress不同的是，jekyll是一个使用ruby开发的静态文件生成程序，理论上它可以用来生成任何类型的网站，更别说blog了。每次内容有更新时，我们就用jekyll按照自定义的格式重新生成一次静态的html，然后再把这些html文件部署到host上，访客就可以看到最新的内容了。</p>
<p>相比于wordpress，jekyll的优势</p>
<ul>
<li>不用数据库，内容是基于文件的</li>
<li>页面是预先生成好的静态html，无需动态渲染，因此加载速度快</li>
<li>对host要求不高，只需能发布html即可</li>
<li>备份方便，因为只是一堆的文件，想怎么备份就怎么备份，打包zip，存git等，悉听尊便</li>
</ul>
<p>劣势</p>
<ul>
<li>折腾，不适合大众</li>
<li>页面内容的展现形式，灵活度大大降低</li>
<li>默认主题略显简陋，也没有什么可以拿来就可以用的主题，更别要说美观了</li>
<li>发布麻烦，不像wordpress，在后台写完了保存就可以了</li>
</ul>
<p>本来打算直接host在<a href="http://pages.github.com/">github pages</a>上的，结果github的jekyll版本是1.0.3，这个版本在分页上有个<a href="https://github.com/mojombo/jekyll/issues/1348">重大bug</a>，而且<a href="https://help.github.com/articles/pages-don-t-build-unable-to-run-jekyll#unsafe-plugins">不支持plugins</a>，所以只能部署在自己的vps上了。</p>
<p>花了几天的时间，折腾了不少内容：把文章和图片从wordpress导过来，维持post之前的permalink不变，分页，tag，代码高亮显示等。接下来还有不少可以折腾的空间，比如弄一个git hooks，内容有变化就自动build、发布，写一个responsive的主题，tag cloud，SEO等。很多很多，就怕想不到，这下有意思了。</p>
<p>昨晚，我把域名指向了这个blog，而这，就是我用markdown写的第一篇blog。</p>
<p>再见wordpress，你好jekyll。</p>
<p>最后说一下，这个blog备份在<a href="https://github.com/chengbo/chengbo.github.io">github</a>上。</p>]]></content:encoded>
    </item>
    
    <item>
      <title>多线程写代码的时候要注意安全</title>
      <link>https://blog.chengbo.net/2013/07/27/becareful-when-doing-multithreading-programming.html</link>
      <guid isPermaLink="true">https://blog.chengbo.net/2013/07/27/becareful-when-doing-multithreading-programming.html</guid>
      <pubDate>Sat, 27 Jul 2013 16:00:00 +0000</pubDate>
      <description>今天在做项目时候，发现获取当前登录user信息的rest service，偶尔会报错 An item with the same key has already been added. 只是偶尔报错，大部分时间是正常的，很奇怪。查了半天才查出原因，记录下来： 打开service代码，如下 public static…</description>
      <content:encoded><![CDATA[<p>今天在做项目时候，发现获取当前登录user信息的rest service，偶尔会报错</p>
<pre><code>An item with the same key has already been added.
</code></pre>
<p>只是偶尔报错，大部分时间是正常的，很奇怪。查了半天才查出原因，记录下来：</p>
<p>打开service代码，如下</p>
<pre><code class="language-csharp">public static class UserInfoProcess
{
  private static DataAccessDataContext db = new DataAccessDataContext();

  public static EmployeeInfo GetEmployeeInfoById(string employeeId)
  {
    return db.EmployeeInfos.SingleOrDefault(c =&gt; c.EmployeeId == employeeId);
  }
}
</code></pre>
<p>注意，这里的<code>DataContext</code>是static的，这里有个问题等会儿说。</p>
<p>查一下MSDN：</p>
<p><a href="http://msdn.microsoft.com/en-us/library/system.data.linq.datacontext.aspx">http://msdn.microsoft.com/en-us/library/system.data.linq.datacontext.aspx</a></p>
<p>Thread Safety</p>
<hr />
<p>Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.</p>
<p>MSDN说，<code>DataContext</code>只保证它static member的线程安全，而instance member则不保证。</p>
<p>那么什么叫线程安全呢，我觉得简单的说，就是多个线程同时访问一个object或者method的时候，内部的值要处理正确。</p>
<p>上面的service代码，调用了<code>DataContext</code>的<code>EmployeeInfos</code>属性，这个属性是instance member，所以它的线程安全得不到保证。</p>
<p>线程不安全，是怎么体现的呢？我用reflector里反编译了<code>EmployeeInfos</code>属性，下面摘一点重要的出来</p>
<pre><code class="language-csharp">private ITable GetTable(MetaTable metaTable)
{
  ITable table;
  if (!this.tables.TryGetValue(metaTable, out table))
  {
    ValidateTable(metaTable);
    table = (ITable) Activator.CreateInstance(typeof(Table&lt;&gt;).MakeGenericType(new Type[] { metaTable.RowType.Type }), BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, new object[] { this, metaTable }, null);
    this.tables.Add(metaTable, table);
  }
  return table;
}
</code></pre>
<p>这个方法中，先看看tables这个dictionary里有没有对应的key，没有就反射create一个，再把它加到dictionary里。</p>
<p>如果只有一个线程，那么这里永远不会有问题，但是，rest service是一个多线程的环境。每一个request进来，都是一个线程，他们共享的是同一个<code>DataContext</code>（因为上面的service代码中，<code>DataContext</code>定义成static了），两个线程有一定的几率同时add一个key（这里没有lock，有lock，就可以线程安全了），导致开头说的那个错误。</p>
<p>所以，解决方法找到了：</p>
<ol>
<li>
<p>把这个代码加上lock的机制，但是由于这是.Net Framework的代码，我们改不了，所以只能</p>
</li>
<li>
<p>这里<code>DataContext</code>不定义成static，换成instance的，每个线程访问自己独有的<code>DataContext</code></p>
</li>
</ol>
<p>PS：说句题外话，换成instance后，每个请求都要反射，可见Linq to sql性能不怎么样</p>]]></content:encoded>
    </item>
    
    <item>
      <title>一个轻量级的Android App: Tip Calculator</title>
      <link>https://blog.chengbo.net/2013/06/10/a-lightweight-android-app-tip-calculator.html</link>
      <guid isPermaLink="true">https://blog.chengbo.net/2013/06/10/a-lightweight-android-app-tip-calculator.html</guid>
      <pubDate>Mon, 10 Jun 2013 22:55:30 +0000</pubDate>
      <description>在外面吃饭，经常为了算小费而头痛，昨天突然想到，应该有这种帮助算小费的App，上Google Play找了一圈，却没有看着顺眼的。 于是着手自己写一个，花了一晚上的时间做了一个非常简单的App，几个月没碰Android，忘了不少东西，不过好歹是弄出来了，发布在 Google Play 上。 基于自己是一个毫无美术功底…</description>
      <content:encoded><![CDATA[<p>在外面吃饭，经常为了算小费而头痛，昨天突然想到，应该有这种帮助算小费的App，上Google Play找了一圈，却没有看着顺眼的。</p>
<p>于是着手自己写一个，花了一晚上的时间做了一个非常简单的App，几个月没碰Android，忘了不少东西，不过好歹是弄出来了，发布在<a href="https://play.google.com/store/apps/details?id=net.chengbo.tipcalculator">Google Play</a>上。</p>
<p>基于自己是一个毫无美术功底的程序猿，所以界面有点简陋：）自己大概测了下，应该还有一些bug。</p>
<p><img alt="" src="https://lh6.ggpht.com/ECF87JJvK5kW-hdE7Ow1PntXnK4ETriN_ndhSCI4tPeRHxROdU2CCX8WlrlEh1SC49Y" /></p>
<ul>
<li>算小费可以基于税前和税后的金额</li>
<li>可自定义税率</li>
<li>可以把金额分到不同的人头上（方便AA）</li>
<li>安全，不需求任何特殊的权限</li>
<li>完全免费，不含广告</li>
<li>异常轻量，仅仅40k</li>
</ul>
<p>同时，这个App是开源的，代码放在<a href="https://github.com/chengbo/tip-calculator">Github</a>上。</p>
<p>如果你对这个App有任何意见或者建议，欢迎告诉我。</p>]]></content:encoded>
    </item>
    
    <item>
      <title>Android Studio：为Android定制的IDE</title>
      <link>https://blog.chengbo.net/2013/05/17/android-studio-ide-built-for-android.html</link>
      <guid isPermaLink="true">https://blog.chengbo.net/2013/05/17/android-studio-ide-built-for-android.html</guid>
      <pubDate>Fri, 17 May 2013 23:35:36 +0000</pubDate>
      <description>原文： http://android-developers.blogspot.com/2013/05/android-studio-ide-built-for-android.html 由 Xavier Ducrohet , Tor Norbye, Katherine Chou发表 今天在Google I/O上，我们…</description>
      <content:encoded><![CDATA[<p>原文：<a href="http://android-developers.blogspot.com/2013/05/android-studio-ide-built-for-android.html">http://android-developers.blogspot.com/2013/05/android-studio-ide-built-for-android.html</a></p>
<p><em>由 <a href="https://plus.google.com/109385828142935151413">Xavier Ducrohet</a>, Tor Norbye, Katherine Chou发表</em></p>
<p><img alt="" src="/static/images/2013/05/google-io-lockup-2.png" /></p>
<p><img alt="" src="/static/images/2013/05/Studio_table.png" /></p>
<p>今天在Google I/O上，我们发布了一个专为Android开发者准备的新IDE：Android Studio，它可以免费使用，你现在就可以试试它的早期预览版。</p>
<p>我们与最流行的Java IDE之一，<a href="http://www.jetbrains.com/idea/">IntelliJ IDEA 社区版</a>，的开发公司<a href="http://www.jetbrains.com">JetBrains</a>合作，开发了Android Studio。在强大的IntelliJ IDEA 社区版的基础上，我们添加了一系列针对Android开发的功能，可以提高你的工作效率。</p>
<h3>可扩展的构建工具</h3>
<p>我们知道你需要一个适合项目的构建系统，Android Studio的新构建系统基于<a href="http://www.gradle.org/">Gradle</a>，它不仅提供了灵活、定制化的构建方式，还有依赖管理等更多的特性。</p>
<p>这个新的构建系统不仅可以让你在IDE中构建项目，它同样也支持持续集成服务器。在整个工作流程中，N多杂七杂八的工具旁，你可以更方便的管理你复杂的构建配置项。如想了解更多，请查看<a href="http://tools.android.com/tech-docs/new-build-system/user-guide">预览版文档</a>。</p>
<p><img alt="" src="/static/images/2013/05/laptop600.png" /></p>
<h3>强大的代码编辑</h3>
<p>Android Studio包括一个强大的代码编辑器，这个编辑器基于IntelliJ IDEA，提供了诸如智能提示，高级代码重构，深度静态代码分析等功能。</p>
<p>智能提示中的查找内嵌资源，可以让你在编辑后台资源的时候，更快速的阅读资源对应的代码。高级<a href="http://www.jetbrains.com/idea/features/refactoring.html">代码重构</a>可以让你快速的，放心的优化整个项目中代码。</p>
<p>静态代码分析可以让你更快的定位bug。在由IntelliJ IDEA提供的成千上万inspection的基础上，我们又加了一些定制化的inspection。比如，我们为Android API添加了一些元数据，这些元数据指示哪些方法可以返回null，而哪些方法又不可以；某个方法接受哪些常量值，等等。Android Studio就可以通过它们来分析你的代码，找出潜在的错误。</p>
<p><img alt="" src="/static/images/2013/05/ide-refactor.png" /></p>
<p><img alt="" src="/static/images/2013/05/ide-smart.png" /></p>
<p><img alt="" src="/static/images/2013/05/ide-resourcelookup2.png" /></p>
<h3>更平滑、更丰富的图形界面</h3>
<p>过去几年，我们为ADT添加了一些拖放控件的UI功能，现在我们正在努力为Android Studio移植它们。这个Android Studio版本，你可以在IDE中预览你的布局文件在不同尺寸，语言和版本的设备中的显示效果。下面会展示XML编辑页面中预览不同的配置。</p>
<h3>方便的使用Google services</h3>
<p>我们想让你更方便的在IDE中使用Google Service的强大功能。首先，我们可以让你直接在IDE中将诸如<a href="http://developer.android.com/google/gcm/index.html">Google Cloud Messaging</a>（GCM）的Google Service集成到App中。</p>
<p>我们还添加了一个名为<a href="http://developer.android.com/sdk/installing/installing-adt.html#tmgr">ADT Translation Manager Plugin</a>的插件来帮助你本地化你的App。通过这个插件，你可以把字符串导出到Google Play Developer Console中翻译，然后下载并导入这些翻译好的字符串回项目中。</p>
<h3>开源</h3>
<p>下周开始我们的所有开发工作就会开源，到时候你就可以下载之，然后向我们提交你的代码。Android Studio的代码放在<a href="https://android.googlesource.com/platform/tools/adt/idea/">AOSP</a>中。</p>
<h3>试用Android Studio并给我们反馈</h3>
<p><a href="http://developer.android.com/sdk/installing/studio.html">开始试用Android Studio</a> 并给我们反馈吧！它是免费的，并且下载包中包括你所需要的一切：IDE，最新的SDK以及最新的Android平台等。</p>
<p>注意：这只是一个早期预览版，只适合喜欢尝鲜，或想决定Android工具未来发展方向的人。如果你的App有大量用户使用的话，现在还不是时候迁移到新工具上。我们还将继续支持Eclipse作为首要的开发平台。</p>
<p>如果你有任何意见或建议，请通过<a href="https://code.google.com/p/android/issues/entry?template=Android%20Studio%20bug&amp;comment=Build:%20AI-130.675642,%2020130514">Android Studio issue tracker</a>告诉我们。</p>
<p><a href="https://plus.google.com/108967384991768947849/posts/Sr8LNyHDuax">Join the discussion on</a></p>
<p><a href="https://plus.google.com/108967384991768947849/posts/Sr8LNyHDuax/">+Android Developers</a></p>
<p><a href="https://plus.google.com/108967384991768947849/posts/Sr8LNyHDuax"><img alt="" src="https://ssl.gstatic.com/images/icons/gplus-32.png" /></a></p>
<p>本文由Roy最初发表于：<a href="http://blog.chengbo.net/2013/05/17/android-studio-ide-built-for-android.html">http://blog.chengbo.net/2013/05/17/android-studio-ide-built-for-android.html</a>，你可以在保持文章完整和保留本声明的情况下转帖、分发和印刷等。</p>]]></content:encoded>
    </item>
    
    <item>
      <title>使用Gitolite来对Git的repository实现权限控制</title>
      <link>https://blog.chengbo.net/2012/04/20/use-gitolite-to-manage-git-repositories.html</link>
      <guid isPermaLink="true">https://blog.chengbo.net/2012/04/20/use-gitolite-to-manage-git-repositories.html</guid>
      <pubDate>Fri, 20 Apr 2012 06:15:59 +0000</pubDate>
      <description>我们项目组打算从svn向git迁移，前几天我搭建了git环境，把代码从svn转移过来，然后所有成员都通过server上的git账号来做pull和push，一切都安置妥当，没有问题。但是后来其它项目组也打算使用这个git server，那么问题来了，之前那种授权的方式肯定是不够的，因为只要能连上server，那么他对这…</description>
      <content:encoded><![CDATA[<p>我们项目组打算从svn向git迁移，前几天我搭建了git环境，把代码从svn转移过来，然后所有成员都通过server上的git账号来做pull和push，一切都安置妥当，没有问题。但是后来其它项目组也打算使用这个git server，那么问题来了，之前那种授权的方式肯定是不够的，因为只要能连上server，那么他对这个server上所有的repository都有完全的读写权限，这显然是不可接受的。</p>
<p>所以打算使用Gitolite这个组件来做权限控制，搜索了下，找到的文章貌似都是老版本的，所以有了写这篇文章的想法。</p>
<p>Gitolite其实也是一个git repository，首先在server上安装好后，在client上把server上的repository clone下来，在本地做一些更改，再push回server，server端的hooks会根据push上来的配置来更新权限。</p>
<p>接下来，介绍下安装和配置步骤</p>
<h3>准备工作</h3>
<p>如果你之前是用git账号来做权限控制的话，记得把<code>/etc/passwd</code>里git用户的shell换回<code>/bin/bash</code>，然后把<code>~git/.ssh/authorized_key</code>里不再需要的key移除。</p>
<p>用<code>ssh-kengen</code>生成一对key，比如your-name和your-name.pub（下文均以此为例）</p>
<p>拷贝私钥到本用户的.ssh文件夹中</p>
<pre><code>mv your-name ~/.ssh/
</code></pre>
<p>拷贝公钥到git server上</p>
<pre><code>scp you-name.pub git@your.server.name.or.ip.address:~
</code></pre>
<p>为了以后方便，这里可以做一个server别名，指定连接所需的用户名，server的地址、端口以及私钥</p>
<pre><code>vim ~/.ssh/config
</code></pre>
<p>输入以下内容</p>
<pre><code>host githost
user your-name
hostname your.server.name.or.ip.address
port 22
identityfile ~/.ssh/your-name
</code></pre>
<h3>安装Gitolite</h3>
<p>登录git server</p>
<pre><code>ssh git@your.server.name.or.ip.address
</code></pre>
<p>下载最新的Gitolite</p>
<pre><code>git clone git://github.com/sitaramc/gitolite
</code></pre>
<p>安装，这里说明下，安装方式有3种，区别在与指定生成<code>gitolite</code>可执行文件的路径，这里采用Gitolite作者推荐的第二种，也就是把文件生成到<code>$HOME/bin</code>中，这样可以在接下来的bash中直接执行<code>gitolite</code>命令而不用指定路径(如果你的<code>~/bin</code>目录不存在记得先<code>mkdir ~/bin</code>)</p>
<pre><code>gitolite/install -ln
</code></pre>
<p>设置，由于是第一次运行这个命令，所以这里指定的key是拥有Gitolite管理员权限的</p>
<pre><code>gitolite setup -pk your-name.pub
</code></pre>
<p>此命令会在你的<code>~/repositories/</code>目录生成两个repository：gitolite-admin.git和testing.git</p>
<h3>配置权限</h3>
<p>退到你的workstation上</p>
<pre><code>exit
</code></pre>
<p>clone刚才生成的gitolite-admin.git</p>
<pre><code>git clone githost:gitolite-admin
</code></pre>
<p>注意这里用的是刚才准备好的server别名来连接的，其中最重要的区别是使用your-name.pub这个key，并且没有采用绝对路径来指定想要clone的repository，而是直接使用名称，并且这个名称也没有包括.git这个后缀。这一点很重要，因为这是用Gitolite的机制来clone，如果你跳过它直接使用git来，那么它的一些功能就无法实现了。以后clone, push其它需要受Gitolite权限控制的repository都必须这样做。</p>
<p>clone完后会有个新的目录<code>gitolite-admin</code>，里面有两个文件夹<code>conf</code>和<code>keydir</code>，第一个目录中包含的是配置文件，里面就是记录权限配置的地方，第二个目录中则包含所有用户的pub key。</p>
<p>现在我们打开配置文件，按照我们的权限配置需要进行设置</p>
<pre><code>vim gitolite-admin/conf/gitolite.conf
</code></pre>
<p>我期望的配置如下，你也可以根据你的需要做更改</p>
<pre><code>@repos_a @proj1 @proj2
@repos_b @proj3 @proj4 @proj5

@team_a @user1 @user2
@team_b @user3 @user4

repo gitolite-admin
RW+ = your-name

repo @repos_a
RW+ = @team_a
R = @all

repo @repos_b
RW+ = @team_b
</code></pre>
<p>这个配置很简单，首先定义了两个repository group，再又定义了两个user group，group的好处就是以后添加repository和user的时候，不需要再单独配置，只需加入到对应的group中即可。</p>
<ul>
<li>添加全新的repository，在上面提到的gitolite.conf文件中配置好对应的名称和权限，再push到server即可，server会自动帮你创建一个empty的bare repository。</li>
<li>如果你已经有一个repository，想把它加进来的话，那就把它拷贝到git server上的<code>~/repositories</code>文件夹里，记得文件夹名要以.git结尾，并且这个repository一定要是bare的，（你可以通过拷贝repository里的.git文件夹，然后运行<code>git config --bool core.bare true</code>，也可以运行<code>git clone --bare your-repository</code>来得到bare repository）。这种方式还有一个额外的操作就是在server上运行一次<code>gitolite setup</code>。</li>
<li>移除repository，在配置文件中移除对应的repo，然后push，接着再删除server上对应的文件夹即可。</li>
<li>添加user，把pub key拷贝到<code>keydir</code>文件夹里</li>
<li>删除user，一样，移除<code>keydir</code>里对应的pub key</li>
</ul>
<p>注意，上面说的操作，都必须在clone的gitolite-admin里做更改，然后push，千万别在server上自己来，那样是没用的，因为这些权限配置、repository管理都有一些额外的操作，gitolite-admin会帮你搞定一切。</p>
<p>把你的更改push回server上，试试clone，pull，push，看看权限是否正确。比如</p>
<pre><code>git clone githost:proj3
</code></pre>
<p>更多的内容，可以参考<a href="http://sitaramc.github.com/gitolite/master-toc.html">官方文档</a></p>
<p>本文由Roy最初发表于：<a href="http://blog.chengbo.net/2012/04/20/use-gitolite-to-manage-git-repositories.html">http://blog.chengbo.net/2012/04/20/use-gitolite-to-manage-git-repositories.html</a>，你可以在保持文章完整和保留本声明的情况下转帖、分发和印刷等。</p>]]></content:encoded>
    </item>
    
    <item>
      <title>用Debian当路由，来解决BT造成的网络慢的问题</title>
      <link>https://blog.chengbo.net/2012/04/18/use-debian-server-as-a-router.html</link>
      <guid isPermaLink="true">https://blog.chengbo.net/2012/04/18/use-debian-server-as-a-router.html</guid>
      <pubDate>Wed, 18 Apr 2012 05:30:29 +0000</pubDate>
      <description>自从 @TimothyYe 童鞋介绍偶加入HDC后，为了快点完成新人作业，也为了满足我不折腾不舒服斯基的欲望，哥配了一台凌动小PC，Intel ATOM D525NW的主板，集成了CPU和显卡，加上小机箱总共700元。到手后，插上我Thinkpad拆下来的2根1G内存和另外一台闲置N久的台式机160G SATA硬盘，…</description>
      <content:encoded><![CDATA[<p>自从<a href="http://www.weibo.com/timothyye">@TimothyYe</a> 童鞋介绍偶加入HDC后，为了快点完成新人作业，也为了满足我不折腾不舒服斯基的欲望，哥配了一台凌动小PC，Intel ATOM D525NW的主板，集成了CPU和显卡，加上小机箱总共700元。到手后，插上我Thinkpad拆下来的2根1G内存和另外一台闲置N久的台式机160G SATA硬盘，装了个Debian，就可以用了。</p>
<p>装上transmission后，全速挂BT无压力，比那些直接路由或者1、200的NAS给力多了。哥还继续在上面折腾了Git，emule，动态DNS等，远远没有把2G内存榨干，当然这里都说远了，继续回来。</p>
<p>我家使用的是电信ADSL，一个宽带无线路由，手机，notebook，iPad，PC，xbox等（哥真败家。。。），路由拨号连入Internet，然后通过WIFI把其它设备连入LAN，共享外网连接。这个配置在我挂PT之前一直工作正常，可是当我把BT开着，就算上传和下载速度都为0，LAN中的其它设备访问Internet的速度一样很慢，很慢。</p>
<p>分析了下，估计是我那100元的低端无线路由无法支撑如此多的连接会话造成的，简单直接的办法就是升级路由，于是开始上网查高端路由，不查不知道，一查才知道这东西好贵，便宜的怕是不能解决问题，贵的哥又承受不了。纠结了N久，最后发现，何不把我那台Debian来做路由呢？</p>
<p>马上在淘宝买了根20元的USB有线网卡，收到后插入Debian上，这东西不像Windows和MAC可以自动识别出来然后提示你安装驱动，要自己去折腾，而且附送的光盘上也没有Linux的驱动，看来，要找Google了。</p>
<h3>安装配置USB网卡</h3>
<p>在Debian上运行</p>
<pre><code>$ lsusb
</code></pre>
<p>Bus 005 Device 002: ID 0fe6:9700 Kontron (Industrial Computer Source / ICS Advent) DM9601 Fast Ethernet Adapter</p>
<p>从上得知，USB网卡是DM9601这个型号的</p>
<pre><code>$ /sbin/ifconfig
</code></pre>
<p>只有lo和eth0，新加的网卡没有识别</p>
<p>以DM9601为关键字，Google，找到了<a href="http://www.davicom.com.tw/page1.aspx?no=209814">这里</a>，下载解压好linux的驱动后，编译出错，好像是头文件不对，哥不会写驱动啊，只有继续Google，发现DM9601的驱动已经集成在新版的内核里了，但是我试了下，用不了，不知道什么原因。继续Google，又找到了<a href="http://ceyes.blog.51cto.com/2377614/808386">这里</a>，根据上面的说明，下载了qf9700的驱动，编译，成功，生成文件qf9700.ko。</p>
<p>安装刚才编译好的驱动</p>
<pre><code># cp qf9700.ko /lib/modules/`uname -r`/kernel/drivers/net/usb
# cd /lib/modules/`uname -r`/kernel/drivers/net/usb
# modprobe usbnet
# insmod qf9700.ko
# ifconfig eth1 up
</code></pre>
<p>配置好驱动后再运行</p>
<pre><code>$ /sbin/ifconfig
</code></pre>
<p>多了一个eth1了，到现在新网卡已经可以使用了。</p>
<h3>安装配置ADSL拨号相关软件</h3>
<p>把原先连接无线宽带路由和猫的网线拔掉，接在猫和Debian的USB网卡上
安装拨号软件</p>
<pre><code># apt-get install pppoe pppoeconf
</code></pre>
<p>成功后运行</p>
<pre><code># pppoeconf
</code></pre>
<p>会弹出一个窗口，自动检测连接ADSL的网卡，然后照提示输入你的用户名，密码，其它的可以用默认值。</p>
<p>运行</p>
<pre><code># pon dsl-provider
</code></pre>
<p>就可以拨号了，过后再<code>ifconfig</code>一下，会发现多了个ppp0。<code>poff</code>命令可以关闭ppp0连接。另外，我发现多次拨号可以有多个ppp，比如ppp1，而且IP还不一样，不知道这样是否可以让带宽double，待测试。</p>
<p>此时Debian可以上网了，但是LAN中的其它设备还不行。</p>
<h3>设置LAN路由</h3>
<p>设置Debian连接LAN的网卡配置</p>
<pre><code># vim /etc/network/interfaces
</code></pre>
<blockquote>
<p>allow-hotplug eth0
iface eth0 inet static
address 192.168.3.3
netmask 255.255.255.0
network 192.168.3.0
broadcast 192.168.3.255
gateway 192.168.3.3</p>
</blockquote>
<p>由于所有的无线设备都是有无线宽带路由来DHCP的，所以登录无线宽带路由，把配置改下：</p>
<blockquote>
<p>range 192.168.3.100-192.168.3.200
netmask 255.255.255.0
gateway 192.168.3.3
dns 8.8.8.8 or 4.4.4.4</p>
</blockquote>
<p>DNS没有用电信分配给我的，是因为不想看电信强行插入的广告</p>
<p>设置NAT</p>
<pre><code># echo "1" &gt; /proc/sys/net/ipv4/ip_forward
# /sbin/iptables -t nat -A POSTROUTING -o ppp0 -s 192.168.3.0/24 -j MASQUERADE
</code></pre>
<p>至此LAN中的其它设备也可以上网了，如果还不行的话，检查下你的配置是否正确，然后再看看路由表，把错误的路由改掉。</p>
<p>最后，我家网络的结构如下图</p>
<p><a href="/static/images/2012/04/home-network.png"><img alt="home network" src="/static/images/2012/04/home-network.png" /></a></p>
<p>// TODO: 此文还需添加Debian重启后自动配置USB网卡，拨号，NAT的内容</p>
<p>本文由Roy最初发表于：<a href="http://blog.chengbo.net/2012/04/18/use-debian-server-as-a-router.html">http://blog.chengbo.net/2012/04/18/use-debian-server-as-a-router.html</a>，你可以在保持文章完整和保留本声明的情况下转帖、分发和印刷等。</p>]]></content:encoded>
    </item>
    
    <item>
      <title>更快的，更好的支持硬件的模拟器</title>
      <link>https://blog.chengbo.net/2012/04/10/faster-emulator-with-better-hardware.html</link>
      <guid isPermaLink="true">https://blog.chengbo.net/2012/04/10/faster-emulator-with-better-hardware.html</guid>
      <pubDate>Tue, 10 Apr 2012 15:18:02 +0000</pubDate>
      <description>原文： http://android-developers.blogspot.com/2012/04/faster-emulator-with-better-hardware.html [This post is by Xavier Ducrohet and Reto Meier of the Android eng…</description>
      <content:encoded><![CDATA[<p>原文：<a href="http://android-developers.blogspot.com/2012/04/faster-emulator-with-better-hardware.html">http://android-developers.blogspot.com/2012/04/faster-emulator-with-better-hardware.html</a></p>
<p><em>[This post is by Xavier Ducrohet and Reto Meier of the Android engineering team. — Tim Bray.]</em></p>
<p>Android模拟器是开发和测试Android程序的一个关键工具。目前Android设备的功能以及多样性发展的日益迅猛，模拟器要跟上步伐十分的困难。</p>
<p>今天我们激动的宣布，模拟器做了一些十分显著的改进，包括激动人心的性能提升，众多硬件特性，尤其是传感器和多点触控的支持。</p>
<h3>加入GPU支持</h3>
<p>今天我们发布的系统镜像内置了GPU支持（Android 4.0.3 r2）。Android日益依赖GPU来提高性能，所以新模拟器的差异十分显著。在下面的视频中（需翻墙才能看）模拟器依旧翻译着ARM指令（运行模拟器的宿主系统一般是x86平台，此镜像是ARM平台的，所以中间存在着ARM-&gt;x86指令的转换。之前没有GPU支持，运行如此高分辨率的模拟器并不流畅）；GPU可以让性能提升不少。</p>
<p>一个额外的红利，我们现在已经支持OpenGL ES 2.0了，所以你的OpenGL游戏可以在模拟器中运行了。</p>
<p>请注意的是，目前有很多种的GPU，我们并没有用所有GPU对这个beta版的模拟器做测试，所以，如果你有什么意见或者遇到了什么问题，请<a href="http://code.google.com/p/android/issues/entry?template=Tools%20GPU%20bug%20report">联系我们</a>。</p>
<h3>模拟更多的硬件特性</h3>
<p>移动设备的硬件特性是一个开发平台的重要组成部分，所以我们也高兴的宣布，除了去年加入的摄像头支持，现在还可以使用一个绑定的Android设备来支持传感器和多点触控了。</p>
<p>我们还在为模拟器支持更多的硬件特性，包括蓝牙和NFC（近距离无线通信），而努力。</p>
<h3>优化的CPU性能</h3>
<p>我们同样也优化了Android模拟器的CPU性能。硬件浮点运算操作在冰淇淋三明治版本(Android 4.0)之上的版本中有效，它让模拟CPU操作大概快了2倍。</p>
<p>上一周，我们发布了包括x86系统镜像和主机驱动程序的Android开发工具r17版本，可以让模拟器使用x86指令执行，大大提高了执行效率。</p>
<p>下面这个视频显示了两个CPU相关的程序，一个有虚化（virtualization），一个没有，在两个运行着相同系统镜像的模拟器上运行的情况。（同样需要翻墙）</p>
<h3>构建一个现代化的模拟器</h3>
<p>因为Android平台允许应用程序和系统组件之间的深层相互操作，所以我们必须提供一个有着完整系统镜像的模拟器。我们的模拟器虚拟了一个完整的设备：硬件，内核，底层系统库和应用框架。</p>
<p>当然，系统一般被虚拟为ARM CPU的设备；之前，我们用软件来虚拟这些指令，它一直工作的不错，直到包括更多动画和更加复杂的Android 3.0的到来。</p>
<p>我们缺少的是Android x86的支持，和上周r17版本的SDK工具中的GPU支持。把模拟器的OpenGL ES 2.0指令传给宿主操作系统，转换成标准的OpenGL 2.0，然后用宿主GPU来执行，这样模拟器就支持GPU了。</p>
<h3>总结</h3>
<p>Android生态系统有着很多的来自不同厂商的设备。开发人员需要一个不用买设备就可以测试程序的途径。同时一个快速的，更真实的模拟器有着极大的帮助。</p>
<p>我们希望这些新的优化能够让模拟器在你的开发和测试过程中更加有用，同时期盼能进一步的为你优化它。</p>
<p>本文由Roy最初发表于：<a href="http://blog.chengbo.net/2012/04/10/faster-emulator-with-better-hardware.html">http://blog.chengbo.net/2012/04/10/faster-emulator-with-better-hardware.html</a>，你可以在保持文章完整和保留本声明的情况下转帖、分发和印刷等。</p>]]></content:encoded>
    </item>
    
    <item>
      <title>当ListView有Header时，onItemClick里的position不正确</title>
      <link>https://blog.chengbo.net/2012/03/09/onitemclick-return-wrong-position-when-listview-has-headerview.html</link>
      <guid isPermaLink="true">https://blog.chengbo.net/2012/03/09/onitemclick-return-wrong-position-when-listview-has-headerview.html</guid>
      <pubDate>Fri, 09 Mar 2012 07:15:49 +0000</pubDate>
      <description>今天在做项目的时候，遇到一个问题，记录下来。 当给 ListView 加了一个HeaderView后（代码如下），我们发现， onItemClick 方法里的 position 参数的值不是我们所期望的，比如点击ListView的第一行，我们期望的 position 是0，可是实际上却是1，也就是说，它是从Heade…</description>
      <content:encoded><![CDATA[<p>今天在做项目的时候，遇到一个问题，记录下来。</p>
<p>当给<a href="http://developer.android.com/reference/android/widget/ListView.html" title="ListView">ListView</a>加了一个HeaderView后（代码如下），我们发现，<a href="http://developer.android.com/reference/android/widget/AdapterView.OnItemClickListener.html#onItemClick(android.widget.AdapterView&lt;?&gt;,%20android.view.View,%20int,%20long)" title="onItemClick">onItemClick</a>方法里的<code>position</code>参数的值不是我们所期望的，比如点击ListView的第一行，我们期望的<code>position</code>是0，可是实际上却是1，也就是说，它是从Header而不是从第一行开始计数的。</p>
<pre><code class="language-java">@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.home);

    mAdapter = new MyAdapter(this);

    mListView = (ListView) findViewById(R.id.list);
    mListView.addHeaderView(getLayoutInflater().inflate(R.layout.list_header));
    mListView.setAdapter(mAdapter);
    mListView.setOnClickListener(this);
}

@Override
public void onItemClick(AdapterView&lt;?&gt; parent, View v, int position, long id) {
    doSomething(mAdapter.getItem(position));
}
</code></pre>
<p>Google了下，发现有个老外issue过一个<a href="http://code.google.com/p/android/issues/detail?id=4197">bug</a>，和我遇到的问题一样，不过这个bug被RomainGuy reject掉了，理由是，你用错了，请用<a href="http://developer.android.com/reference/android/widget/ListView.html#getAdapter()" title="getAdapter">getAdapter</a>。这回答的太简洁了，完全没法理解，所以只好又去仔细研究ListView的代码，终于领会他的意思了。把其中<a href="http://developer.android.com/reference/android/widget/ListView.html#addHeaderView(android.view.View)" title="addHeaderView">addHeaderView</a>和<a href="http://developer.android.com/reference/android/widget/ListView.html#setAdapter(android.widget.ListAdapter)" title="setAdapter">setAdapter</a>方法贴下来</p>
<pre><code class="language-java">/**
 * Add a fixed view to appear at the top of the list. If addHeaderView is
 * called more than once, the views will appear in the order they were
 * added. Views added using this call can take focus if they want.
 * &lt;p&gt;
 * NOTE: Call this before calling setAdapter. This is so ListView can wrap
 * the supplied cursor with one that that will also account for header
 * views.
 *
 * @param v The view to add.
 * @param data Data to associate with this view
 * @param isSelectable whether the item is selectable
 */
public void addHeaderView(View v, Object data, boolean isSelectable) {
    if (mAdapter != null) {
        throw new IllegalStateException(
                &quot;Cannot add header view to list -- setAdapter has already been called.&quot;);
    }

    FixedViewInfo info = new FixedViewInfo();
    info.view = v;
    info.data = data;
    info.isSelectable = isSelectable;
    mHeaderViewInfos.add(info);
}

/**
 * Sets the data behind this ListView.
 *
 * The adapter passed to this method may be wrapped by a {@link WrapperListAdapter},
 * depending on the ListView features currently in use. For instance, adding
 * headers and/or footers will cause the adapter to be wrapped.
 *
 * @param adapter The ListAdapter which is responsible for maintaining the
 *        data backing this list and for producing a view to represent an
 *        item in that data set.
 *
 * @see #getAdapter()
 */
@Override
public void setAdapter(ListAdapter adapter) {
    if (null != mAdapter) {
        mAdapter.unregisterDataSetObserver(mDataSetObserver);
    }

    resetList();
    mRecycler.clear();

    if (mHeaderViewInfos.size() &gt; 0|| mFooterViewInfos.size() &gt; 0) {
        mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
    } else {
        mAdapter = adapter;
    }

    //其它的一些代码这里省略之...
}
</code></pre>
<p>从代码和注释里都可以很清楚的得知，<code>addHeaderView</code>一定要在<code>setAdapter</code>之前调用，如果不这样做，<code>addHeaderView</code>会抛出一个异常。Android为什么要这样？这是因为，在<code>setAdapter</code>的时候，会针对我遇到的这种情况（也就是添加Header后<code>position</code>不正确的这种情况）做些特殊的处理。<code>setAdapter</code>在内部判断了当前ListView是否有Header或者Footer，如果没有，就直接使用参数传进来的adapter；如果有，则用一个decorated的<code>HeaderViewListAdapter</code>来替换参数。这个<code>HeaderViewListAdapter</code>的使命，就是排除Header和Footer，让<code>position</code>（当然也包括<a href="http://developer.android.com/reference/android/widget/Adapter.html#getItem(int)" title="getItem">getItem</a>, <a href="http://developer.android.com/reference/android/widget/Adapter.html#getItemId(int)" title="getItemId">getItemId</a>）等方法的<code>position</code>参数）正确返回。</p>
<p>分析到这里，解决方案就出来了：在<code>onItemClick</code>不要直接使用我们声明的adapter，而是用ListView里的那个decorated adapter。获取它的方法就是调用<code>parent.getAdapter()</code>。当然，如果ListView没有Header和Footer，直接使用声明的adapter也没有问题，不过为了避免出错，还是统一使用decorated adapter比较好。</p>
<p>把onItemClick改成下面这样，就可以了</p>
<pre><code class="language-java">@Override
public void onItemClick(AdapterView&lt;?&gt; parent, View v, int position, long id) {
    doSomething(parent.getAdapter().getItem(position));
}
</code></pre>
<p>本文由Roy最初发表于：<a href="http://blog.chengbo.net/2012/03/09/onitemclick-return-wrong-position-when-listview-has-headerview.html">http://blog.chengbo.net/2012/03/09/onitemclick-return-wrong-position-when-listview-has-headerview.html</a>，你可以在保持文章完整和保留本声明的情况下转帖、分发和印刷等。</p>]]></content:encoded>
    </item>
    
    <item>
      <title>如何提升Android手机电池的使用时间</title>
      <link>https://blog.chengbo.net/2011/06/29/how-to-maximizing-your-android-phones-battery-life.html</link>
      <guid isPermaLink="true">https://blog.chengbo.net/2011/06/29/how-to-maximizing-your-android-phones-battery-life.html</guid>
      <pubDate>Wed, 29 Jun 2011 06:59:29 +0000</pubDate>
      <description>很多朋友抱怨Android手机耗电恐怖，其实我刚 入手我的i9003 的时候，也被他恐怖的耗电量吓了一跳，睡觉之前还是60%，第二天早上起床却发现手机已经耗尽了所有电量，自动关机了。其实这也不能完全怪Android，它耗电在于几个方面，同样还是和ios做对比： Android和ios的体制不一样。ios实际上是一个单…</description>
      <content:encoded><![CDATA[<p><img alt="" src="/static/images/2011/06/android.logo_.jpg" /></p>
<p>很多朋友抱怨Android手机耗电恐怖，其实我刚<a href="http://blog.chengbo.net/2011/06/15/my-new-mobile-samsung-i9003.html">入手我的i9003</a>的时候，也被他恐怖的耗电量吓了一跳，睡觉之前还是60%，第二天早上起床却发现手机已经耗尽了所有电量，自动关机了。其实这也不能完全怪Android，它耗电在于几个方面，同样还是和ios做对比：</p>
<p>Android和ios的体制不一样。ios实际上是一个单线程系统，程序只能在前台运行，进入后台后就已经是睡眠状态了，只能通过apple的API来进行推送，这就是iphone qq超级难用的原因。而android就是一个纯粹的多线程操作系统，程序完全可以在后台正常运行，这样的代价自然是会多耗费一些电量了。</p>
<p>Android程序普遍上来说比起ios的质量要差一些。Google为了在数量上尽量追赶Apple AppStore，所以在Android Market的准入审批上不像Apple做的那么严格，再加上Android开发门槛要比ios低的多得多，自然造成了Android程序质量普遍偏低。很多程序未充分考虑以及测试在电量上的消耗，如果你正好安装了这些程序，那么电池电量消耗过快也不足为奇了。</p>
<p>那么有什么办法可以尽量提高电池的使用时间呢，我总结了下面几点：</p>
<ul>
<li>安装质量高的程序。安装前到网上搜索下别人的经验，或者安装后记得监控程序的耗电量（Settings-&gt;About phone-&gt;Battery use），太高的话卸载找另外的替代品吧或者采取其它措施，比如我发现Talkbox就非常耗电，我什么都没做，也没运行它，它自己在后台就耗了30%，所以果断卸载，换微信。</li>
<li>关掉平常不用的服务。WIFI，蓝牙，GPS，3G这些肯定不会随时都需要使用的，平常的时候把它们都关掉，等到需要使用的时候再打开。</li>
<li>调节合适的屏幕亮度。屏幕是耗电大户，因此调节一个合适的亮度对于提升电池使用时间非常有帮助，在Settings-&gt;Display-&gt;Brightness里选择一个对你来说合适的亮度，感觉Automatic brightness偏亮了一点。</li>
<li>保持桌面整洁。Widgets别用太多了，这些东西看起来挺小巧，但是他们还是要耗电滴。</li>
<li>禁用同步。Android可以同步日历，邮件，联系人，相册等信息，关掉这个功能也会提高电池的使用时间。Settings-&gt;Accounts and sync</li>
<li>经常杀进程。不用的程序杀掉它，别以为你按了Home键返回了，它就会安安静静的呆在后台，有些程序不会这么乖，他们可能会同步数据，会联网尝试更新，所以，不用了就kill them，很多软件可以方便的让你批量杀进程，比如我用的Advanced Task Killer，感觉还不错，免费软件。</li>
<li>不要用动态墙纸。动态墙纸看起来挺炫，但是肯定要占用CPU资源的，低调点，静态的墙纸还是有很多好看的。</li>
<li>手机放在常温的地方。过冷过热都会影响电池使用时间。炎炎烈日下面暴晒的车车中，太恐怖了，为了你也为了手机，开空调吧。</li>
</ul>
<p>这里特别说明下，上面有些方法过于极端了点，手机本来就是拿来使用的，如果你把所有功能都关掉，那自然最省电，但是这还叫手机吗？根据自己的情况做下适当的优化，这才是最好的。</p>
<p>另外，如果你还有其他办法补充，欢迎留言分享给大家。</p>]]></content:encoded>
    </item>
    
    <item>
      <title>升级我的I9003到2.3.4</title>
      <link>https://blog.chengbo.net/2011/06/26/upgrade-my-i9003-to-2-3-4.html</link>
      <guid isPermaLink="true">https://blog.chengbo.net/2011/06/26/upgrade-my-i9003-to-2-3-4.html</guid>
      <pubDate>Sun, 26 Jun 2011 14:22:27 +0000</pubDate>
      <description>忍不住手痒，把我的i9003升级到了Gingerbread（Android 2.3.4），在这里把我的升级过程写下来，希望对大家有点帮助。 到 这里 下载最新的2.3.4的firmware，压缩包的解压密码是samfirmware.com。 运行Odin3_v1.83.exe。 选中Re-Partition，Auto…</description>
      <content:encoded><![CDATA[<p><img alt="" src="/static/images/2011/06/samsung_logo.png" /></p>
<p>忍不住手痒，把我的i9003升级到了Gingerbread（Android 2.3.4），在这里把我的升级过程写下来，希望对大家有点帮助。</p>
<ol>
<li>到<a href="http://forum.xda-developers.com/showthread.php?t=1004647">这里</a>下载最新的2.3.4的firmware，压缩包的解压密码是samfirmware.com。</li>
<li>运行Odin3_v1.83.exe。</li>
<li>选中Re-Partition，Auto Reboot和F. Reset Time三个复选框。</li>
<li>点击PIT然后选择latona_20110114.pit文件。</li>
<li>手机关机，然后依次按音量向下键（按住不放），Home（按住不放），电源（按住不放），过几秒手机会显示一个绿色的机器人在挖东西，这就是传说中的挖煤模式，学名download mode。</li>
<li>用数据线连接手机和电脑，如果需要装驱动请耐心等待驱动安装完毕。然后odin会识别手机的COM，显示在界面上，我的是COM9。</li>
<li>点击Start按钮。</li>
<li>完毕后点击Reset按钮，这时程序会自动取消Re-Partition复选框。</li>
<li>点击BOOTLOADER按钮选择APBOOT_I9003XXKP7_CL280937_REV08_eng_mid_ship.tar；点击PDA按钮选择CODE_I9003XXKP7_CL280937_REV08_eng_mid_ship.tar.md5；点击PHONE按钮选择MODEM_I9003XXKP7_REV_00_CL1021949.tar.md5；点击CSC选择GT-I9003-CSC-MULTI-OXAKP7.tar.md5。</li>
<li>扣掉电池，按照第5步的方法再次进入挖煤模式。</li>
<li>点击Start按钮，然后不要动，直到看到绿色的PASS。</li>
<li>启动手机，此时就可以正常使用了，但是相机还用不了，黑屏，解决方法是按照上面的步骤再刷一次，就可以了。</li>
</ol>
<p>升级后的一些感受：</p>
<ul>
<li>虽说不是稳定版本，但我觉得还是挺稳定的。</li>
<li>界面有所变化，但是区别不大。</li>
<li>ROM很干净，没有太多预装的程序。</li>
<li>Local setting里没有中国，但是并不是说不支持访问中文网页，安装中文软件，以及发送接收中文短信，只是说手机的界面是英文的，并且某些显示的风格也是按照英文的文化来的，比如说号码的分段方式。</li>
<li>VPN依然不能使用，哎。</li>
</ul>
<p>2011/7/3 Update:
I9003XXKP7貌似和微信有点冲突，经常在待机情况下无法唤醒机器，只有拔电池重新开机。目前我已刷至最新的I9003XXKP9，再当一次小白鼠。
2011/8/20 Update:
目前最新版是I9003XXKPH。</p>
<p>经过我的测试，<strong>I9003XXKP9已经可以连接VPN了</strong>，哇哈哈哈哈！</p>]]></content:encoded>
    </item>
    
  </channel>
</rss>