<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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"
	>

<channel>
	<title>Times New Rohan &#187; Tinkering</title>
	<atom:link href="http://robrohan.com/category/tinkering/feed/" rel="self" type="application/rss+xml" />
	<link>http://robrohan.com</link>
	<description>任意的技术</description>
	<pubDate>Fri, 16 May 2008 17:18:23 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>Automator Radio - Create your own automatic podcast</title>
		<link>http://robrohan.com/2008/04/21/automator-radio-create-your-own-automatic-podcast/</link>
		<comments>http://robrohan.com/2008/04/21/automator-radio-create-your-own-automatic-podcast/#comments</comments>
		<pubDate>Mon, 21 Apr 2008 17:28:21 +0000</pubDate>
		<dc:creator>小罗</dc:creator>
		
		<category><![CDATA[Chinese]]></category>

		<category><![CDATA[Mac]]></category>

		<category><![CDATA[Tinkering]]></category>

		<category><![CDATA[Web Apps]]></category>

		<category><![CDATA[Windows]]></category>

		<category><![CDATA[Automator]]></category>

		<category><![CDATA[Podcast]]></category>

		<guid isPermaLink="false">http://robrohan.com/2008/04/21/automator-radio-create-your-own-automatic-podcast/</guid>
		<description><![CDATA[Another hair brained scheme&#8230;
I woke up Saturday with an idea (which is actually a joke at our house now, &#8220;Guess what honey, I have an idea!&#8221;). I wanted to have a podcast of news bits that I could listen to while I did my morning routine - the catch being I wanted it daily, and [...]]]></description>
			<content:encoded><![CDATA[<p>Another hair brained scheme&#8230;</p>
<p>I woke up Saturday with an idea (which is actually a joke at our house now, &#8220;Guess what honey, I have an idea!&#8221;). I wanted to have a podcast of news bits that I could listen to while I did my morning routine - the catch being I wanted it daily, and I wanted to control the shows overall subjects at will.</p>
<p>That desire, along with my new found <a href="http://automator.us/">Automator</a> curiosity, led me to throw together <em>Rohan Times Radio News</em> ( :-D ). It&#8217;s an automatic process that takes an RSS feed, reads it, and makes a podcast out of the stories. To get the content I want, I am using <a href="http://pipes.yahoo.com/pipes/" target="_blank">yahoo pipes</a> to filter and sort the feeds, and then republish the feeds as the shows teleprompt.</p>
<p>Here is a basic overview of how it works (sorry for the oddities with the movie, youtube seems to be doing odd things on upload lately):</p>
<div class="movie"><embed src="http://www.youtube.com/v/Rt8fg7KCcvU&amp;hl=en" width="425" height="355" type="application/x-shockwave-flash" wmode="transparent"></embed></div>
<p>One of the coolest parts about this is it basically requires no code (I did, however, use a bit of code to have finer control).</p>
<p>I don&#8217;t think I can publish the podcast for the world, as I think it would be seen as a copyright violation, but if you are interested in this let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://robrohan.com/2008/04/21/automator-radio-create-your-own-automatic-podcast/feed/</wfw:commentRss>
		</item>
		<item>
		<title>XBox Controller as a SNES Controller</title>
		<link>http://robrohan.com/2008/04/04/xbox-controller-as-a-snes-controller/</link>
		<comments>http://robrohan.com/2008/04/04/xbox-controller-as-a-snes-controller/#comments</comments>
		<pubDate>Fri, 04 Apr 2008 15:32:57 +0000</pubDate>
		<dc:creator>小罗</dc:creator>
		
		<category><![CDATA[Mac]]></category>

		<category><![CDATA[Tinkering]]></category>

		<category><![CDATA[Games]]></category>

		<category><![CDATA[Hack]]></category>

		<category><![CDATA[Nintendo]]></category>

		<guid isPermaLink="false">http://robrohan.com/?p=697</guid>
		<description><![CDATA[If you are into playing emulated Super Nintendo games on your Mac OS X laptop, but find the keyboard awkward to use, and have a spare Xbox controller, and a spare USB cord laying around &#8230; have I got a deal for you.
(I should preface this with using game emulators and and game ROMS is, [...]]]></description>
			<content:encoded><![CDATA[<p>If you are into playing emulated Super Nintendo games on your Mac OS X laptop, but find the keyboard awkward to use, and have a spare Xbox controller, and a spare USB cord laying around &#8230; have I got a deal for you.</p>
<p>(I should preface this with using game emulators and and game ROMS is, sadly, of questionable legality)</p>
<p>Short and sweet: it seems XBox controllers (non 360) use USB to do their magic, so modifying an XBox controller to use with your computer is very simple. Just cut the XBox controller and the USB cords then wire them together (leaving out the yellow wire). The inside wire colors will match up so it shouldn&#8217;t be hard, but here is <a href="http://www.metacafe.com/watch/851500/xbox_controller_hack/">a movie showing how it&#8217;s done</a> (ignore the driver part unless you are on windows).</p>
<p>Once your controller is ready, download the Mac OS X <a href="http://xhd.sourceforge.net/">XBox HID driver</a>. After it&#8217;s installed you can find the settings in <i>System Preferences</i>.</p>
<p>Finally, fire up <a href="http://www.snes9x.com/downloads.php">Snes9x</a>, and go into <i>Config</i> &gt; <i>Configure Controllers</i>. You should see the following:</p>
<div class="movie">
<img src="http://robrohan.com/wp-content/uploads/2008/04/picture-1.png" height="242" width="391" border="1" hspace="4" vspace="4" alt="Picture 1" />
</div>
<p>In this screen click on a button (for example the purple <i>up</i> arrow) then press the corresponding button on the controller (the direction pad up button, or the joystick up). Once the controller is configured you&#8217;re all set to play - and you didn&#8217;t even have to <a href="http://www.retrousb.com/index.php?categoryID=81">ruin your original SNES controllers</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://robrohan.com/2008/04/04/xbox-controller-as-a-snes-controller/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Head, Shoulders, Knees, and Toes (in Chinese)</title>
		<link>http://robrohan.com/2007/12/28/head-shoulders-knees-and-toes-in-chinese/</link>
		<comments>http://robrohan.com/2007/12/28/head-shoulders-knees-and-toes-in-chinese/#comments</comments>
		<pubDate>Sat, 29 Dec 2007 03:23:54 +0000</pubDate>
		<dc:creator>小罗</dc:creator>
		
		<category><![CDATA[Chinese]]></category>

		<category><![CDATA[Tinkering]]></category>

		<guid isPermaLink="false">http://robrohan.com/2007/12/28/head-shoulders-knees-and-toes-in-chinese/</guid>
		<description><![CDATA[One of my presents this year was a program called Anime Studio. It&#8217;s a fun little program that you can use to create animations.
It works by adding bones to vector drawings, and then you animate the drawings with the bones. It&#8217;s quite fun.
I&#8217;ve been learning how it works by making silly, pointless movies. I showed [...]]]></description>
			<content:encoded><![CDATA[<p>One of my presents this year was a program called Anime Studio. It&#8217;s a fun little program that you can use to create animations.</p>
<p>It works by adding bones to vector drawings, and then you animate the drawings with the bones. It&#8217;s quite fun.</p>
<p>I&#8217;ve been learning how it works by making silly, pointless movies. I showed this one to my wife, and she was cracking up (mostly because the animation is so dorky I think).</p>
<p>Hopefully you&#8217;ll find it mildly entertaining (both my wife and I are quite mad, so our version of funny is not often other people&#8217;s).</p>
<div class="movie">
<object width="425" height="350"><param name="movie" value="http://www.youtube.com/v/l5iyBc7HJgA"></param> <embed src="http://www.youtube.com/v/l5iyBc7HJgA" type="application/x-shockwave-flash" width="425" height="350"></embed></object>
</div>
<p>The song is from <a href="http://chinesepod.com/">ChinesePod.com</a>, from the lesson <a href="http://chinesepod.com/lessons/head-shoulders-knees-and-toes/discussion">Head, Shoulders, Knees, and Toes</a>.</p>
<p>(for the astute Chinese learner they&#8217;ll notice the words are actually Hair, Shoulders, Knees, and Feet)</p>
]]></content:encoded>
			<wfw:commentRss>http://robrohan.com/2007/12/28/head-shoulders-knees-and-toes-in-chinese/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Git, the Frugal Project&#8217;s Repository</title>
		<link>http://robrohan.com/2007/12/17/git-the-frugal-projects-repository/</link>
		<comments>http://robrohan.com/2007/12/17/git-the-frugal-projects-repository/#comments</comments>
		<pubDate>Mon, 17 Dec 2007 18:29:09 +0000</pubDate>
		<dc:creator>小罗</dc:creator>
		
		<category><![CDATA[Linux]]></category>

		<category><![CDATA[Mac]]></category>

		<category><![CDATA[Tinkering]]></category>

		<category><![CDATA[Web Apps]]></category>

		<category><![CDATA[Git]]></category>

		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://robrohan.com/2007/12/17/git-the-frugal-projects-repository/</guid>
		<description><![CDATA[The vast majority of the projects I have worked on were in some kind of source control. Lately they&#8217;ve been in Subversion, but before that most were in CVS. I&#8217;ve also worked on a couple projects that were using Microsoft Source Safe (I don&#8217;t even know if that&#8217;s still around).
Recently, however, I&#8217;ve been getting into [...]]]></description>
			<content:encoded><![CDATA[<p>The vast majority of the projects I have worked on were in some kind of source control. Lately they&#8217;ve been in Subversion, but before that most were in CVS. I&#8217;ve also worked on a couple projects that were using Microsoft Source Safe (I don&#8217;t even know if that&#8217;s still around).</p>
<p>Recently, however, I&#8217;ve been getting into <a href="http://git.or.cz/">Git</a>. Git is different from any source control system I&#8217;ve used. It&#8217;s a distributed source control system which not only gives it a huge work flow advantage in my opinion, but also means you can have repositories without a dedicated server.</p>
<h2>The distributed nature</h2>
<p>Every coder I&#8217;ve ever seen that is working on a project using source control has a work flow like the following:</p>
<p>1) Checkout code locally.<br />
2) Work on code locally trying to add features / bug fixes.<br />
3) If work spans several days then, &#8220;update&#8221; every day, and try to solve small conflicts with the main repository.<br />
4) When done - commit, and if there are conflicts, resolve the conflicts.</p>
<p>The main, and slightly elusive, point I&#8217;ve noticed with this setup is the repository is nothing but a database. All the work, all the code managing is done by the developer and then &#8220;pushed&#8221; to the repository database when ready.</p>
<p>The developers local copy is really just a branch of the main repository. So why not let the developers local copy have all the rights and privileges to be someone else&#8217;s main repository? Git was built with this idea in mind, and the explicit goal of being able to merge all changes back upstream.</p>
<p>What this means in reality, is branching and merging are at the core of git, and I&#8217;ve found it to work really well. It lets you test wild ideas with code, and not worry about how you&#8217;re going to rollback your changes if you go to far out, and it doesn&#8217;t work - if that makes any sense.</p>
<h2>Look ma, no server</h2>
<p>The other exciting part about git, for me, is you don&#8217;t need a server running a process anywhere - you don&#8217;t need a git server running somewhere.</p>
<p>Most places I&#8217;ve worked I&#8217;ve implemented source control, and managing a source control server is time consuming. This is all subjective to the level of funding, number of people on staff, tools available, amount of branching etc, but what if you could just remove the overhead of another service that someone has to manage?</p>
<p>By the way, quick plug, I often use <a href="http://cvsdude.com">cvsdude.com</a> for my Subversion outsourcing, but even with the tools they offer someone still has to manage the Subversion server (adding users, permissions, the cost). </p>
<p>While I feel you&#8217;re insane if you don&#8217;t use source control, sometimes running an entire Subversion server is overkill for a project. Writing a Mac OS X widget for example - do you need a full on server, bugzilla, a wiki, and trac hooks for that?</p>
<p>With git, however, you can just put a copy of the repository on a server, and call it your main repository. Done. You can control push access using SSH logins, and if you want to allow anonymous access to the repository, you can make it available over HTTP.</p>
<p>Here is what this looks like, for my notes and if you want to try it yourself:</p>
<p>Get a git repository. Either a new one:</p>
<pre>
$ mkdir my_cool_project; cd my_cool_project;
$ git-init
$ cp -R [all_my_code_files] ./
$ git add .
$ git commit -a
</pre>
<p>or copy a whole subversion repository (comments changes and all):</p>
<pre>
$ git-svn clone -T trunk https://mystuff.com/my_project
</pre>
<p>Do your stuff</p>
<pre>
$ write_lots_of_amazing_code.sh
$ git commit -a
</pre>
<p>Prepare for publish:</p>
<pre>
$ pwd
/home/guy/my_cool_project
$ git repack -d
$ git clone --bare -l . /tmp/your-proj.git
$ git --bare --git-dir=/tmp/your-proj.git update-server-info
$ mv /tmp/your-proj.git /home/guy/Desktop
</pre>
<p>Now upload the <i>your-proj.git</i> folder to your publicly available server. As I said before, if you want to allow anonymous access put it in a HTTP available folder, if you want a private one, put it in your home directory or something.</p>
<p>Turn on the hooks for it to update itself when you &#8220;push&#8221; your new code changes. (one thing to note here is the server needs to have git installed - <i>sudo apt-get install git git-core</i> on Debian / Ubuntu systems)</p>
<pre>
$ uname -a
your_server GNU/Linux
$ pwd
/var/www/myrepo.com/your-proj.git
$ git --bare update-server-info
$ chmod a+x hooks/post-update
</pre>
<p>Now it&#8217;s ready to be used as a central server.</p>
<p>To &#8220;checkout&#8221; the code - really cloning the repository locally:</p>
<pre>
$ uname -a
your_development_box
$ git clone ssh://[username]@[server]/var/www/myrepo.com/your-proj.git
</pre>
<p>Then working locally, you commit your changes locally.</p>
<pre>
$ git commit -a
</pre>
<p>It is very easy to make branches and merge them back into your local <i>trunk</i> (often named <i>master</i>). Here is an in depth <a href="http://lwn.net/Articles/210045/">posting on the subject</a> when you are ready.</p>
<p>To update your local repository to the code on the server:</p>
<pre>
$ git pull
</pre>
<p>And when you are all set with your local changes and ready to push them to the server:</p>
<pre>
$ git push
</pre>
<p>Anonymous checkout:</p>
<pre>
$ git clone http://myrepo.com/your-proj.git
</pre>
<h2>Last bits</h2>
<p>Some things to consider:</p>
<p>  * Git doesn&#8217;t work on windows without Cygwin. It works great on Mac OS X and Linux however.</p>
<p>  * There are very few GUI tools for git, you (and your developers) need to be cool with the terminal. (try gitk from the command line)</p>
<p>  * You will have many full copies of your repository floating around. While this is great for backup purposes, it might be bad for some projects.</p>
<p>  * On Mac OS X I think you have to compile Git from source (I did anyway). It&#8217;s not hard, but if that scares you&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://robrohan.com/2007/12/17/git-the-frugal-projects-repository/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Server Backup with Amazon S3 (Howto)</title>
		<link>http://robrohan.com/2007/11/03/server-backup-with-amazon-s3-howto/</link>
		<comments>http://robrohan.com/2007/11/03/server-backup-with-amazon-s3-howto/#comments</comments>
		<pubDate>Sat, 03 Nov 2007 18:30:35 +0000</pubDate>
		<dc:creator>小罗</dc:creator>
		
		<category><![CDATA[Linux]]></category>

		<category><![CDATA[Mac]]></category>

		<category><![CDATA[Ruby]]></category>

		<category><![CDATA[Tinkering]]></category>

		<category><![CDATA[Web Apps]]></category>

		<category><![CDATA[S3]]></category>

		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://robrohan.com/2007/11/03/server-backup-with-amazon-s3-howto/</guid>
		<description><![CDATA[I&#8217;ve been interested in using Amazon S3 (Simple Storage Service) for server backups, but I couldn&#8217;t find a simple, straight forward howto. This is a walk though on one way to setup a Unix server to automatically backup data to Amazon S3.
I guess I should start out with what Amazon S3 is I suppose&#8230; It&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been interested in using Amazon S3 (Simple Storage Service) for server backups, but I couldn&#8217;t find a simple, straight forward howto. This is a walk though on one way to setup a Unix server to automatically backup data to Amazon S3.</p>
<p>I guess I should start out with what Amazon S3 is I suppose&#8230; It&#8217;s a service that you can use to store reams of data, offsite, online, accessible anytime for a decent price. As of this writing the costs are:</p>
<p>Storage: $0.15 per GB-Month of storage used<br />
Data Transfer: $0.10 per GB - all data transfer in</p>
<p>$0.18 per GB - first 10 TB / month data transfer out<br />
$0.16 per GB - next 40 TB / month data transfer out<br />
$0.13 per GB - data transfer out / month over 50 TB</p>
<p>see <a href="http://www.amazon.com/gp/browse.html?node=16427261">Amazon S3</a> for more details. If you use .mac, you can think of it like an iDisk on steroids - or a huge webdav server - but it&#8217;s not just one sever it&#8217;s a farm of servers with huge amounts of redundancy.</p>
<p>My goal here is to make a simple process that will automatically back up some of my web sites - for this example I am using this blog. What this process is going to do is backup the blogs MySQL database. This will just be a basic setup, but you can tweak it or add to it as you see fit.</p>
<h3>The Plan</h3>
<p>We are going to make some scripts that dump the database to a directory, and then sync that directory with the Amazon Service. The sync will work somewhat like rsync so if we want to add other files to the <i>sync tree</i>, it will just be a matter of adding them into sync area. </p>
<h3>Amazon S3 Account</h3>
<p>To start off, you&#8217;ll need an S3 account. You can sign up (and login) <a href="https://aws-portal.amazon.com/gp/aws/developer/account/index.html">here</a>. As you can tell, I like the Amazon Storage Service; however, their web site lacks in the usability department in my opinion. So if you get a bit confused trying to navigate the site, don&#8217;t worry you&#8217;re not alone.</p>
<p>After you go though the account setup process, you&#8217;ll need to get your <i>access key id</i> (like your username) and your <i>secret access key</i> (like your password). To find these hover over the <i>Your Web Services Button</i> button on the top right, and click <i>AWS Access Identifiers</i> (See shot below).</p>
<div class="movie">
<img src="http://robrohan.com/wp-content/uploads/2007/11/safariscreensnapz001.jpg" height="215" width="306" border="1" hspace="4" vspace="4" alt="Safariscreensnapz001" />
</div>
<p>From that screen, on the right you should see your Access Key ID, and be able to show your Secret key. You&#8217;ll need these for the next steps.</p>
<h3>Using S3 From the Desktop</h3>
<p>You&#8217;ll likely want access to your S3 account from your desktop. If only to verify the backups are running. However, once you get this setup, see how well it works, and see how inexpensive it is you&#8217;ll probably start using it for other stuff (as I do :D).</p>
<p>For desktop access there are quite a few choices. I went the cheap route. I use <a href="http://jets3t.s3.amazonaws.com/applications/cockpit.html">cockpit</a>. It&#8217;s a Java based application that lets you use your S3 account from the desktop. It has the feel of an FTP application. <a href="http://www.jungledisk.com/">Jungle Disk</a> is another one I hear is very good. It mounts the S3 account as if it&#8217;s a remote drive (on Mac) or a drive letter on windows (and it also works on Linux) - Jungle Disk is $20 USD.</p>
<p>I am going to use cockpit in this article, but they should all work about the same.</p>
<p>Start up cockpit. On Mac / Linux, run the file:</p>
<pre>
$ /Applications/jets3t-0.5.0/bin/cockpit.sh
</pre>
<p>(on windows it&#8217;s the cockpit.bat file)</p>
<p>When it first starts up there will be several ways to login. You can read up on the choices on the cockpit website, but for now we&#8217;ll use the <i>Direct Login</i> tab. On this tab is where you&#8217;ll put the keys you got from the S3 Account page (see image)</p>
<div class="movie">
<img src="http://robrohan.com/wp-content/uploads/2007/11/org.jets3t.apps.cockpit.cockpitscreensnapz001.jpg" height="268" width="350" border="1" hspace="4" vspace="4" alt="Org.Jets3T.Apps.Cockpit.Cockpitscreensnapz001" />
</div>
<p>S3 uses things called <i>buckets</i>. You&#8217;ll see that term quite a bit when reading about S3. It&#8217;s just a place to store stuff. You can think of it as a drive letter (if you&#8217;re coming from a windows world), or a database table, or whatever. What we need to do here is make a bucket for our backups. I made one called <i>server.robrohan.com</i> - you can name yours anything you like. The shot below is of my <i>server.robrohan.com</i> bucket and a few backups that have already run.</p>
<div class="movie">
<img src="http://robrohan.com/wp-content/uploads/2007/11/org.jets3t.apps.cockpit.cockpitscreensnapz002.jpg" height="252" width="350" border="1" hspace="4" vspace="4" alt="Org.Jets3T.Apps.Cockpit.Cockpitscreensnapz002" />
</div>
<p>To create a new bucket, click the gear icon on the left and select <i>Create new bucket&#8230;</i>. You&#8217;ll need at least one bucket to continue with this article.</p>
<h3>Database Dump</h3>
<p>Now that we have an Amazon S3 account setup, we can access it from our desktop, and we have one bucket ready to hold stuff we can start doing our backups. The first step in doing a backup of our MySQL database is to get a dump of the database. If you already have a process for this you can skip this section. (Note: This is a very simple way to get a backup of a MySQL database there are better, more efficient ways to do this.)</p>
<p>Here is a simple script to dump a database to a bziped file. You an call this script <i>dbbackup.sh</i>, and it is written so it can be called from cron. (This is pretty insecure, so be sure you&#8217;re ok with that or seek help in making it more secure if you need)</p>
<pre>
#!/bin/sh

# This file backs up a database to a backup dir
# that will be synced with s3

if [ $# != "3" ]; then
    echo &#8220;Usage:&#8221;
    echo &#8221;      $0 [database] [username] [password]&#8221;
    exit 1
fi

DATE=`date +%d`
DB=$1
USER=$2
PASS=$3

BACKUPDIR=/home/my_user_name/backups
DBSTORE=${BACKUPDIR}/database

# create database backup
mysqldump &#8211;add-drop-table \
          -h localhost \
          &#8211;user=${USER} \
          &#8211;password=${PASS} \
          ${DB} \
          | bzip2 -c > ${DBSTORE}/${DB}_${DATE}.sql.bz2
</pre>
<p>Note the variable <i>BACKUPDIR</i>. This should be a directory you create somewhere on your server that you want to &#8220;sync&#8221; with the Amazon service. Meaning that anything you put in that directory will get backed up to S3. In this article we are just putting a database backup in the tree, but you could put server code, documents on the server, copies of configuration files, or whatever. The main point being anything in that directory will get copied to S3 (recursively - subdirectories as well).</p>
<p>The script is run like the following:</p>
<pre>
$ ./dbbackup.sh mydatabase myusername mypassword
</pre>
<p>And would produce the file:</p>
<pre>
/home/my_user_name/backups/database/mydatabase_[day_of_month].sql.bz2
</pre>
<p>In this process database backups will only go back a month. The first of the month will overwrite the last month&#8217;s first of the month backup. If you&#8217;d like to archive forever, just change the <i>DATE</i> variable to be <i>`date +%y%m%d`</i>. For my purposes, doing backups everyday is overkill.</p>
<h3>Syncing with S3</h3>
<p>So now the meat of the thing. There are, as in the desktop access, many server side scripts you can use to write data to S3. What this example is going to use is <a href="http://s3sync.net/wiki">s3sync.rb</a>. s3sync is a ruby script that acts much like rsync. There is also an outdated perl version, and even a <a href="http://code.google.com/p/s3-bash/">bash</a> version. You can try others if you&#8217;d like, but for this I&#8217;ll be using the ruby version. That, of course, means you&#8217;ll need ruby on the sever (not rails or anything, just ruby).</p>
<p>(If you don&#8217;t have ruby you can do <i>apt-get install ruby</i>, <i>yum install ruby</i>, <i>ports install ruby</i>, or whatever. It&#8217;s often very easy to get ruby on your *nix box)</p>
<p>Download and untar the s3sync file:</p>
<pre>
$ wget http://s3.amazonaws.com/ServEdge_pub/s3sync/s3sync.tar.gz
$ tar -zxvf s3sync.tar.gz
</pre>
<p>Copy s3config.yml.example to s3config.yml and edit it. Adding in your Amazon S3 keys. It&#8217;s also a good idea to setup the SSL certificate so your transfers to S3 will be https. Checkout the README.txt on how to do that. If you don&#8217;t care about that remove the -s flag from the script we will be writing in a minute.</p>
<p>(Optional: just to be on the safe side, you might want to make the s3config.yml file owned by the cron user that will run the backup, and then <i>chmod 600 s3config.yml</i>. It&#8217;s not a huge amount of security, but it&#8217;s better than nothing.)</p>
<p>Next up is the wrapper script that will run the s3sync ruby script. This is a simple script that just moves into the directory where we installed s3sync, and runs the script (I named it <i>s3backup.sh</i>):</p>
<pre>
#!/bin/sh

# This file syncs a direcotry with a specified
# bucket.
BACKUPDIR=/home/my_user_name/backups
SYNCDIR=/home/my_user_name/s3sync
S3BUCKET=server.robrohan.com
S3PREFIX=x
S3STORE=${S3BUCKET}:${S3PREFIX}

# move to the ruby sync direcotry where the .yml file is
cd ${SYNCDIR}
./s3sync.rb -r -s ${BACKUPDIR} ${S3STORE}
</pre>
<p>Obviously, you&#8217;ll want to change the paths to your install locations (or make them env variables or an include or whatever), the bucket name, and if you are not doing https, remove the -s flag.</p>
<p>Also, the <i>S3PREFIX</i> is any string you want it to be. It&#8217;s kind of like a drive letter inside the bucket - the &#8220;root&#8221; of the bucket so to speak. You can leave it as <i>x</i>.</p>
<p>At this point you should be able to run this script by hand (don&#8217;t forget <i>chmod u+x</i>):</p>
<pre>
$ ./s3backup.sh
</pre>
<p>And your backup directory should &#8220;sync&#8221; with S3. You can verify that by refreshing the view in cockpit (the gear on the right has &#8220;Refresh object listing&#8221;). You can also right click on an object to delete / download it.</p>
<p>I use the sync term is somewhat lightly because the ruby process doesn&#8217;t delete files that have been deleted from the backup directory. It will only add or update the files on S3 - hardly a show stopper though.</p>
<h3>Cron&#8217;ing It</h3>
<p>The last step is wrapping this all up into a cron job so you don&#8217;t have to think about it. The server should just back itself up.</p>
<p>To do this requires one more simple wrapper <i>server_backup.sh</i>:</p>
<pre>
#!/bin/sh

UTILS=/home/my_user_name/path_to_the_previous_scripts

# Create database backups
${UTILS}/dbbackup.sh database1 myusername1 password1
${UTILS}/dbbackup.sh database2 myusername2 password2

# Send the backups to S3
${UTILS}/s3backup.sh
</pre>
<p>Pretty straight forward. It creates backups of any databases we care about, and then calls the script to sync the backup directory with Amazon S3.</p>
<p>The last step is adding it to cron which you should probably already know how to do, but basically it&#8217;s:</p>
<pre>
$ crontab -e
</pre>
<p>and then adding a line something like:</p>
<pre>
0 2 * * 1,3,5 /home/my_user_name/path_to_the_previous_scripts/server_backup.sh
</pre>
<p>Which will do a backup at 2:00am on Monday, Wednesday, and Friday - tweak as needed of course.</p>
<h3>Conclusion</h3>
<p>When I first started coding almost no one out outside of Rome used source control (Rome meaning corporations). Now, if you&#8217;re not using source control on your projects people look at you like you&#8217;re nuts (and for good reason - it just makes sense to use source control). I think backups are following this same pattern. Everyone knows they should backup, but few actually do - and those that do probably don&#8217;t do it offsite or redundantly.</p>
<p>Amazon S3 (and similar services) offer pretty easy to use, low cost, redundant, high bandwidth, always on, offsite storage. If your data == your business, you&#8217;re nuts not to use Amazon S3 or something like it.</p>
<p>I hope this lifted some of the mystery of how to use this kind of service (the exercise did for me :D).</p>
]]></content:encoded>
			<wfw:commentRss>http://robrohan.com/2007/11/03/server-backup-with-amazon-s3-howto/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Borrowing YouTube Videos</title>
		<link>http://robrohan.com/2007/10/04/borrowing-youtube-videos/</link>
		<comments>http://robrohan.com/2007/10/04/borrowing-youtube-videos/#comments</comments>
		<pubDate>Fri, 05 Oct 2007 03:43:56 +0000</pubDate>
		<dc:creator>小罗</dc:creator>
		
		<category><![CDATA[Flash]]></category>

		<category><![CDATA[Mac]]></category>

		<category><![CDATA[Tinkering]]></category>

		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://robrohan.com/2007/10/04/borrowing-youtube-videos/</guid>
		<description><![CDATA[A quick tutorial on how to download flash videos and convert them into other formats using Safari and VLC. You can use the borrowed videos for mash ups, offline viewing, or playing on your ipod or iphone.

 
Borrowing YouTube Videos

]]></description>
			<content:encoded><![CDATA[<p>A quick tutorial on how to download flash videos and convert them into other formats using Safari and VLC. You can use the borrowed videos for mash ups, offline viewing, or playing on your ipod or iphone.</p>
<div class="movie">
<object width="425" height="350"><param name="movie" value="http://www.youtube.com/v/G3EifK3pL48"></param> <embed src="http://www.youtube.com/v/G3EifK3pL48" type="application/x-shockwave-flash" width="425" height="350"></embed></object><br />
<a href="http://www.youtube.com/watch?v=G3EifK3pL48">Borrowing YouTube Videos</a>
</div>
]]></content:encoded>
			<wfw:commentRss>http://robrohan.com/2007/10/04/borrowing-youtube-videos/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Mac OS X WebArchive Extractor Utility</title>
		<link>http://robrohan.com/2007/09/18/mac-os-x-webarchive-extractor-utility/</link>
		<comments>http://robrohan.com/2007/09/18/mac-os-x-webarchive-extractor-utility/#comments</comments>
		<pubDate>Wed, 19 Sep 2007 03:50:51 +0000</pubDate>
		<dc:creator>小罗</dc:creator>
		
		<category><![CDATA[Mac]]></category>

		<category><![CDATA[Tinkering]]></category>

		<category><![CDATA[Web Apps]]></category>

		<guid isPermaLink="false">http://robrohan.com/2007/09/18/mac-os-x-webarchive-extractor-utility/</guid>
		<description><![CDATA[The other day I wanted to use TextEdit to make simple web pages for documentation purposes. I actually didn&#8217;t really care what application I used, just one that was more word processor-ish than a coding tool. TextEdit did most of what I needed by saving to HTML, but the kicker was I wanted to have [...]]]></description>
			<content:encoded><![CDATA[<p>The other day I wanted to use TextEdit to make simple web pages for documentation purposes. I actually didn&#8217;t really care what application I used, just one that was more word processor-ish than a coding tool. TextEdit did most of what I needed by saving to HTML, but the kicker was I wanted to have images in the document.</p>
<p>TextEdit can save HTML with images in a file format called WebArchive, but in order to put the files on a web server for the world to view, the files need to be extracted from that format into a normal directory structure.</p>
<p>I found a utility on Sourceforge that would extract the file from a WebArchive format, but it seemed to mangle the src attribute of the image tags. Since the application was so close to what I wanted, I decided to tweak the code to my liking.</p>
<p>However, the source code provided on Sourceforge was incomplete - it was missing the .nib files. So I decided to just fork that project and put together my own <a href="http://robrohan.com/projects/WebArchiveExtractor/">Web Archive Extractor</a> utility using most of that project&#8217;s code as a base. </p>
<p>After I got it all setup, it seems the core worked correctly without me changing anything. Meaning the image references where getting generated correctly. So either the binary distribution is not the same as the source, or I just messed up somehow when originally extracting.</p>
<p>Either way, my version works like I want it to, and it looks better ^_^</p>
<p>If you&#8217;re looking for such a thing, you can download it on the <a href="http://robrohan.com/projects/WebArchiveExtractor/">project page</a>.</p>
<p>(Safari can also save whole web pages in WebArchive format - images, css, js, and all - by selecting Save As&#8230; If you are leaning something about a site, you can do that and then look over the site&#8217;s code at your leisure.)</p>
]]></content:encoded>
			<wfw:commentRss>http://robrohan.com/2007/09/18/mac-os-x-webarchive-extractor-utility/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Howto: Create AdBlock Resistant Ads</title>
		<link>http://robrohan.com/2007/09/14/howto-create-adblock-resistant-ads/</link>
		<comments>http://robrohan.com/2007/09/14/howto-create-adblock-resistant-ads/#comments</comments>
		<pubDate>Fri, 14 Sep 2007 08:37:21 +0000</pubDate>
		<dc:creator>小罗</dc:creator>
		
		<category><![CDATA[Tinkering]]></category>

		<category><![CDATA[Web Apps]]></category>

		<guid isPermaLink="false">http://robrohan.com/2007/09/14/howto-create-adblock-resistant-ads/</guid>
		<description><![CDATA[I am felling a little cantankerous.
There are a few ways to get around the AdBlock Firefox plugin, and I&#8217;ve yet to see any site do it. For a hoot, here is one way to get around Adblock. (My teaser post a year ago gets a heck of a lot of traffic, and no one offered [...]]]></description>
			<content:encoded><![CDATA[<p>I am felling a little cantankerous.</p>
<p>There are a few ways to get around the AdBlock Firefox plugin, and I&#8217;ve yet to see any site do it. For a hoot, here is one way to get around Adblock. (My <a href="http://robrohan.com/2006/09/20/subverting-adblock-demo-of-always-showing-ads/">teaser post</a> a year ago gets a heck of a lot of traffic, and no one offered me 5 million for this - doh)</p>
<p>(If this post makes you upset: While this isn&#8217;t really an exploit, it can kind of be seen that way. Isn&#8217;t publishing exploits good for security? This should just make AdBlock stronger in the end.)</p>
<p>One flaw of Adblock is that you have to deny images, or explicitly block ads. Adblock makes this easy by letting you do regular expressions to block ads, but this also means that you have to find patterns in the ad URL. So the simplest way around Adblock is to never create ad URLs that have a pattern.</p>
<p>This will become an arms race at some point, but as long as you can keep URLs random - file name, directory name, and directory levels - it should be near impossible to create a regular expression to stop the ads. In the <a href="http://robrohan.com/UnAdblock/">example</a>, the URL is only mildly random, and using a real word every once in a while should make it even more difficult to defend against (though I think even the example would be hard to keep ads from showing up).</p>
<p>One other thing required for this technique to work is the ads have to be served from the same domain as the other content - or at least appear that way. If you use an ad server that supports RPC calls to get the ads to display, or if you serve your own ads you can use this technique. </p>
<p>The reason the ads need to come from the same domain is because it makes creating a rule like <i>http://robrohan.com/*</i> a bad thing. Doing a rule like that will stop the ads, but it will also stop every image on the site. If you have at least somewhat interesting content (say an image in the article), they are less likely to create that rule.</p>
<p>So here is how you use the technique. (This stuff is not really new, just applied in an effort to subvert adblock)</p>
<p>The example uses Apache mod_rewrite to force URLs that look a certain way to the ad generation page.</p>
<pre>
&lt;IfModule mod_rewrite.c&gt;
RewriteEngine On
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^([a-zA-Z0-9\/]+)/([a-zA-Z0-9]+)(.*)$ ad.php
&lt;/IfModule&gt;
</pre>
<p>You can tweak this to your liking / needs, but, again, you&#8217;ll want the randomness to start at the root of the site. Most frameworks hit the index page on the root and delegate work out from there. If you are using a framework like that you should be golden, else it should still work with a bit of tweaking. In the <a href="http://robrohan.com/UnAdblock/">example</a>, it calls another php page with no problems for example.</p>
<p>You could do the mod rewrite stuff with straight php, asp, cf, ruby or whatever too if you want (or if you use IIS).</p>
<p>Once the <i>when-you-get-some-random-stuff-send-the-request-to-the-ad-generation-page</i> process is setup, you can write some sort of random url generation function that will cause that rule to fire. Then use this function everywhere you want to show an ad. In the example I am using:</p>
<pre>
function ad_url($base) {
	$levels = rand(1,10);
	$fake_dir  = '';

	for( $x=0; $x<$levels; $x++ ) {
		$bit_o_stuff = md5(uniqid());

		$part = substr($bit_o_stuff, rand(1, strlen($bit_o_stuff)), rand(1,strlen($bit_o_stuff)) );
		$fake_dir .= $part . '/';
	}

	return $base . $fake_dir;
}
</pre>
<p>Which basically just creates a path that could be between 1 and 10 levels deep with random directory names. The urls it spits out would look something like:</p>
<pre>
http://robrohan.com/UnAdblock/4e9800998ecf8427e/0b204e9800998ecf8427e/800998ecf8427e/8/98ecf8427/8f00b204e9800998ecf8427e/0998ecf/f8427e/204e9800998/204e9800998ecf8427e/
or
http://robrohan.com/UnAdblock/27e/04e9800998ecf8427e/
or
http://robrohan.com/UnAdblock/b20/8ecf8427e/9//998ecf8427e/427e/e/98f00b204e9800998ecf8427e/427e/
</pre>
<p>(remember for the example it&#8217;s in a subdirectory, but you&#8217;d want the URL from the root when doing it for real)</p>
<p>The last part is the ad.php file which just loads and shows some ad:</p>
<pre>
header('Content-Type: image/jpeg');
//lots of hardcoded stuff, but you get the idea
$x = 0;
$images = array();

//get a listing of files from a directory or from a database
for ( $x=0; $x<=3; $x++) {
	$images[] = $x . '.jpg';
}

$full_path_start = str_replace('ad.php', '', $_SERVER['SCRIPT_FILENAME']);
$dsp_image = rand(0,3);
echo file_get_contents($full_path_start . 'images/' . $images[$dsp_image]);
</pre>
<p>The result can be seen on the <a href="http://robrohan.com/UnAdblock/">example</a> page.</p>
<p>Using this in the real world you&#8217;d have to have a way to know which ad you were showing to create the proper anchor tag - you could have the first number of each subdirectory be a digit of the ID or something, but remember patterns are your enemy.</p>
<p>Anyway, I hope that was fun. And I eagerly look forward to being bombarded with ads.</p>
]]></content:encoded>
			<wfw:commentRss>http://robrohan.com/2007/09/14/howto-create-adblock-resistant-ads/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Studying on Your Bike</title>
		<link>http://robrohan.com/2007/09/01/studying-on-your-bike/</link>
		<comments>http://robrohan.com/2007/09/01/studying-on-your-bike/#comments</comments>
		<pubDate>Sun, 02 Sep 2007 00:19:06 +0000</pubDate>
		<dc:creator>小罗</dc:creator>
		
		<category><![CDATA[Chinese]]></category>

		<category><![CDATA[Tinkering]]></category>

		<guid isPermaLink="false">http://robrohan.com/2007/09/01/studying-on-your-bike/</guid>
		<description><![CDATA[I started riding my bike to work. I figured it would be good for the environment, save a bit of money, and I need to take more exercise anyway so it&#8217;s a win win win.
The ride is about 6 miles one way. Depending on the head wind, and how I feel about taking on the [...]]]></description>
			<content:encoded><![CDATA[<p>I started riding my bike to work. I figured it would be good for the environment, save a bit of money, and I need to take more exercise anyway so it&#8217;s a win win win.</p>
<p>The ride is about 6 miles one way. Depending on the head wind, and how I feel about taking on the hills that day, the trip takes 35-45 minutes.</p>
<p>In my Chinese class, I am memorizing poems to work on my tones. It seemed like there should be a way to use that extra hour plus of pedal time to study without killing myself.</p>
<p>Here is my simple, cheap way of having my reference material available while I ride. (This is a really, really simple hack).</p>
<p>By the way, this is <b>not</b> something you can use to read while riding (unless you are crazy). This will probably only be useful if you are trying to memorize something, and doing a quick glance down is enough to check yourself.</p>
<p>This is what it looks like when you&#8217;re done:</p>
<div class="movie">
<img src="http://robrohan.com/wp-content/uploads/2007/09/bikeupper.jpg" height="573" width="430" border="0" hspace="0" vspace="0" alt="IMG_0093.JPG" title="IMG_0093.JPG" />
</div>
<div class="movie">
<img src="http://robrohan.com/wp-content/uploads/2007/09/bikelower.jpg" height="573" width="430" border="0" hspace="0" vspace="0" alt="IMG_0094.JPG" title="IMG_0094.JPG" />
</div>
<p>You can probably figure out how to do it from the picture, but here is how I put mine together.</p>
<p>Get a sandwich bag and three twisty ties. The ties can be anything really, but I happen to have some fancy cable ties.</p>
<p>Cut 4 small slits on the back of the sandwich bag. Two horizontally below the zipper, towards the top, on the left and right side. Then cut two slits vertically towards the middle of the bag about an inch apart.</p>
<p>Then feed the ties though the top slits, and secure the ties to the handle bars. Finally, feed the other tie though the middle slits, and secure it to the bottom of the handle bars.</p>
<p>You can fold a piece of paper with a good amount of it showing, and slip it in the sandwich bag. If you do it right, you can close the sandwich bag to keep water out.</p>
<p>You could also use it to hold a map, but it probably wont stand up to serious mountain biking. However, I&#8217;ve been using the same bag for two weeks now and it&#8217;s still going strong.</p>
]]></content:encoded>
			<wfw:commentRss>http://robrohan.com/2007/09/01/studying-on-your-bike/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Parallel Universes Documentary</title>
		<link>http://robrohan.com/2007/05/06/parallel-universes-documentary/</link>
		<comments>http://robrohan.com/2007/05/06/parallel-universes-documentary/#comments</comments>
		<pubDate>Sun, 06 May 2007 17:29:11 +0000</pubDate>
		<dc:creator>小罗</dc:creator>
		
		<category><![CDATA[General]]></category>

		<category><![CDATA[Tinkering]]></category>

		<guid isPermaLink="false">http://robrohan.com/2007/05/06/parallel-universes-documentary/</guid>
		<description><![CDATA[This is a fun, easy to understand video from the BBC on string theory, m theory, and parallel universes.

 
BBC Documentary - Parallel Universes

]]></description>
			<content:encoded><![CDATA[<p>This is a fun, easy to understand video from the BBC on string theory, m theory, and parallel universes.</p>
<div class="movie">
<embed style="width:400px; height:326px;" id="VideoPlayback" type="application/x-shockwave-flash" src="http://video.google.com/googleplayer.swf?docId=-1649449085849253581&#038;hl=en" flashvars=""> </embed><br />
<a href="http://video.google.com/videoplay?docid=-1649449085849253581">BBC Documentary - Parallel Universes</a>
</div>
]]></content:encoded>
			<wfw:commentRss>http://robrohan.com/2007/05/06/parallel-universes-documentary/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
