<?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"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Everything In Between &#187; Unix/Linux</title>
	<atom:link href="http://maymay.net/blog/category/techcomputing/unixlinux/feed/" rel="self" type="application/rss+xml" />
	<link>http://maymay.net/blog</link>
	<description>The brutally honest, first-person account of Meitar Moscovitz&#039;s life.</description>
	<lastBuildDate>Thu, 19 Jan 2012 08:54:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>How to work around &#8220;sorry, you must have a tty to run sudo&#8221; without sacrificing security</title>
		<link>http://maymay.net/blog/2010/03/17/how-to-work-around-sorry-you-must-have-a-tty-to-run-sudo-without-sacrificing-security/</link>
		<comments>http://maymay.net/blog/2010/03/17/how-to-work-around-sorry-you-must-have-a-tty-to-run-sudo-without-sacrificing-security/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 01:21:50 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[Bash/Shell Scripting]]></category>
		<category><![CDATA[Security & Privacy]]></category>
		<category><![CDATA[Tech/Computing]]></category>
		<category><![CDATA[Unix/Linux]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/?p=1208</guid>
		<description><![CDATA[While working on $client&#8216;s Linux server last week, I found myself installing a cron job that ran as root. The cron job called a custom bash script that, in turn, called out to various custom maintenance tasks client had already written. One task in particular had to run as a different user. During testing, I [...]]]></description>
			<content:encoded><![CDATA[<p>While working on $<var>client</var>&#8216;s Linux server last week, I found myself installing a cron job that ran as <code>root</code>. The cron job called a custom bash script that, in turn, called out to various custom maintenance tasks <var>client</var> had already written. One task in particular had to run as a different user.</p>
<p>During testing, I discovered that the odd-ball task failed to run, and found the following error in the system log:</p>
<pre>sudo: sorry, you must have a tty to run sudo</pre>
<p>I traced this error to a line trying to invoke a <code>perl</code> command as a user called <code>dynamic</code>:</p>
<pre>sudo -u dynamic /usr/bin/perl run-periodic-tasks --load 5 --randomly</pre>
<p>A simple Google search turned up an obvious solution to the error: <a href="http://www.adminmyserver.com/articles/sorry-you-must-have-a-tty-to-run-sudo">use <code>visudo</code> to disable sudo&#8217;s tty requirement</a>, allowing <code>sudo</code> to be invoked from any shell lacking a tty (including <code>cron</code>). This would have solved my problem, but it just felt wrong, dirty, and most troublingly <em>insecure</em>.</p>
<p>One reason why <code>sudo</code> ships with the <code>requiretty</code> option enabled by default is, among other reasons, to <a href="http://www.cyberciti.biz/faq/linux-unix-bsd-sudo-sorry-you-must-haveattytorun/">prevent remote users from exposing the root password over <acronym title="Secure SHell">SSH</acronym></a>. Disabling this security precaution for a simple maintenance task <em>already running as root</em> seemed totally unnecessary, not to mention irresponsible. Moreover, <var>client</var>&#8216;s script didn&#8217;t even need a tty.</p>
<p>Thankfully, there&#8217;s a better way: use <code>su --session-command</code> and send the whole job to the background.</p>
<pre>su --session-command="/usr/bin/perl run-periodic-tasks --load 5 --randomly" dynamic &#038;</pre>
<p>This line launches a new, non-login shell (typically <code>bash</code>) <em>as the other user</em> in a separate, background process and runs the command you passed using the shell&#8217;s <code>-c</code> option. Sending the command to the background (using <code>&#038;</code>) continues execution of the rest of the cron job.</p>
<p>A process listing would look like this:</p>
<pre>root     28109     1  0 17:10 ?        00:00:00 su --session-command=/usr/bin/perl run-periodic-tasks --load 5 --randomly dynamic
dynamic  28110 28109  0 17:10 ?        00:00:00 bash -c /usr/bin/perl run-periodic-tasks --load 5 --randomly</pre>
<p>Note the parent process (PID 28109) is owned by root but the actual <code>perl</code> process (PID 28110) is being run as <code>dynamic</code>.</p>
<p>This in-script solution that replaces <code>sudo -u <var>user</var> <var>cmd</var></code> with <code>su --session-command=<var>cmd</var> <var>user</var></code> seems much better than relying on a change in <code>sudo</code>&#8216;s default (and more secure) configuration to me.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2010/03/17/how-to-work-around-sorry-you-must-have-a-tty-to-run-sudo-without-sacrificing-security/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>How to use HTTP Basic Authentication with git</title>
		<link>http://maymay.net/blog/2008/08/08/how-to-use-http-basic-authentication-with-git/</link>
		<comments>http://maymay.net/blog/2008/08/08/how-to-use-http-basic-authentication-with-git/#comments</comments>
		<pubDate>Fri, 08 Aug 2008 05:56:57 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[Crosspost]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[Tech/Computing]]></category>
		<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/?p=563</guid>
		<description><![CDATA[Coming right on the heels of my need to set up a git repository on shared hosts, I next wanted to see if I could use HTTP authentication for such a repository. Of course, HTTP authentication is an extremely insecure protocol, but it typically is enough to dissuade the casual user (such as Googlebot) from [...]]]></description>
			<content:encoded><![CDATA[<p>Coming right on the heels of my need to <a href="/blog/2008/08/06/how-to-install-git-on-a-shared-web-hosts-server/">set up a git repository on shared hosts</a>, I next wanted to see if I could use <acronym title="HyperText Transfer Protocol">HTTP</acronym> authentication for such a repository. Of course, <acronym title="HyperText Transfer Protocol">HTTP</acronym> authentication is an extremely insecure protocol, but it typically is enough to dissuade the casual user (such as Googlebot) from peeking at things you don&#8217;t want available on the public Internet, so it has its uses.</p>
<p>Note that with <a href="/blog/2008/08/06/how-to-install-git-on-a-shared-web-hosts-server/">the set up described</a> in the above-linked previous post, you can only pull over <acronym title="HyperText Transfer Protocol">HTTP</acronym>. <strong>This is usually what you want.</strong> If you want to be able to push over <acronym title="HyperText Transfer Protocol">HTTP</acronym> as well, git must be compiled with the <code>USE_CURL_MULTI</code> flag.</p>
<p>This is, as it turns out, because <code>git</code> seems to use <code>curl</code> for its <acronym title="HyperText Transfer Protocol">HTTP</acronym> operations, which also obviously means you must have <code>curl</code> installed on your workstation if you don&#8217;t already and it also implies that it&#8217;s <code>curl</code>, <em>not <code>git</code></em> which you need to configure. In other words, accessing a git repository that is behind <acronym title="HyperText Transfer Protocol">HTTP</acronym> authentication is exactly the same as accessing one without it, and so is <a href="http://www.kernel.org/pub/software/scm/git/docs/user-manual.html#public-repositories">publishing a git repository to an <acronym title="HyperText Transfer Protocol">HTTP</acronym> server</a>. The rest of this short tutorial assumes you have published your repository at <code>http://example.com/git/public-repo.git</code> and are using <a href="//apache.org/">the Apache web server</a>.</p>
<h2>Step 1: Create an <acronym title="HyperText Transfer Protocol">HTTP</acronym> Basic Authentication username and password file</h2>
<p>First, you&#8217;ll need to create a file that lists the usernames who are permitted to access your repository over <acronym title="HyperText Transfer Protocol">HTTP</acronym> Basic authentication. This is easily accomplished with the <code>htpasswd</code> utility (or your host&#8217;s custom web <acronym title="User Interface">UI</acronym>, if one is provided). Let&#8217;s create a file called <code>.git-htpasswd</code> to store these usernames and passwords.</p>
<p>From your shell, run the following command:</p>
<pre>
htpasswd -c <var>/path/to/DOCUMENT_ROOT</var>/.git-htpasswd <var>username</var>
</pre>
<p>where <var>/path/to/DOCUMENT_ROOT</var> is the full path to the root directory of your web site and <var>username</var> is the username you want to add. If you want to add subsequent users to this file, run the same command again without the <code>-c</code>, like this:</p>
<pre>
htpasswd <var>/path/to/DOCUMENT_ROOT</var>/.git-htpasswd <var>another_username</var>
</pre>
<p>You&#8217;ll then be prompted to enter a password, and then prompted again to verify that you&#8217;ve typed it correctly.</p>
<h2>Step 2: Configure <acronym title="HyperText Transfer Protocol">HTTP</acronym> Basic Authentication on Apache</h2>
<p>Next, configure standard <acronym title="HyperText Transfer Protocol">HTTP</acronym> Basic Authentication on Apache. In most shared hosting environments, you&#8217;ll be allowed to configure per-directory passwords using <code>.htaccess</code> files. Some hosts provide web <acronym title="User Interface">UI</acronym> interfaces for creating &#8220;protected folders,&#8221; which is basically the same thing. Make certain that the kind of protection you select is &#8220;Basic,&#8221; because <code>curl</code> will require that.</p>
<p>To do that, create a new file named <code>.htaccess</code> in your <code><var>DOCUMENT_ROOT</var>/git</code> directory if one does not already exist with the following contents:</p>
<pre>
AuthType Basic
AuthName "Git"
AuthUserFile <var>/path/to/DOCUMENT_ROOT</var>/.git-htpasswd
Require valid-user
</pre>
<p>This tells Apache to look for usernames and passwords in the file named <code>.git-htpasswd</code> we created in step 1.</p>
<p>If everything is set up correctly, you should now be able to access <code>http://example.com/git/public-repo.git</code> in your Web browser and you should be presented with a login dialogue box.</p>
<h2>Step 3: Configure <code>curl</code> on your (client) workstation computer</h2>
<p>Next, configure your local <code>curl</code> client. <code>git-pull</code> will call <code>curl</code> with its <code>--netrc-optional</code> switch for <acronym title="HyperText Transfer Protocol">HTTP</acronym> operations. This means <code>curl</code> will look for a file named <code>.netrc</code> in your home directory and will read authentication configurations from that file. The format of this file is incredibly simple:</p>
<pre>
machine <var>yourserver.example.com</var>
username <var>your_username</var>
password <var>your_password</var>
</pre>
<p>To check if this is working correctly, run <code>curl</code> yourself to access the current <code>HEAD</code> of the public repository and see if you get the expected result:</p>
<pre>
curl --netrc --location -v http://example.com/git/public-repo.git/HEAD | grep 'ref: refs/heads'
</pre>
<p>If you see a line of output then you know this is working, otherwise you should double check your work.</p>
<h2>Step 4: There is no step four</h2>
<p>You&#8217;re done. With this configuration, you can <code>git-pull</code> as you normally would, and <code>git</code> will automatically use your <code>.netrc</code> file to enable <code>curl</code>&#8216;s <acronym title="HyperText Transfer Protocol">HTTP</acronym> authentication schemes.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2008/08/08/how-to-use-http-basic-authentication-with-git/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>How to install git on a shared web host&#8217;s server</title>
		<link>http://maymay.net/blog/2008/08/06/how-to-install-git-on-a-shared-web-hosts-server/</link>
		<comments>http://maymay.net/blog/2008/08/06/how-to-install-git-on-a-shared-web-hosts-server/#comments</comments>
		<pubDate>Wed, 06 Aug 2008 16:59:35 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tech/Computing]]></category>
		<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/?p=556</guid>
		<description><![CDATA[Tonight I found myself with the need to host my own git repository on one of my own servers. This time, for the first time, it was a server I don&#8217;t actually have administrative access to and it was one where git wasn&#8217;t pre-installed. Thankfully, with a bit of help from Blue Static, I built [...]]]></description>
			<content:encoded><![CDATA[<p>Tonight I found myself with the need to host my own git repository on one of my own servers. This time, for the first time, it was a server I don&#8217;t actually have administrative access to <em>and</em> it was one where git wasn&#8217;t pre-installed. Thankfully, with a bit of help from <a href="http://www.bluestatic.org/blog/2007/08/01/git-public-push-ing/">Blue Static</a>, I built and installed git from scratch in literally ten minutes. Here&#8217;s the short version of how I did it, which may even be generic enough that you can copy and paste this into a <code>bash</code> shell prompt on your server to do the same thing:</p>
<pre class="shell">
cd ~/                          # change to home directory
test -d ~/src || mkdir ~/src   # if there isn't already a ~/src directory, create it
cd ~/src                       # then change to that directory
curl -O http://www.kernel.org/pub/software/scm/git/git-1.5.6.4.tar.gz # download
tar -xvzf git-1.5.6.4.tar.gz   # and extract the git source code
cd git-1.5.6.4                 # change to the source code directory
./configure --prefix=$HOME     # configure build to install into $HOME
make                           # do the build
make install                   # move the built binaries to the right places
echo "export PATH=\$PATH:$HOME/bin" >> ~/.bashrc # make sure non-interactive shells can find git
</pre>
<p>Of special note is the last line, which sets up the necessary <code>$PATH</code> specifically for non-interactive <code>bash</code> shells for use with <code>git-push</code> or <code>git-pull</code>. With out that, you&#8217;ll run into the infamous &#8220;bash: git-receive-pack: command not found&#8221; error.</p>
<p><ins datetime="2008-10-14T08:57:11+00:00">Also, of course, lines 4 through 6 are referring to version 1.5.6.4 of the git tarballs, so you may want to change these to point to whatever is now the most recent version.</ins></p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2008/08/06/how-to-install-git-on-a-shared-web-hosts-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>One minute Mac tip: Schedule off-hours downloads by enabling `at`, `batch` UNIX job scheduling commands</title>
		<link>http://maymay.net/blog/2008/07/14/one-minute-mac-tip-schedule-off-hours-downloads-by-enabling-at-batch-unix-job-scheduling-commands/</link>
		<comments>http://maymay.net/blog/2008/07/14/one-minute-mac-tip-schedule-off-hours-downloads-by-enabling-at-batch-unix-job-scheduling-commands/#comments</comments>
		<pubDate>Mon, 14 Jul 2008 08:48:56 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[Crosspost]]></category>
		<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Tech/Computing]]></category>
		<category><![CDATA[Unix/Linux]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/?p=508</guid>
		<description><![CDATA[In a lot of places in the world, many people still have to pay for bandwidth costs. I&#8217;m one of those people who just can&#8217;t afford to download lots of stuff during peak hours when my bandwidth might quickly get shaped or, worse, I&#8217;ll get charged. Nevertheless, there are often plenty of legit reasons to [...]]]></description>
			<content:encoded><![CDATA[<p>In a lot of places in the world, many people still have to pay for bandwidth costs. I&#8217;m one of those people who just can&#8217;t afford to download lots of stuff during peak hours when my bandwidth might quickly get shaped or, worse, I&#8217;ll get charged. Nevertheless, there are often plenty of legit reasons to initiate huge downloads.</p>
<p>In these cases, it makes sense to be smart about <em>when</em> I initiate these downloads. Being something of a UNIX-head myself, I wanted to use the age-old <code>at</code> command to download a Linux ISO during off-peak hours, which my <acronym title="Internet Service Provider">ISP</acronym> says starts at 2 AM. Much to my chagrin, I found that <code>at</code> doesn&#8217;t work by default on Mac <acronym title="Operating System">OS</acronym> X and, worse, the Leopard man page leads to a dead end (though it didn&#8217;t back in Tiger…).</p>
<p>Turns out that the system daemon that is responsible for checking up on <code>at</code> jobs has been wrapped with a <code>launchd</code> job. This makes enabling <code>at</code> on your system really easy:</p>
<pre>sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.atrun.plist</pre>
<p>Once you&#8217;ve done this, you can now use <code>at</code> as you normally have done. For instance, I could now schedule my downloads to happen during the off-peak hours:</p>
<pre><samp>Perseus:Fedora maymay$ </samp>at 2:15am tomorrow # now press <kbd>return</kbd>
curl -LO http://download.fedoraproject.org/pub/fedora/linux/releases/9/Fedora/x86_64/iso/Fedora-9-x86_64-<acronym title="Digital Video Disc">DVD</acronym>.iso
# now press <kbd>CTRL-D</kbd>.
<samp>job 1 at Tue Jul 15 02:15:00 2008
Perseus:Fedora maymay$ </samp>atq
<samp>1	Tue Jul 15 02:15:00 2008</samp>
</pre>
<p>This is also incredibly handy for scheduling just about any resource-intensive task that you don&#8217;t have to do <em>right now</em>. To take it one step further, you can even let the computer itself choose when to run these resource-heavy tasks by using the <code>batch</code> command, which will execute commands much like <code>at</code> but will check the system load average instead of the system clock to determine if it should start the job.</p>
<p>Note that with the <code>com.apple.atrun</code> job loaded <code>/usr/libexec/atrun</code> is started every 30 seconds (unless you change the <code>StartInterval</code> key in the <code>plist</code> file). Since the <code>atrun</code> command checks a file on disk (that it places in the <code>/usr/lib/cron/jobs</code> directory) to see if there is any work to do, this will probably prevent your disks from ever sleeping, which could be a major concern for battery life on portables. Also, obviously, your computer needs to be turned on and awake for the job to actually launch.</p>
<p>For more information, check out the result of typing <code>man at</code> and <code>man launchctl</code> at a Terminal prompt. There&#8217;s also a really good <a href="http://video.google.com/videoplay?docid=1781045834610400422">Google Tech Talk about Launchd</a> that will teach you a lot more about job scheduling on Mac <acronym title="Operating System">OS</acronym> X.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2008/07/14/one-minute-mac-tip-schedule-off-hours-downloads-by-enabling-at-batch-unix-job-scheduling-commands/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>One minute Mac tip: Create the illusion that Bonjour works over a VPN</title>
		<link>http://maymay.net/blog/2008/06/26/one-minute-mac-tip-create-the-illusion-that-bonjour-works-over-a-vpn/</link>
		<comments>http://maymay.net/blog/2008/06/26/one-minute-mac-tip-create-the-illusion-that-bonjour-works-over-a-vpn/#comments</comments>
		<pubDate>Thu, 26 Jun 2008 10:25:46 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[Tech/Computing]]></category>
		<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/?p=483</guid>
		<description><![CDATA[If you&#8217;re a Mac user who often uses VPN connections, you&#8217;ll notice one very disappointing thing about connecting to your corporate or personal network over such tunneled connections: typically, Bonjour-style addresses (such as &#8220;computer-name.local&#8221;) don&#8217;t work. This is because multicast DNS (or mDNS) doesn&#8217;t work over a tunnel. Though there are ways to get it [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re a Mac user who often uses VPN connections, you&#8217;ll notice one very disappointing thing about connecting to your corporate or personal network over such tunneled connections: typically, Bonjour-style addresses (such as &#8220;computer-name.local&#8221;) don&#8217;t work. This is because multicast <acronym title="Domain Name System or Domain Name Server">DNS</acronym> (or mDNS) doesn&#8217;t work over a tunnel. Though there are ways to get it functional, they are pretty complicated and require that you have a lot of esoteric networking knowledge.</p>
<p>However, if the services you typically access via Bonjour use static <acronym title="Internet Protocol">IP</acronym> addresses, then there is one age-old networking technique you can use to simulate Bonjour-style naming conventions without actually using Bonjour. This, of course, is the <code>/etc/hosts</code> file.</p>
<p>The <code>/etc/hosts</code> is a simple, static, text-based mapping of computer names to <acronym title="Internet Protocol">IP</acronym> addresses. It does exactly what Bonjour does except it doesn&#8217;t keep itself up to date when things change. Of course, if you&#8217;re using static IPs for the services you want access to, you can pretty safely assume that things aren&#8217;t going to be changing frequently anyway. Long-time sysadmins will laugh at this, but I say let them laugh. This is remarkably useful and very easy to implement.</p>
<p>Let&#8217;s assume I&#8217;m running a personal web server on my home network, and I can access my home network via a VPN. On my home network, my web server&#8217;s <acronym title="Internet Protocol">IP</acronym> address is, say, <code>192.168.2.100</code>, and I usually access it as <code>http://server.local/</code>. All I need to do is open a Terminal prompt and run the following commands as an administrative user:</p>
<pre>
sudo echo "192.168.2.100	server.local" >> /etc/hosts
</pre>
<p>That&#8217;s it. What this does is hard-wire the name <code>server.local</code> so that it always resolves to the <acronym title="Internet Protocol">IP</acronym> address <code>192.168.2.100</code>. Now, anytime anything on my computer tries to access <code>server.local</code>, it&#8217;ll always access <code>192.168.2.100</code> directly instead of ever needing to make an mDNS query on the network. The net effect is that we can trick our computer into thinking that Bonjour is working, even when it&#8217;s not—such as over a VPN connection.</p>
<p>Note that in default cases, hard-wiring an <acronym title="Internet Protocol">IP</acronym> address like this <em>completely prevents your computer from ever asking other computers (such as <acronym title="Domain Name System or Domain Name Server">DNS</acronym> servers) what the current <acronym title="Internet Protocol">IP</acronym> address for this name is</em>. That means if the <acronym title="Internet Protocol">IP</acronym> address of the remote server changes, you won&#8217;t be notified, and things will just not work. So be mindful that you&#8217;ve made this change, and revert it as a first step in troubleshooting procedures.</p>
<p>By the way, Windows users can do the very same thing simply by editing their <code>etc/hosts</code>. They can find this file at <code>C:\WINDOWS\system32\drivers\etc\hosts</code> and can edit it with Notepad. They will also need to <a href="//www.apple.com/support/downloads/bonjourforwindows.html">install Bonjour for Windows</a> to get Bonjour working in the first place, of course.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2008/06/26/one-minute-mac-tip-create-the-illusion-that-bonjour-works-over-a-vpn/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Quick &#8216;N&#8217; Dirty Drupal Module SVN Tagging Script</title>
		<link>http://maymay.net/blog/2008/05/14/quick-n-dirty-drupal-module-svn-tagging-script/</link>
		<comments>http://maymay.net/blog/2008/05/14/quick-n-dirty-drupal-module-svn-tagging-script/#comments</comments>
		<pubDate>Wed, 14 May 2008 09:46:14 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[Bash/Shell Scripting]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Tech/Computing]]></category>
		<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[Drupal]]></category>
		<category><![CDATA[Subversion]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/?p=435</guid>
		<description><![CDATA[In a (rather beastly) project at work today, I found myself needing to import a significant number of contributed Drupal modules into Subversion vendor branches to prepare for custom development. To do so manually would have been quite the hassle, so after downloading the appropriate tarballs and creating a module_name/current directory under my vendor/drupal/modules vendor [...]]]></description>
			<content:encoded><![CDATA[<p>In a (rather beastly) project at work today, I found myself needing to import a significant number of contributed Drupal modules into Subversion vendor branches to prepare for custom development. To do so manually would have been quite the hassle, so after downloading the appropriate tarballs and creating a <code><var>module_name</var>/current</code> directory under my <code>vendor/drupal/modules</code> vendor branch directory, I concocted this little (relatively untested) script to handle the mass tagging operations I needed to perform.</p>
<pre>for i in *; do
    v=`grep 'version = "' "$i/current/$i/"*.info |
      cut -d ':' -f 2 |
        sed -e 's/^version = "/v/' -e 's/"$//'`
    svn cp "$i/current" "$i/$v"
done;</pre>
<p>It&#8217;s a bit buggy for some modules that have multiple <code>.info</code> files, but I&#8217;m sure a few more pipeline stages can fix that. (Which, because I&#8217;m done with this at the moment, I will leave as an exercise to the reader.)</p>
<p>Chalk this one up as another testament to the power of shell scripting and how it can help every developer get their job done faster.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2008/05/14/quick-n-dirty-drupal-module-svn-tagging-script/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How To: Move all pages in an Apple WikiServer Group to a new Group</title>
		<link>http://maymay.net/blog/2008/05/01/how-to-move-all-pages-in-an-apple-wikiserver-group-to-a-new-group/</link>
		<comments>http://maymay.net/blog/2008/05/01/how-to-move-all-pages-in-an-apple-wikiserver-group-to-a-new-group/#comments</comments>
		<pubDate>Thu, 01 May 2008 09:18:16 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Tech/Computing]]></category>
		<category><![CDATA[Unix/Linux]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/?p=427</guid>
		<description><![CDATA[As I&#8217;ve been blogging about, I&#8217;ve been playing a lot with Apple&#8217;s new WikiServer (or &#8220;Teams Server&#8221;) at work. We&#8217;re still evaluating what we&#8217;d like to use it for, but as part of the experiments, I&#8217;ve been finding myself having to do some pretty crazy things with the WikiServer. This one is pretty bizarre, and [...]]]></description>
			<content:encoded><![CDATA[<p>As I&#8217;ve been blogging about, I&#8217;ve been <a href="/blog/2008/04/05/a-web-developers-introduction-to-the-apple-wikiserver-part-1/">playing a lot</a> with Apple&#8217;s new WikiServer (or &#8220;Teams Server&#8221;) at work. We&#8217;re still evaluating what we&#8217;d like to use it for, but as part of the experiments, I&#8217;ve been finding myself having to do some pretty crazy things with the WikiServer. This one is pretty bizarre, and is probably not only very dangerous for the content of your group&#8217;s wiki and blog, but also almost certainly not a best-practice.</p>
<p>With that caveat out of the way, here&#8217;s how I managed to move all the pages in an Apple WikiServer group wiki and blog from one group to another.</p>
<h2>Dear God, please have a backup!</h2>
<p>Okay, step 1 is mundane, but seriously, please of please have a backup of your data before you do any of these things. To make a back up of your entire WikiServer&#8217;s data store, simply:</p>
<pre><kbd>sudo tar -cvzf <var>backup-file-name</var>.tgz /Library/Collaboration</kbd></pre>
<p>If anything goes wrong, you can restore from your backup just as simply:</p>
<pre><kbd>sudo tar -C /Library/Collaboration -xvzf <var>backup-file-name</var>.tgz</kbd></pre>
<p>Okay, with that out of the way, next make sure absolutely nobody is using any of the Group services for the group you are going to perform the move from, or to. People can work on other group&#8217;s wikis, it&#8217;s just the ones you&#8217;ll be touching you want people to avoid. You can enforce this with some Apache redirects, which is left as an exercise to the reader.</p>
<h2>Step 1: Rename or create a new Group in Workgroup Manager</h2>
<p>First, you need to either rename or create a new group in Workgroup Manager. If you make a new group, be sure to enable all the services that the old group used.</p>
<p>If you&#8217;re simply renaming a group, then you might not even have to go through this trouble. You merely need to change the group&#8217;s &#8220;Name&#8221; (as opposed to its &#8220;Short Name&#8221;) and then stop and start the Web Service from Server Admin to see the group&#8217;s name change. However, if you also want to change the group&#8217;s &#8220;Short Name&#8221; (i.e., the group&#8217;s POSIX group account symbolic name), then you will need to perform these steps.</p>
<p>Once you have the new group ready to go in Workgroup Manager and you have stopped and started your Web Service in Server Admin, continue to the next step.</p>
<h2>Step 2: rsync all your files from the old group to the new group</h2>
<p>This is simple. Just run:</p>
<pre><kbd>sudo rsync -avzE --progress /Library/Collaboration/Groups/<var>old-group</var>/ /Library/Collaboration/Groups/<var>new-group</var>/</kbd></pre>
<p>Note that the trailing slashes on the directory names in this command are quite important, as they tell <code>rsync</code> to take the <em>contents</em> of the first directory and place those items as the contents of the second directory. Without the trailing slashes, <code>rsync</code> will make extraneous directories for you, which Apple WikiServer won&#8217;t understand. See <code>man rsync</code> for more information.</p>
<h2>Step 3: Update the <code>plist</code>s for all your WikiServer pages in the new group</h2>
<p>Now, WikiServer has all the content of your old group but all of the internal references are wrong, since they still point to the old group. What you need to do is rewrite all those references so that they point to the new group address. The group references are stored in property list files. See my older blog entries for <a href="/blog/2008/04/08/a-web-developer’s-introduction-to-the-apple-wikiserver-part-2/">details about the filesystem structure of Apple&#8217;s WikiServer</a> data storage layout.</p>
<p>To do this is a relatively simple procedure. As root, do the following, and do it <em>carefully</em> because as root you can easily mess up (and there is no undo button on the command line!):</p>
<pre><kbd>sudo su -</kbd>
<kbd>cd /Library/Collaboration/Groups/<var>new-group</var></kbd>
<kbd>grep -ri "<var>old-group</var>" * | grep '^[^B]' | cut -d ':' -f 1 | grep 'plist$' | sort | uniq &gt; /tmp/<var>list_of_plist_files_to_edit</var></kbd>
<kbd>for i in `cat /tmp/<var>list_of_plist_files_to_edit</var>`; do sed -e 's/&lt;string&gt;groups\/<var>old-group</var>/&lt;string&gt;groups\/<var>new-group</var>/' $i &gt; $i.new; mv "$i.new" "$i"; chown teamsserver:teamsserver "$i"; chmod o-rwx "$i" done;</kbd></pre>
<p>In English, this means:</p>
<ol>
<li>Become root.</li>
<li>Change to the <code>/Library/Collaboration/Groups/<var>new-group</var></code> directory</li>
<li>Find all <code>plist</code> files that have the the string <var>old-group</var> in them, sort them, and write this list of files to the <code>/tmp/<var>list_of_plist_files_to_edit</var></code> file.</li>
<li>For each of the files listed in the <code>/tmp/<var>list_of_plist_files_to_edit</var></code>, find the text string <code>&lt;string&gt;groups/<var>old-group</var></code> and replace that text with <code>&lt;string&gt;groups/<var>new-group</var></code>, and save this change as the name of the file with <code>.new</code> appended. Finally, replace the original file with the file we modified, and give them the appropriate permissions.</li>
</ol>
<h2>Step 4: Create an Apache redirect to make sure no <acronym title="HyperText Markup Language">HTML</acronym> links are broken</h2>
<p>Okay, at this point your new group is up and running and it should be working. However, if you had any links at all in any of your group&#8217;s pages, they are now all broken because they still point to the old group. Rather than going through the <acronym title="HyperText Markup Language">HTML</acronym> itself and cleaning this up right now (because that&#8217;s very error-prone indeed, even with automated tools), it&#8217;s much easier to just tell Apache to redirect all requests for the old group to the new group.</p>
<p>To do this, edit the Apache configuration file of whatever Virtual Host you have been serving the WikiServer from. Most of the time, this will be at <code>/etc/httpd/sites/0000_any_80_.conf</code>.</p>
<p>The end of that file probably looks something like this::</p>
<pre>#       Include /etc/httpd/httpd_users.conf
#       Include /etc/httpd/httpd_directory.conf
        Include /etc/httpd/httpd_groups.conf
        Include /etc/httpd/httpd_teams_required.conf
        LogLevel warn
        ServerAlias *
&lt;/VirtualHost&gt;</pre>
<p>Right above these <code>Include</code> directives, simply add the following:</p>
<pre><kbd>        &lt;Location /groups&gt;
            &lt;IfModule mod_alias.c&gt;
                Redirect 301 /groups/<var>old-group</var> http://<var>your.server.address</var>/groups/<var>new-group</var>
            &lt;/IfModule&gt;
        &lt;/Location&gt;</kbd>
#       Include /etc/httpd/httpd_users.conf
#       Include /etc/httpd/httpd_directory.conf
        Include /etc/httpd/httpd_groups.conf
        Include /etc/httpd/httpd_teams_required.conf
        LogLevel warn
        ServerAlias *
&lt;/VirtualHost&gt;
</pre>
<p>There you have it. New Teams Server group, old group&#8217;s data.</p>
<h2>Caveats</h2>
<p>Note that this does <em>not</em> update any of the SQLite databases used to store things like revision history and so forth. These things are, for the most part, not really necessary to update but it would be ideal if the old <code>plist</code> revisions could be changed in there, too. That&#8217;s not so much more extra work, really, but I&#8217;ve found it typically unnecessary except in fringe cases, so I leave that as an exercise to the reader.</p>
<p>If you do this to your WikiServer and do not update the SQLite databases as well, just be mindful of that fact so that you&#8217;re not surprised if something goes wonky down the line.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2008/05/01/how-to-move-all-pages-in-an-apple-wikiserver-group-to-a-new-group/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using Calendars from the Command Line</title>
		<link>http://maymay.net/blog/2008/04/18/using-calendars-from-the-command-line/</link>
		<comments>http://maymay.net/blog/2008/04/18/using-calendars-from-the-command-line/#comments</comments>
		<pubDate>Sat, 19 Apr 2008 01:47:49 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[Geeky]]></category>
		<category><![CDATA[Tech/Computing]]></category>
		<category><![CDATA[Unix/Linux]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/?p=426</guid>
		<description><![CDATA[If you&#8217;re anything like me, you always have a terminal window open. One of the reasons I do this, of course, is because it&#8217;s fast. If I want to know anything at all about my computer, all I need do is type the question. The answer, because it&#8217;s always text-based, comes back immediately. I don&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re anything like me, you always have a terminal window open. One of the reasons I do this, of course, is because it&#8217;s <em>fast</em>. If I want to know anything at all about my computer, all I need do is type the question. The answer, because it&#8217;s always text-based, comes back immediately. I don&#8217;t have to wait for a window to open or for a pane to scroll. Everything comes at me from a single visual direction, the bottom of my terminal window.</p>
<p>However, there are some occasions when a text-based response to a complicated question isn&#8217;t very helpful because it requires so much extra work to understand. For me, the most common example of this sort of issue has always been in looking at time-based information, and more specifically, calendars. Whenever I&#8217;m on my machine, I almost always need to look at a calendar.</p>
<p>In the past, I used to go all the way over to iCal. Sure, I can do this using keyboard shortcuts only, but sometimes all I want is a quick answer to &#8220;what date is this upcoming Friday?&#8221; In situations like that, I&#8217;ve lately begun using the <code>cal</code> command, and my oh my, what a timesaver.</p>
<p><code>cal</code> is kind of like <code>man</code> for dates. Of course, you can get more info by saying <code>man cal</code> to your prompt. The <code>cal</code> program, installed by default on almost all UNIX-based systems (including Mac <acronym title="Operating System">OS</acronym> X), has a ton of useful options. However, most of the time, I don&#8217;t need more than a few.</p>
<p>For instance, let&#8217;s say I just want a calendar of the current month. I can get get a compact, simple month view instead of going to iCal by saying just <code>cal</code> at the command line:</p>
<pre><samp>Perseus:~ maymay$ </samp><kbd>cal</kbd>
<samp>     April 2008
Su Mo Tu We Th Fr Sa
       1  2  3  4  5
 6  7  8  9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30

</samp></pre>
<p>Other options let me ask other questions of <code>cal</code>. Easy, simple, fast. I like it.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2008/04/18/using-calendars-from-the-command-line/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How to import CVS code repositories into Git using `git cvsimport`</title>
		<link>http://maymay.net/blog/2008/04/15/how-to-import-cvs-code-repositories-into-git-using-git-cvsimport/</link>
		<comments>http://maymay.net/blog/2008/04/15/how-to-import-cvs-code-repositories-into-git-using-git-cvsimport/#comments</comments>
		<pubDate>Tue, 15 Apr 2008 09:06:24 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/?p=425</guid>
		<description><![CDATA[This should be straightforward, but it&#8217;s not. To import (not track, but just import) code from a remote CVS repository to a local git repository, you need to do the following: Be certain you have the git-core package installed on your system and that this package includes the git-cvsimport command. You can run git help [...]]]></description>
			<content:encoded><![CDATA[<p>This should be straightforward, but it&#8217;s not. To import (not <em>track</em>, but just import) code from a remote <acronym title="Concurrent Versions System">CVS</acronym> repository to a local git repository, you need to do the following:</p>
<ol>
<li>Be certain you have the git-core package installed on your system and that this package includes the <code>git-cvsimport</code> command. You can run <code>git help -a | grep cvsimport</code> to verify this.</li>
<li>Be certain you have the <code>cvsps</code> command-line tool installed. This does <em>not</em> come with the git suite of tools, so you&#8217;ll need to get it separately. If you&#8217;re a lazy Mac <acronym title="Operating System">OS</acronym> X user, like me, you can use MacPorts: <code>sudo port install cvsps</code>. Otherwise, get it from <a href="//www.cobite.com/cvsps/">the source</a>.</li>
<li>Prepare your <acronym title="Concurrent Versions System">CVS</acronym> login information for the remote server <em>before</em> you run <code>git cvsimport</code>. You need to do this so that the git tool will be able to log you in to the <acronym title="Concurrent Versions System">CVS</acronym> server automatically. The command for this looks like:
<pre>CVSROOT=:<var>cvs-login-method</var>:<var>cvs-user-name</var>@<var>cvs.server.name</var>:<var>/path/to/CVS/root</var> cvs login</pre>
<p> For example, if you&#8217;re pulling code from the anonymous <acronym title="Concurrent Versions System">CVS</acronym> server that runs on Drupal.org, you might use this: <code>CVSROOT=:pserver:anonymous@cvs.drupal.org:/cvs/drupal-contrib cvs login</code>. This command will prompt you for the password for the user you specified at the server you specified (for anonymous access, the password is almost always <code>anonymous</code>) and will hash this in the <code>~/.cvspass</code> file for future use by <acronym title="Concurrent Versions System">CVS</acronym></li>
<li>Finally, run the <code>git cvsimport</code> tool, and specify the proper options. Using the Drupal example above, your command might look like this:
<pre>git cvsimport -v -d :pserver:anonymous@cvs.drupal.org:/cvs/drupal-contrib contributions/modules/<var>module-name</var></pre>
<p> This would login to <code>cvs.drupal.org</code> using the <acronym title="Concurrent Versions System">CVS</acronym>&#8216;s <code>pserver</code> login method, provide the username <code>anonymous</code> and the password you specified in the previous step that is hashed in <code>~/.cvspass</code>, set the <acronym title="Concurrent Versions System">CVS</acronym> document root to <code>/cvs/drupal-contrib</code>, and pull the code located at <code>contributions/modules/<var>module-name</var></code> into the current working directory as a git repository.</li>
</ol>
<p>This works pretty nicely, and creates a git repository just as though you&#8217;d created it with <code>git init</code> in the current working directory.</p>
<p>If you get an error that looks like this:</p>
<pre>AuthReply: cvs [pserver aborted]: descramble: unknown scrambling method</pre>
<p>then you&#8217;ve most likely specified the <acronym title="Concurrent Versions System">CVS</acronym> document root incorrectly. Most notably, <code>git cvsimport</code> does not understand a <acronym title="Concurrent Versions System">CVS</acronym> document root wherein the password is specified in the document root <acronym title="Uniform Resource Locator">URL</acronym> itself. So, for example, <code>git cvsimport -d :pserver:<var>password</var>:<var>username</var>@<var>cvs.server.name</var>:<var>/path/to/CVS/root</var> <var>code/to/checkout</var></code> will not work. Omitting the password and the separating colon from the <acronym title="Uniform Resource Locator">URL</acronym> should fix it.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2008/04/15/how-to-import-cvs-code-repositories-into-git-using-git-cvsimport/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>HowTo: Use git for personal development when everyone else is using Subversion (part 2)</title>
		<link>http://maymay.net/blog/2008/03/28/howto-use-git-for-personal-development-when-everyone-else-is-using-subversion-part-2/</link>
		<comments>http://maymay.net/blog/2008/03/28/howto-use-git-for-personal-development-when-everyone-else-is-using-subversion-part-2/#comments</comments>
		<pubDate>Fri, 28 Mar 2008 08:20:36 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/2008/03/28/howto-use-git-for-personal-development-when-everyone-else-is-using-subversion-part-2/</guid>
		<description><![CDATA[When we left off, you had just finished transforming a remote Subversion repository into a git repository and optimizing it to save you some space. Now that you have a git repository, what do you do? First things first. Once you have an idea of what work you want to do, you should give yourself [...]]]></description>
			<content:encoded><![CDATA[<p>When we left off, you had just finished transforming a remote Subversion repository into a git repository and optimizing it to save you some space. Now that you have a git repository, what do you do?</p>
<p>First things first. Once you have an idea of what work you want to do, you should give yourself a space to do this work without disturbing anybody else&#8217;s work. Do this by making a new, personal branch. Unlike Subversion and some other centralized version control systems, git makes it possible to do make all kinds of changes to your repository, including making branches, and even save those changes without having to republish everything back to the central repository server at each step. In other words, if you thought Subversion branches were &#8220;cheap,&#8221; you&#8217;ll love git&#8217;s branches.</p>
<p>Also unlike Subversion, which stores its branches in completely separate pathnames, git keeps all branches in the same filesystem tree separated only with metadata (in <code>.git/refs/remotes</code> for remote branches and in <code>.git/refs/heads</code> for local branches, to be a bit more precise), so you don&#8217;t have to create lots of different directories for all your branches (unless you want to). With no branches defined, you&#8217;re working in the &#8220;master branch,&#8221; or &#8220;the trunk&#8221; by default.</p>
<pre><kbd>git branch</kbd>
<samp>* master</samp></pre>
<p>By saying <code>git branch</code> you ask git to print a list of all (local) branches. The one with the asterisk marks the current branch, the one you&#8217;re using at the moment you run the command. Since there are no branches, you&#8217;re currently in the &#8220;master&#8221; branch. But we don&#8217;t want to make changes here, we want to make changes in our own private branch, so we&#8217;ll make a new one.</p>
<pre>git checkout -b <var>new_branch_name</var></pre>
<p>This will create a new branch with the name <var>new_branch_name</var> and immediately switch to it. Notice that you&#8217;ve made absolutely no changes to the filesystem itself; only the git metadata has been altered. Saying <code>git branch</code> again will show you the change:</p>
<pre><kbd>git branch</kbd>
<samp>  master
* new_branch_name</samp></pre>
<p>Also note that since we haven&#8217;t comitted any changes, we don&#8217;t need a commit message (or &#8220;log message&#8221;) for creating this branch. We&#8217;ll add one later, when we need it. Now go ahead and write some code in your new branch. At any time, you can create a new branch in the same way you added the first. Each new branch is created at the <code>HEAD</code> (&#8220;latest&#8221;) revision of whatever branch you&#8217;re currently working in.</p>
<pre><kbd>git checkout -b <var>another_branch</var></kbd>
<samp>Switched to a new branch "<var>another_branch</var>"</samp>
<kbd>git branch</kbd>
<samp>  master
  new_branch_name
* another_branch</samp></pre>
<p>To switch back to any other branch, simply <code>git checkout</code> that branch again:</p>
<pre><kbd>git checkout master</kbd>
<samp>Switched to branch "master"</samp></pre>
<p>If you want to delete a branch you don&#8217;t like, that&#8217;s easy too:</p>
<pre><kbd>git branch -d <var>another_branch</var></kbd>
<samp>Deleted branch <var>another_branch</var></samp>.</pre>
<p>Keep in mind that throughout all of these branch creation and deletion actions, the only thing that&#8217;s being altered is the git metadata. That&#8217;s why it&#8217;s so cheap to create new branches. If you ever have a new idea you&#8217;re working on, it&#8217;s recommended that you create a branch for it, even if that branch is so short-lived it never gets published.</p>
<p>So you have a new local branch, and you&#8217;ve been working as you normally do for a few minutes, creating files, editting them, and so on. Running <code>git status</code> now will ask git to show you the changes you&#8217;ve made to your filesystem. If you&#8217;ve created any files in new directories that git doesn&#8217;t know about, it will simply report that directory. If you&#8217;ve made new files in directories git does know about, it will list all those files explicitly.</p>
<pre><kbd>git status</kbd>
<samp># On branch cartoon_contests
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#	sites/default/modules/cartoon_contests/
#	sites/default/modules/factiva/.factiva.module.swp
#	sites/default/modules/testfile
#	sites/default/settings.php
nothing added to commit but untracked files present (use "git add" to track)
</samp></pre>
<p>In the above sample output, I&#8217;m working on a new Drupal module for a web site. I&#8217;ve created a new directory, <code>sites/default/modules/cartoon_contests/</code> (note the trailing slash), and I have several untracked files. One is my <a href="//vim.org/">vim</a> swap file for a different module, <code>.factiva.module.swp</code>, one&#8217;s an unimportant <code>testfile</code>, and the last is the Drupal configuration file, <code>settings.php</code>.</p>
<p>The only thing I want to commit is the new <code>cartoon_contests</code> directory, and all the files within it. Like Subversion, I have to tell git that I want to <dfn>track</dfn> this directory, which is done simply by saying <code>git add cartoon_contests</code>. Unlike Subversion, future invocations of <code>git status</code> let me see everything that git is going to go in the next commit.</p>
<pre><kbd>git status</kbd>
<samp># On branch cartoon_contests
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	new file:   sites/default/modules/cartoon_contests/cartoon_contests.info
#	new file:   sites/default/modules/cartoon_contests/cartoon_contests.module
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#	sites/default/modules/factiva/.factiva.module.swp
#	sites/default/modules/testfile
#	sites/default/settings.php</samp></pre>
<p>The &#8220;Changes to be committed&#8221; section of the output is called the <dfn>staging area</dfn>, or the <dfn>index</dfn>. In this way, I can prepare all the changes I want to commit before I do so, making sure they&#8217;re perfect before I actually commit them to the git repository. At any time before I commit, I can make additional modifications, such as <code>git add</code>ing more files or directories, <code>git reset</code>ing to unstage all (or some) of my changes, etc. <code>git help reset</code> also has a number of handy explanations with examples for different things you might need to do at this point.</p>
<p>If you were using <code>svn:ignore</code>, equivalent functionality exists in git. Simply append file glob patterns, one per line, to the <code>$GIT_DIR/info/exclude</code> file in your git repository. Like so:</p>
<pre><kbd>echo -e "*.swp\nsites/default/settings.php" >> .git/info/exclude ; git status</kbd>
<samp># On branch cartoon_contests
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	new file:   sites/default/modules/cartoon_contests/cartoon_contests.info
#	new file:   sites/default/modules/cartoon_contests/cartoon_contests.module
#
</samp></pre>
<p>If you&#8217;ve got many of these, you can use <code>git svn show-ignore >> .git/info/exclude</code> to search through your old Subversion repository and look for any and all ignores, automatically adding them to git&#8217;s exclude list. (Checkout <a href="//tsunanet.blogspot.com/2007/07/learning-git-svn-in-5min.html">Tsuna&#8217;s blog entry on learning git</a> for more tips like this.)</p>
<p>Finally, after you&#8217;ve done some of your work and you&#8217;ve finished <dfn>staging</dfn> your changes, you&#8217;re ready to commit them to the repository. On the other hand, if you hate what you&#8217;ve done and want to undo it all, you can say <code>git reset --hard HEAD</code> to throw away all your local changes. To throw away changes to just a single file, just checkout that file again by saying <code>git checkout <var>filename</var></code>. This is the equivalent of Subversions <code>svn revert <var>filename</var></code> command.</p>
<p>Before you actually make your first commit, however, you should properly introduce yourself to git. You don&#8217;t have to do this because git will try to figure out who you are by itself (<a>details explained in detail here</a>), but you probably should at least create global defaults for your user (which git will store in <code>~/.gitconfig</code>). If you want to, you can also create per-repository defaults (which git will store in <code>.git/config</code>), or even system-wide defaults for all users of this computer (which git will store in <code>/etc/gitconfig</code>). To do so, say this:</p>
<pre><kbd>git config --global user.name "Your Full Name"
git config --global user.email "you@example.com"</kbd></pre>
<p>This will create the file <code>~/.gitconfig</code> if it doesn&#8217;t alreay exist and will write your name into it. You can also just edit the file directly yourself instead of using <code>git config</code> commands.</p>
<p>Like Subversion, committing will create a saved, fixed point-in-time that marks the changes you have made to your files. Like branches, commits are also very cheap in git, so go ahead and commit at any time you like. Remember to stage your files (by <code>git add</code>ing them), and then just <code>git commit</code>.</p>
<pre><kbd>git add <var>filepattern</var></kbd>
<kbd>git commit -m "My very frst git commit!"</kbd>
<samp>Created commit ef483c1: My very frst git commit!
 5 files changed, 58 insertions(+), 12 deletions(-)</samp></pre>
<p>If you forget to specify a commit log message (<code>-m "log message"</code>) on the command line, or if you want to enter a multi-line commit log, git will prompt you for it in your favorite <code>$EDITOR</code>. You can view a history, including all the log messages, for your project with <code>git log</code>. You can even the view logs in a number of pretty formats. Check <code>git help log</code> for more information.</p>
<p>If you want to change anything about the commit you just made, such as the author, you can just run <code>git commit</code> again with the <code>--amend</code> flag added to the command. Notice the typo in the commit log? Fixing it is really easy:</p>
<pre><kbd>git commit --amend -m "My very first git commit!"</kbd>
<samp>Created commit 88602f6: My very first git commit!
 5 files changed, 58 insertions(+), 12 deletions(-)</samp></pre>
<p>Finally, with your new code commited to your local git branch, it&#8217;s time to share that code with your colleagues who are (for some inexplicable reason) still using Subversion. This is also extremely simple. Just say <code>git svn dcommit</code>. (That&#8217;s right, <code><strong>d</strong>commit</code>, not just commit. I don&#8217;t know why….)</p>
<p>Not sharing your changes via Subversion, but with a patch instead? <code>git diff -p</code> will generate patches for you. See <code>git help diff-files</code> and look for the &#8220;GENERATING PATCHES WITH -P&#8221; section.</p>
<p>If you found this helpful, you may also enjoy an <a href="//cworth.org/hgbook-git/tour/">alternative tour for beginners from Carl Worth</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2008/03/28/howto-use-git-for-personal-development-when-everyone-else-is-using-subversion-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HowTo: Use git for personal development when everyone else is using Subversion (part 1)</title>
		<link>http://maymay.net/blog/2008/03/26/howto-use-git-for-personal-development-when-everyone-else-is-using-subversion-part-1/</link>
		<comments>http://maymay.net/blog/2008/03/26/howto-use-git-for-personal-development-when-everyone-else-is-using-subversion-part-1/#comments</comments>
		<pubDate>Wed, 26 Mar 2008 06:54:57 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/2008/03/26/howto-use-git-for-personal-development-when-everyone-else-is-using-subversion-part-1/</guid>
		<description><![CDATA[Let&#8217;s just jump into it. Using Mac OS X, first make sure you have the git core installed as well as the git-svn components. Unlike other version control systems, git is not one monolithic program but a collection of smaller utilities, and the Subversion conduits are a subset of these utilities. The git-Subversion utilities themselves [...]]]></description>
			<content:encoded><![CDATA[<p>Let&#8217;s just jump into it.</p>
<p>Using Mac <acronym title="Operating System">OS</acronym> X, first make sure you have the git core installed as well as the git-svn components. Unlike other version control systems, git is not one monolithic program but a collection of smaller utilities, and the Subversion conduits are a subset of these utilities. The git-Subversion utilities themselves depend on having the <code>Perl::Subversion</code> bindings installed for Perl 5.</p>
<p>For the lazy MacPorts user, simply run:</p>
<pre>sudo port install git-core +svn</pre>
<p>This will install the git-core, the git-svn packages, as well as all the documentation for git and any required dependencies you don&#8217;t already have. Note that the documentation (man pages) is installed in <code>/opt/local/man</code>, which may not be in your default <code>$MANPATH</code>, so be sure to add that directory if <code>man git</code> returns a &#8220;No manual entry for git&#8221; error.</p>
<p>Alternatively, if you don&#8217;t want to use MacPorts, you can <a href="//git.or.cz/#download">download a pre-compiled Mac <acronym title="Operating System">OS</acronym> X binary</a> that includes git, the git docs, and the git-svn package from the git web site that comes complete with a standard <acronym title="Graphical User Interface">GUI</acronym> installation procedure.</p>
<p>Next, initialize a new git repository that tracks a remote Subversion one. This allows you to work privately using git, but to collaborate with other people who are using Subversion. Running</p>
<pre>git svn init svn://my.svn.server/path/to/svn/repo <var>workingcopy</var></pre>
<p>will give you an empty git working copy named <var>workingcopy</var> configured to use the remote Subversion repository at <var>svn://my.svn.server/path/to/svn/repo</var>. This step is analogous to the need to run <code>svnadmin create <var>repo_db</var></code>, to initialize a new repository database (where all the file versioning information will be stored). Unlike Subversion, git&#8217;s distributed database means that the working copy itself is <em>also</em> the location of the repository database, so there&#8217;s no need to deal with two filesystem paths anymore.</p>
<p>Next, change directory to your working copy, and run</p>
<pre>cd <var>workingcopy</var>
git svn fetch</pre>
<p>to populate your new, empty git working copy (and repository) with all the files from the remote Subversion repository.</p>
<p>Now that you have filled your git repository with a lot of data, <e>if you want to</em>, you can now also save a significant chunk of disk space by repacking that data into a more single, efficient, native packed git archive format (a <code>.pack</code> file). The <code>git-repack -a</code> command is used to do this, and its manual page says:</p>
<blockquote><p>Instead of incrementally packing the unpacked objects, pack everything referenced into a single pack. Especially useful when packing a repository that is used for private development and there is no need to worry about people fetching via dumb protocols from it.</p></blockquote>
<p>According to <a href="//utsl.gen.nz/talks/git-svn/intro.html#howto-fetch-convert" title="An introduction to git-svn for Subversion/SVK users and deserters">some sources</a>, this can turn a <acronym title="353 Megabyte(s)">353MB</acronym> Subversion repository into <acronym title="31 Megabyte(s)">31MB</acronym> of git pack. Say:</p>
<pre><kbd>git repack -a -d -f</kbd>
<samp>Generating pack...
Counting objects: 284
Done counting 4475 objects.
Deltifying 4475 objects...
 100% (4475/4475) done
Writing 4475 objects...
 100% (4475/4475) done
Total 4475 (delta 1876), reused 0 (delta 0)
Pack pack-a115c320ff9c9968248bd250bdfea3110d0f0c1a created.
Removing unused objects 100%...
Done.
</samp></pre>
<p>to perform the compression. For even greater savings, increase the compression by stipulating a high <code>--window</code> option, such as <code>git repack -a -d -f --window=100</code>. (<code>--window</code> defaults to 10—the higher the window, the harder <code>git-repack</code> will try to compress your stuff.) This turned a <acronym title="36 Megabyte(s)">36MB</acronym> Subversion repository in one of my projects to a <acronym title="20 Megabyte(s)">20MB</acronym> git pack. As always, your mileage may vary.</p>
<p>Congratulations, you have transformed your old Subversion repository to a git repository. All that&#8217;s left to do now is to get to the coding. Perhaps start by making a local (cheaper than cheap!) git branch….</p>
<p>That was easy, right? Most things in git are, in fact, that easy. If you&#8217;ve never used other version control systems before, be grateful. If you have, you can breathe a sigh of relief. Still not convinced? Don&#8217;t take my word for it…<a href="//video.google.com/videoplay?docid=-2199332044603874737">ask Linus Torvalds</a> (or <a href="//video.google.com/videoplay?docid=-3999952944619245780">Randall Schwartz</a>).</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2008/03/26/howto-use-git-for-personal-development-when-everyone-else-is-using-subversion-part-1/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Mac OS X Desktop Background sets without iPhoto Albums</title>
		<link>http://maymay.net/blog/2008/03/22/mac-os-x-desktop-background-sets-without-iphoto-albums/</link>
		<comments>http://maymay.net/blog/2008/03/22/mac-os-x-desktop-background-sets-without-iphoto-albums/#comments</comments>
		<pubDate>Sun, 23 Mar 2008 04:24:26 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Tech/Computing]]></category>
		<category><![CDATA[Unix/Linux]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/2008/03/22/mac-os-x-desktop-background-sets-without-iphoto-albums/</guid>
		<description><![CDATA[One of the pleasures of using Mac OS X is that Apple&#8217;s often-elegant UI makes the easy things easy and gracefully reveals the complexity of any complicated tasks you may wish to perform. Except when you want to do something out of the ordinary, of course, in which case things get complicated a bit more [...]]]></description>
			<content:encoded><![CDATA[<p>One of the pleasures of using Mac <acronym title="Operating System">OS</acronym> X is that Apple&#8217;s often-elegant <acronym title="User Interface">UI</acronym> makes the easy things easy and gracefully reveals the complexity of any complicated tasks you may wish to perform. Except when you want to do something out of the ordinary, of course, in which case things get complicated a bit more quicky. Thankfully, Apple doesn&#8217;t seem to go to any great lengths to cripple users, and this comes in handy time and time again.</p>
<p>While playing with my Desktop Backgrounds (computer &#8220;wallpapers&#8221;) the other day, I ran into an issue like this. I wanted to make sets of wallpaper images that overlapped one another. This is easily doable with Apple&#8217;s iPhoto, since all iPhoto albums appear as Desktop Background sets by default. I could simply put together a bunch of iPhoto Albums containing the images I wanted, including overlapping images, and be done with it. iPhoto takes care not to duplicate the photo into every album so space on my hard drive would not have been wasted.</p>
<p>But what if I didn&#8217;t want to use iPhoto? If I just have a bunch of image files on my disk in folders, how can I make overlapping sets? The solution is as simple as a Unix symbolic link&mdash;with a catch: <em>only a symbolic link with an absolute path would work</em>.</p>
<p>At first, I tried to simply use a standard Mac <acronym title="Operating System">OS</acronym> X &#8220;alias,&#8221; but that didn&#8217;t work. My MacBook Pro wouldn&#8217;t follow the alias file to the original file when trying to display the wallpaper. Then I tried a simple symlink from one file to another, but again it didn&#8217;t work.</p>
<p>Luckily, then I tried dragging the file into my terminal window, which automatically listed the full POSIX pathname of my image. This, surprisingly, worked. So it turns out that the Desktop &amp; Screen Saver System Preference pane requires an absolute path to be specified if it&#8217;s to follow symlinks for creating wallpaper sets organized by folders. Go figure.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2008/03/22/mac-os-x-desktop-background-sets-without-iphoto-albums/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>No-Framework Ruby on the Web using eRuby on Mac OS X</title>
		<link>http://maymay.net/blog/2007/10/25/no-framework-ruby-on-the-web-using-eruby-on-mac-os-x/</link>
		<comments>http://maymay.net/blog/2007/10/25/no-framework-ruby-on-the-web-using-eruby-on-mac-os-x/#comments</comments>
		<pubDate>Thu, 25 Oct 2007 05:00:16 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[HOWTO]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Tech/Computing]]></category>
		<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[Web Design]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/archives/2007/10/25/no-framework-ruby-on-the-web-using-eruby-on-mac-os-x/</guid>
		<description><![CDATA[I have a suspicion that there are a lot of web developers out there who, like me, are eager to start learning more about Ruby but who are stunted by the incredible amount of unfamiliar conventions that are used in Rails. For many of us, our first introduction to Ruby was (or is) through Rails [...]]]></description>
			<content:encoded><![CDATA[<p>I have a suspicion that there are a lot of web developers out there who, like me, are eager to start learning more about <a href="//ruby-lang.org/">Ruby</a> but who are stunted by the incredible amount of unfamiliar conventions that are used in <a href="//rubyonrails.com/">Rails</a>. For many of us, our first introduction to Ruby was (or is) through Rails and the challenge of learning <em>both</em> Ruby and Rails at once should not be underestimated; frankly it&#8217;s damn hard.</p>
<p>Thankfully, there&#8217;s an easier way. Especially if you&#8217;re accustomed to &#8220;old-school&#8221; development workflows that you learned through, say, <acronym title="PHP Hypertext Preprocessor; an HTML-embedded scripting language">PHP</acronym> or perhaps Perl scripting, then ditching Rails and starting purely with Ruby might be the way to go. Doing things on your own without the &#8220;magic&#8221; of Rails will let you learn Ruby in a simple, yet fully-featured environment, much like the way you might have learned classic <acronym title="Common Gateway Interface">CGI</acronym> programming.</p>
<p>Specifically, by using <a href="//eruby.info/">eRuby</a>, the Embedded Ruby interpreter, you can make Ruby web development feel just like <acronym title="PHP Hypertext Preprocessor; an HTML-embedded scripting language">PHP</acronym> development. Install it, upload an <acronym title="HyperText Markup Language">HTML</acronym> file with some embedded Ruby code in it, and—voila—you have a single-page web application.</p>
<h3>Why this tutorial?</h3>
<p><a href="http://www.hiveminds.co.uk/node/3094">Hivemind&#8217;s Getting Started with Ruby on the Web</a> is an excellent resource that described this process from start-to-finish for Windows users. In fact, it was after finding that article that I realized web development with Ruby didn&#8217;t have to be governed by Rails and, being a web developer like the authors of <cite>Hiveminds</cite>, I wanted an easy way to use my Ruby knowledge on the Web.</p>
<p>However, I couldn&#8217;t find any similar tutorial or walkthrough for those of us who use Macs. Even the Linux walkthroughs are lacking (or at least my Googling skill for them is). After spending a little while successfully getting eRuby set up on my Mac running Mac <acronym title="Operating System">OS</acronym> X 10.4 Tiger, I thought I&#8217;d share what I learned with others, so I wrote this article. Its content mirrors the one from Hiveminds to a great degree but focuses on getting eRuby installed on Mac <acronym title="Operating System">OS</acronym> X instead of Windows (obviously). I imagine these instructions should be pretty similar if not identical for any other *nix-like platform.</p>
<h3>The Setup</h3>
<p>Getting eRuby installed and configured with your web server is actually pretty straightforward and won&#8217;t take an experienced web developer much time at all. All we&#8217;re going to need is the <a href="//httpd.apache.org/">Apache web server</a> and the <a href="//ruby-lang.org/">Ruby programming language</a> to start, both of which are already pre-installed on Mac <acronym title="Operating System">OS</acronym> X 10.4 Tiger. (And in Mac <acronym title="Operating System">OS</acronym> X 10.5 Leopard, Apple is even <a href="/blog/archives/2007/10/18/the-10-geekiest-leopard-features-i-will-probably-love/#li-1">shipping new Macs with Ruby On Rails preconfigured</a>, but that&#8217;s a subject for another time.) However, Apple typically ships an older copy of Ruby than is readily available, so you might choose to use a newer version of Ruby that you download yourself.</p>
<p>The easiest way to get a copy of eRuby (and an updated Ruby, if you want it) is with a package manager such as <a href="//macports.org/">MacPorts</a>. With MacPorts installed (which is a simple, standard package installation downloadable from the MacPorts home page), simply run</p>
<pre><kbd>sudo port install eruby</kbd></pre>
<p>from your terminal to download the latest stable Ruby and eRuby in one fell swoop. After this runs, you&#8217;ll have a new Ruby in <code>/opt/local/bin/ruby</code> and an eRuby in <code>/opt/local/bin/eruby</code>. Alternatively, of course, you could compile and install eRuby yourself. <a href="//eruby.info/" title="Scroll to the 'How do I get eRuby?' section.">Instructions for that</a> are on the eRuby homepage.</p>
<p>As a quick test to see if everything is installed and working correctly, create a plain text file with your favorite editor that contains the following code:</p>
<pre><code class="ruby">Hello world! The time is now &lt;%= Time.now %&gt;.</code></pre>
<p>All this does is print out a &#8220;Hello world!&#8221; greeting and then announces the current time (as reported by your system clock, of course).</p>
<p>If you named the above file <var>helloworld.rhtml</var> then you can feed this file to the <code>eruby</code> interpreter as follows:</p>
<pre><kbd>eruby helloworld.rhtml</kbd></pre>
<p>Note that the file extension doesn&#8217;t actually matter. You could use <code>.erb</code>, if you like, or any other arbitrary file extension. The file extension is, as you&#8217;ll see later, only used for telling Apache which kind of file it is. So once you come up with file extension you like, stick with it. The standard file extensions are either <code>.rhtml</code> or <code>.erb</code>, so I&#8217;d recommend using one of those. (I prefer <code>.erb</code>, myself, since I don&#8217;t necessarily only want to create <acronym title="HyperText Markup Language">HTML</acronym> pages. I might want to create <acronym title="eXtensible Markup Language">XML</acronym> documents like news feeds or even <acronym title="eXtensible Markup Language">XML</acronym> databases, so <code>.erb</code> seems a more reasonable file name extension, though most of the eRuby documentation uses <code>.rhtml</code>.)</p>
<p>If things worked properly, you should see output similar to the following:</p>
<pre><samp class="plaintext">Hello world! The time is now Wed Oct 24 21:58:54 -0400 2007.</samp></pre>
<h3>Serve it up!</h3>
<p>Now that eRuby is installed and working, the next step is to set it up as a <acronym title="Common Gateway Interface">CGI</acronym> so that when your web server (Apache, in my case) fetches the file it will first feed it through eRuby for processing before sending it back to the browser. The simplest way to do this is to configure Apache to use a specific directory somewhere on your filesystem as a <acronym title="Common Gateway Interface">CGI</acronym> directory—that is, a directory whose contents are all treated as <acronym title="Common Gateway Interface">CGI</acronym> programs. You do this via Apache&#8217;s <a href="//httpd.apache.org/docs/1.3/mod/mod_alias.html#scriptalias" title="Documentation for Apache's ScriptAlias directive."><code>ScriptAlias</code></a> directive.</p>
<p>Conveniently, standard installations of Mac <acronym title="Operating System">OS</acronym> X already come with a <acronym title="Common Gateway Interface">CGI</acronym> directory. It&#8217;s located at <code>/Library/WebServer/CGI-Executables</code>. This directory is just like any other, except that Apache treats it specially. It treats it specially because Apache&#8217;s configuration file, <code>/etc/httpd/httpd.conf</code> contains a line of text that reads as follows. (On a standard installation of Mac <acronym title="Operating System">OS</acronym> X client, this is line 671 of the file.)</p>
<pre><code class="httpd-conf">ScriptAlias /cgi-bin/ "/Library/WebServer/CGI-Executables/"</code></pre>
<p>This line basically just tells apache, &#8220;Treat every file in the <code>/Library/WebServer/CGI-Executables</code> directory as though it were a <acronym title="Common Gateway Interface">CGI</acronym> program.&#8221; So, since that&#8217;s how we&#8217;re treating eRuby, we&#8217;re going to want to put our <code>eruby</code> binary in that directory. However, we don&#8217;t actually want to make copies of the binary. Having too many copies of a program on your system can easily get confusing. So instead, we&#8217;ll make a symbolic link (or an alias to use the classic Mac terminology) to the binary.</p>
<pre><kbd>ln -s /opt/local/bin/eruby /Library/WebServer/CGI-Executables/eruby</kbd></pre>
<p>With our <code>eruby</code> <acronym title="Common Gateway Interface">CGI</acronym> executable in the proper place for Apache to find it, we can now tell Apache which files we want it to send to this program. We do this using the <a href="//httpd.apache.org/docs/1.3/mod/mod_mime.html#addhandler" title="Documentationf or Apache's AddHandler directive."><code>AddHandler</code></a> and <a href="//httpd.apache.org/docs/1.3/mod/mod_actions.html#action" title="Documentation for Apache's Action directive."><code>Action</code></a> directives.</p>
<p><code>AddHandler</code> simply tells Apache to treat files with a certain extension in a certain way. For instance, you can say something like, &#8220;Treat all files ending in <code>.php</code> as <acronym title="PHP Hypertext Preprocessor; an HTML-embedded scripting language">PHP</acronym> scripts.&#8221; Similarly, you can (and will) tell Apache, &#8220;Treat all files ending in <code>.rhtml</code> or <code>.erb</code> as eRuby <acronym title="Common Gateway Interface">CGI</acronym> pages.&#8221;</p>
<p>To do this, we add the following line to our <code>/etc/httpd/users/<var>username</var>.conf</code> file somewhere inside the <code>&lt;Directory&gt;</code> and <code>&lt;/Directory&gt;</code> block. Naturally, replace <var>username</var> with, of course, your <a href="//docs.info.apple.com/article.html?artnum=106824" title="Apple KBase Article number 106824 describes use short names in more detail.">Mac <acronym title="Operating System">OS</acronym> X user&#8217;s short name</a>:</p>
<pre><code class="httpd-conf">AddHandler rubypage .erb .rhtml</code></pre>
<p>Again, this just tells Apache that files ending in <code>.erb</code> and <code>.rhtml</code> should be treated the same way other <code>rubypage</code>s are treated. But how are eRuby pages supposed to be treated? They&#8217;re supposed to be handed off to the eRuby program, of course, so we need an <code>Action</code> directive that applies to the <code>rubypage</code> handler we just defined.</p>
<p>Right below the above line, add the following line, too:</p>
<pre><code class="httpd-conf">Action rubypage /cgi-bin/eruby</code></pre>
<p>This line tells Apache that any file that it is treating as a &#8220;rubypage&#8221; file should be sent to the program at the <acronym title="Uniform Resource Locator">URL</acronym> accessible at <code>/cgi-bin/eruby</code>, which we&#8217;ve defined earlier to be our symbolic link to the <code>eruby</code> interpreter.</p>
<p>Your completed user-specific Apache configuration file should now look something like this:</p>
<pre><code class="httpd-conf">&lt;Directory "/Users/<var>username</var>/Sites/"&gt;
&hellip;
    # Let eRuby files get parsed through the proper <acronym title="Common Gateway Interface">CGI</acronym> binary
    AddHandler rubypage .erb .rhtml
    Action rubypage /cgi-bin/eruby
&lt;/Directory&gt;</code></pre>
<h3>Are You Being Served?</h3>
<p>That&#8217;s it, everything should now be in place. To make sure, move your earlier <code>helloworld.rhtml</code> file into your user&#8217;s <code>Sites</code> folder, and now simply point your browser to <code>http://localhost/~<var>username</var>/helloworld.rhtml</code> (again, replacing <var>username</var> with your Mac <acronym title="Operating System">OS</acronym> X user short name, of course). Congratulations, you&#8217;re serving up Ruby-coded applications via eRuby.</p>
<h3>Additional Reading</h3>
<p>This is just the set up, of course. Now the real fun begins: learning Ruby. Here are some suggested places to start.</p>
<ul>
<li><a href="//www.ruby-doc.org/docs/ProgrammingRuby/html/web.html">Programming Ruby: Ruby and the Web</a> — A chapter out of the free book <cite>Programming Ruby</cite> all about Ruby as a <acronym title="Common Gateway Interface">CGI</acronym> programming language.</li>
<li><a href="//hiveminds.co.uk/node/3189">Hiveminds: eRuby: How to use Ruby <acronym title="Common Gateway Interface">CGI</acronym> and ERB templating for Web Pages</a> — a quick&#8217;n'dirty article explaining the basics of using Ruby on web pages in classic <acronym title="Common Gateway Interface">CGI</acronym> style where program logic and <acronym title="HyperText Markup Language">HTML</acronym> templates are kept separated, as opposed to classic <acronym title="PHP Hypertext Preprocessor; an HTML-embedded scripting language">PHP</acronym> style, where the two are mingling together on one page.</li>
<li><a href="//coolnamehere.com/geekery/ruby/web/cgi.html">COOLNAMEHERE: Simple Ruby <acronym title="Common Gateway Interface">CGI</acronym></a> — Like the Hiveminds example above, another quick&#8217;n'dirty Ruby <acronym title="Common Gateway Interface">CGI</acronym> how-to.</li>
<li><a href="//ruby-doc.org/stdlib/libdoc/cgi/rdoc/index.html">cgi: Ruby Standard Library Documentation</a> — Ruby&#8217;s standard library contains a rich set of features, and the <acronym title="Common Gateway Interface">CGI</acronym> objects are among them. They are well-documented in the official Ruby Documentation Project.</li>
</ul>
<p>Naturally, feel free to leave comments if you have more resources that you found helpful.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2007/10/25/no-framework-ruby-on-the-web-using-eruby-on-mac-os-x/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>The 10 Geekiest Leopard Features I Will Probably Love</title>
		<link>http://maymay.net/blog/2007/10/18/the-10-geekiest-leopard-features-i-will-probably-love/</link>
		<comments>http://maymay.net/blog/2007/10/18/the-10-geekiest-leopard-features-i-will-probably-love/#comments</comments>
		<pubDate>Thu, 18 Oct 2007 15:45:59 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[AppleScript]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Security & Privacy]]></category>
		<category><![CDATA[Tech News]]></category>
		<category><![CDATA[Tech/Computing]]></category>
		<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/archives/2007/10/18/the-10-geekiest-leopard-features-i-will-probably-love/</guid>
		<description><![CDATA[This is already horribly old news, and by old I mean several days ago since that&#8217;s about as fast as it takes technology news to grow old, but Apple is releasing Mac OS X 10.5 &#8220;Leopard&#8221; at the end of this month. Apple is calling this release a &#8220;major upgrade,&#8221; and indeed Apple has rarely [...]]]></description>
			<content:encoded><![CDATA[<p>This is already horribly old news, and by old I mean several days ago since that&#8217;s about as fast as it takes technology news to grow old, but Apple is releasing Mac <acronym title="Operating System">OS</acronym> X 10.5 &#8220;Leopard&#8221; at the end of this month. Apple is calling this release a &#8220;major upgrade,&#8221; and indeed Apple has rarely made its users wait so long between operating system releases as they have done between Tiger (Mac <acronym title="Operating System">OS</acronym> X 10.4) and Leopard. So, I&#8217;m already excited.</p>
<p>But then today I was glossing over <a href="//apple.com/macosx/features/300.html">Apple&#8217;s featured features list</a> and I got even more excited. There are the usual, largely meaningless, fluff updates that are nice for Joe Schmo or his mother, but that power users simply don&#8217;t care about, like the new iChat support for animated buddy icons, but the list is also chock-full of really cool, really <em>useful</em> features.</p>
<p>What&#8217;s interesting is that a good deal of these features aren&#8217;t really new features at all. For instance, if you knew how to manipulate the NetInfo database on your Mac, you could already share any folder via Apple&#8217;s &#8220;Personal File Sharing&#8221; feature. (Here&#8217;s a <a href="http://www.macosxhints.com/article.php?story=20011108161839416">Mac <acronym title="Operating System">OS</acronym> X Hints hint explaining how to do it</a>.) In Leopard, however, Apple claims that this functionality is now integrated straight into a folder&#8217;s Get Info… window. If it works as smoothly as Apple claims, this is finally going to bring Mac <acronym title="Operating System">OS</acronym> X (client) into decent competition with Windows XP Professional in terms of <acronym title="Graphical User Interface">GUI</acronym>-level power-user features.</p>
<p>However, while all of these features are really cool, here&#8217;s a list of the ten geekiest features I will probably absolutely love, for one reason or another.</p>
<ul>
<li id="li-1"><strong>Ruby on Rails, out of the box</strong> — <em>The</em> hot thing in web development right now is Ruby on Rails. Macs have already been the best personal desktop and web development platform because they have built-in support for the Apache web server and a host of other features, but now they will come with a ready-to-roll installation of Ruby on Rails, sporting Mongrel and (better yet) Capistrano! Specifically with the addition of Capistrano, which is terribly undersold as simply a Ruby on Rails deployment platform, these UNIX-y &#8220;toolbox&#8221; items are bound to make Macs that much more useful right out of the box.</li>
<li id="li-2"><strong>Safari&#8217;s full history search</strong> — As their recent public partnerships with Google have shown, Apple is very clearly invested in search technologies. Spotlight gets a huge number of improvements in Leopard, but none which I think are going to be more useful to more people than this one: spotlight searches on the full text of each web page in your visited history list. That&#8217;s just awesome. Also awesome: using spotlight as a calculator and as a dictionary, which also shows just how Google-like Apple is trying to be. (<a href="http://www.google.com/help/cheatsheet.html">Google also lets you ask it arithmetic questions and a dictionary</a>.)</li>
<li id="li-3"><strong>Wikipedia articles in Dictionary.app</strong> — I <em>love</em> Wikipedia because it&#8217;s one of the fastest ways to get (relatively) reliable information quickly. Now that Dictionary.app has built-in integration with Wikipedia, imagine the possibilities for getting that knowledge instant-gratification craving fixed. Apple has not yet announced this capability, but I can easily envision a scenario where all Cocoa text fields are instantly &#8220;wikified&#8221; (with text that matches Wikipedia articles highlighted) much in the same way that current Cocoa text fields allow you to right-click on a misspelled word and have it corrected by Dictionary.app.</li>
<li id="li-4"><strong><a href="http://www.apple.com/macosx/features/300.html#security">Application-based firewall</a></strong> — In classic Apple fashion, functionality that was previously available via third-party additions is now available from Apple itself. In this case, I have to wonder how well Apple&#8217;s updates to its firewall will obviate the need for <a href="http://www.obdev.at/products/littlesnitch/index.html">Little Snitch</a>, which is basically an application-based firewall, too, and a good one at that.</li>
<li id="li-5"><strong>Built-in <em>guest</em> log-in account</strong> — If you&#8217;re as paranoid about security as I am, you&#8217;ve already created a special, limited-access user on your system (called Guest or Visitor or whatever) and whenever friends are over, you tell them to use that account instead of your own. Now in Leopard, Apple has gone through the trouble of setting this up for us already. A small change that is going to have a big impact.</li>
<li id="li-6"><strong>Scriptable System Preferences &amp; applications</strong> — With AppleScript, you can automate the things your computer does with scripts, as long as those things are &#8220;scriptable.&#8221; In previous versions of Mac <acronym title="Operating System">OS</acronym> X, huge gaping holes of what things shipped by Apple were scriptable existed, causing me (personally) some really annoying headaches. AppleScript <acronym title="Graphical User Interface">GUI</acronym> scripting helped me get around many of those roadblocks, but now it seems Apple is finally filling in some of the most notorious gaps in this functionality with scriptable System Preferences. Yay!</li>
<li id="li-7"><strong>Automator workflow variables</strong> — Automator brings the power of AppleScript I just mentioned to more people with a completely graphic programming environment. There is no need to open up a text document and write AppleScript code because Automator lets you create a script (called a Workflow in Automator jargon) using your mouse by dragging and dropping <dfn>actions</dfn> into the order you want them to be performed. It&#8217;s very slick, but until now it&#8217;s been very limited. With Leopard, Apple is beefing up Automator so that it includes things like variables, basic programmatic capability that was sorely lacking before. (Also majorly cool: a command-line utility to access Automator!)</li>
<li id="li-8"><strong><a href="http://www.apple.com/macosx/features/300.html#finder">Finder.app&#8217;s path bar</a></strong> — Every serious Mac user knows that the Finder needs a lot of help. Now, it&#8217;s getting some. Something the Windows Explorer has had forever (as had every desktop environment for Linux, of course) is a visual cue to show you where in your filesystem tree a given folder is located when you are viewing said folder. Now the Finder gains this capability (though Apple&#8217;s description implies that it&#8217;s going to be off by default) with what Apple is calling a &#8220;Path Bar&#8221;. Finally!</li>
<li id="li-9"><strong>Cocoa and scripting bridges</strong> — Even though no one really seems to know about it, it has long been possible for languages other than AppleScript to do things like send Apple Events to Mac <acronym title="Operating System">OS</acronym> X applications. Specifically, Ruby and JavaScript, two of the most well-known web development languages in existence, can already do this with a single ScriptingAddition (OSAX). But now Apple is making this functionality a central feature <em>and</em> fully extending it to their Objective-C (and Cocoa) language and applications such as Xcode and Interface Builder. This means people like me will have a shallower learning curve before we&#8217;re able to create full-fledged, native Mac <acronym title="Operating System">OS</acronym> X applications. Now <em>that&#8217;s</em> exciting!</li>
<li id="li-10"><strong>Xcode 3 refactoring</strong> — This is something you kind of have to see to believe. I got the opportunity to see it demoed at Apple&#8217;s Leopard Tech Talks last year and I was really excited by it. With the new Xcode, Apple&#8217;s development <acronym title="Integrated Drive Electronics">IDE</acronym>, you can do away with find-and-replace searches for things like renaming functions because Xcode understands what parts of your code are what structures and, when you tell it to &#8220;change the function named myFunction to myNewFunction,&#8221; it&#8217;ll only find-and-replace <em>function names</em> instead of every instance of the string &#8220;myFunction.&#8221; That&#8217;s pretty big, and if it were available for more languages, it&#8217;s <em>almost</em> enough to make me ditch <code>vim</code>.</li>
</ul>
<p>So there you have it. Ten features you might not have already known about that are some of the most promising features I can see in Leopard. And I didn&#8217;t even get into Wide-Area Bonjour, which could make services like DynDNS or No-<acronym title="Internet Protocol">IP</acronym> a thing of the past (and which I still want to learn more about), or the new Terminal application (finally with tabs!), or even the multiple user certificates for S/MIME encrypted email.</p>
<p><ins datetime="2007-10-24T15:04-0500"><strong>Note:</strong> One of the least known security features available on Mac <acronym title="Operating System">OS</acronym> X is also possibly one of the best, and the simplest. Evidently, <a href="http://developer.apple.com/documentation/MacOSX/Conceptual/universal_binary/universal_binary_diffs/chapter_3_section_6.html">all Intel-based Macs are shipped with the <acronym title="eXecute Disable; a feature of modern Intel chipsets that prevent execution of memory from the stack">XD</acronym> (<acronym title="Also Known As">aka</acronym>. <acronym title="No eXecute; a feature of AMD's modern chipsets that prevent execution of memory from the stack">NX</acronym>, <acronym title="Also Known As">aka</acronym>. <acronym title="Data Execution Prevention; Micosoft Windows's supporting implementation of Intel's Execute Disable bit">DEP</acronym>) bit turned on</a>—and thankfully there doesn&#8217;t seem to be any way for users to turn it off. However, this isn&#8217;t a silver bullet and if you want to learn why you should check out this excellent <a href="//anandtech.com/cpuchipsets/showdoc.aspx?i=2239">Anandtech article: <cite>A Bit About the <acronym title="No eXecute; a feature of AMD's modern chipsets that prevent execution of memory from the stack">NX</acronym> Bit</cite></a>.</ins></p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2007/10/18/the-10-geekiest-leopard-features-i-will-probably-love/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Moving personal data from one Mac to another</title>
		<link>http://maymay.net/blog/2007/09/13/moving-personal-data-from-one-mac-to-another/</link>
		<comments>http://maymay.net/blog/2007/09/13/moving-personal-data-from-one-mac-to-another/#comments</comments>
		<pubDate>Thu, 13 Sep 2007 18:26:43 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[Geeky]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Tech/Computing]]></category>
		<category><![CDATA[Unix/Linux]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/archives/2007/09/13/moving-personal-data-from-one-mac-to-another/</guid>
		<description><![CDATA[I recently purchased a new iMac. It&#8217;s aluminum. And glass. And shiny. And it&#8217;s so much faster than my old G4 workstation I feel a little bit like I&#8217;ve just come out of the stone age. Anyway, the experience of moving one&#8217;s data from one machine to another is always a bit of a hassle. [...]]]></description>
			<content:encoded><![CDATA[<p>I recently purchased a new iMac. It&#8217;s aluminum. And glass. And shiny. And it&#8217;s so much faster than my old G4 workstation I feel a little bit like I&#8217;ve just come out of the stone age.</p>
<p>Anyway, the experience of moving one&#8217;s data from one machine to another is always a bit of a hassle. There are so many little things you&#8217;re sure you&#8217;ve forgotten, preferences you don&#8217;t want to have to recreate, and small gotchas that, if you&#8217;re not careful, will mean you&#8217;ve lost something like your old email or your contacts—sometimes for good.</p>
<p>Thankfully, with a remarkably few easy planning steps, a lot of this trouble can be avoided all together. Much of this is thanks to the brilliant architecture of Mac <acronym title="Operating System">OS</acronym> X, which does a superb (though not perfect) job of separating data from applications. The other major benefactor of this kind of easy transition is server-based data stores, or hosted services (even if those services are ones I&#8217;ve hosted myself).</p>
<p>So here&#8217;s what I wanted to move over from my old mac to my new one:</p>
<ul>
<li>Personal documents, pictures, movies, and music, etc.</li>
<li>Preferences for all applications, such as my dock layout, the Finder&#8217;s and Mail&#8217;s toolbar button arrangements, and so on.</li>
<li>PIM databases, such as my Address Book contacts, iCal calendars, my email, and the like.</li>
</ul>
<p>This could really be a much longer list, especially if I were going to name every single item of personal importance. Nevertheless, each item falls into one of these three main categories of <em>stuff</em> that I want to move.</p>
<p>The first time you turn on a new Mac it will ask if you want to transfer your data from your old computer to your new computer. It does this using the Migration Assistant application located in your Mac&#8217;s <code>/Applications/Utilities</code> folder. While this works well for the most part, I&#8217;ve seen this program fail one too many times—especially for cross-architecture, PPC to Intel, transfers—that I&#8217;m simply not a fan of using it. Besides, as you&#8217;ll see in a moment, it&#8217;s trivially easy to do all of that yourself.</p>
<p>Of course, all of your personal information should be somewhere in your Home folder. You <em>could</em> just copy the entire directory from one Mac to the other, but you&#8217;ll probably end up deleting some (albeit probably non-critical) items from your new machine. When you drag-and-drop in the Finder, the Finder first removes anything of the same name on the destination as the source of the transfer. This is not what you want.</p>
<p>So here&#8217;s how I dealt with moving each type of item, <strong>after ensuring I had a good backup</strong>:</p>
<h3 id="transferring-personal-documents">Transferring personal documents</h3>
<p><code>rsync</code> is a godsend for any situation where you want to ensure that you&#8217;re copying files from one location to another. It compares the contents of folders and, by default, <em>only adds missing items</em> to the destination while leaving everything else alone. It also overwrites identically-named files on the destination with files from the source.</p>
<p>To use <code>rsync</code>, I first needed to turn on the destination Mac&#8217;s &#8220;Remote Login&#8221; feature; this turns on the <acronym title="Secure SHell">SSH</acronym> server. (Find this in System Preferences &rarr; Sharing &rarr; Services.) Next, simply issue this relatively simple command at the command line, from your home directory:</p>
<pre>rsync -aEve ssh Documents <var>UserShortName</var>@<var>DestinationMac</var>:Documents</pre>
<p>This tells <code>rsync</code> to copy files from the local machine&#8217;s <code>Documents</code> directory to the <var>DestinationMac</var>&#8216;s <code>Documents</code> directory in archive mode (the <code>-a</code> option), which preserves numerous file meta-data such as its modification times and access permissions, along with the file&#8217;s extended attributes and resource forks, if any exist (<code>-E</code>), reporting verbosely (<code>-v</code>) as it does so, executing over <acronym title="Secure SHell">SSH</acronym> (<code>-e ssh</code>). The <var>UserShortName</var> is the <var>DestinationMac</var>&#8216;s user short name, obviously, and the <var>DestinationMac</var> is either its hostname (such as <code>mynewmacintosh.local</code>) or its <acronym title="Internet Protocol">IP</acronym> address (such as <code>192.168.0.2</code>).</p>
<p>I repeated the above step for the Desktop, Movies, Music, Pictures, Public, and Sites folders. Most of my music is actually on an external hard drive, so that was of course a cinch, and <code>rsync</code> took care of the rest.</p>
<h3 id="transferring-preferences">Transferring preferences</h3>
<p>Mac <acronym title="Operating System">OS</acronym> X stores its user-specific preferences in each user&#8217;s home <code>Library/Preferences</code> folder. The set up is elegant and beautifully implemented. Just like the folders above, I could have simply <code>rsync</code>&#8216;ed my preferences over, but I wanted to be more selective. So I simply scrolled through the list finding the preference files for the applications I still use and copied them over. I used the Finder&#8217;s drag-and-drop, but you could use whatever method you want.</p>
<p>These files are named in reverse-<acronym title="Domain Name System or Domain Name Server">DNS</acronym> style notation, so for instance, my Mail preferences were stored in the file <code>com.apple.mail.plist</code>.</p>
<p>This was a super-simple step.</p>
<h3 id="transferring-pim-databases">Transferring PIM databases</h3>
<p>Like preferences, user-specific data is often stored in that user&#8217;s home <code>Library/Application Support</code> folder. Inside that folder is a folder for each application that has some data to store. All of iCal&#8217;s information, for example, is thus stored in your home <code>Library/Application Support/iCal</code> folder.</p>
<p><code>rsync</code> to the rescue again:</p>
<pre>rsync -aEve ssh Library/Application\ Support/iCal "<var>UserShortName</var>@<var>DestinationMac</var>:Library/Application\ Support/iCal"</pre>
<p>In this case, because of the space in the <code>Application Support</code> folder&#8217;s name, the quotations and the backslashes are required to help <code>rsync</code> find the proper folders. Other than that, the command is the same as before.</p>
<p>I selectively copied over all the data from the applications I wanted to keep and, voila, the next time I opened iCal or Address Book, my data was there.</p>
<p>The Mail application and Safari both have special ways of handling their information, however, so their datastores couldn&#8217;t be found in the <code>Application Support</code> folder. Instead, they keep their folders directly inside the <code>Library</code> folder named (predictably) <code>Mail</code> and <code>Safari</code>, respectively.</p>
<p>Also, since I use <acronym title="Internet Message Access Protocol">IMAP</acronym> for email and shared calendars in the form of <code>.ics</code> subscriptions whenever possible, the natural sync process for these databases saved a lot of time.</p>
<p>Most other programs in non-standard locations could be found with a little digging inside my Library folder.</p>
<p><strong>It should be noted that for this to work reliably, you should always move all the preference files along with the <code>Application Support</code> directory for any program whose <code>Application Support</code> directory you&#8217;re grabbing!</strong></p>
<h3>Cleaning up</h3>
<p>All told, the whole thing took maybe two hours and most of that time was spent transferring data. It was really quite painless. Because this was a surgical transfer, instead of a full &#8220;migration,&#8221; there&#8217;s very little to clean up.</p>
<p>However, for some reason, Apple&#8217;s .Mac Sync service had quite a bit of trouble keeping up with my new Mac&#8217;s new additions. The fix was simple enough: unregister every sync&#8217;ed computer, then reset all of the .Mac Sync data with the data on the new Mac. Then, re-sync each device either merging its data during its syncing process or replacing the data on it with the new, known-good data on .Mac. (Again, make sure your backup works before you do this.)</p>
<p>And that&#8217;s pretty much it. Now I have a new iMac, but it looks exactly like my old one on the screen. :)</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2007/09/13/moving-personal-data-from-one-mac-to-another/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>List of default Mac OS X command-line editing bash keyboard shortcuts</title>
		<link>http://maymay.net/blog/2007/07/18/list-of-default-mac-os-x-command-line-editing-bash-keyboard-shortcuts/</link>
		<comments>http://maymay.net/blog/2007/07/18/list-of-default-mac-os-x-command-line-editing-bash-keyboard-shortcuts/#comments</comments>
		<pubDate>Wed, 18 Jul 2007 23:19:49 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Tech/Computing]]></category>
		<category><![CDATA[Unix/Linux]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/archives/2007/07/18/list-of-default-mac-os-x-command-line-editing-bash-keyboard-shortcuts/</guid>
		<description><![CDATA[All the keyboard shortcuts you need to use the bash command line like a pro.]]></description>
			<content:encoded><![CDATA[<p>More and more often I find myself doing my work on the command line because it&#8217;s faster and more efficient. However, most users find that they end up spending a lot of time typing and re-typing commands, editting them, and then having to fix them. This is especially true <a href="/blog/archives/2006/09/14/a-mac-users-introduction-to-the-unix-command-line/">if you&#8217;re new to the command line</a>.</p>
<p>In addition, many times you want to run multiple commands with only slight variations. Perhaps you are benchmarking your Web server with <a href="//en.wikipedia.org/wiki/ApacheBench">ApacheBench</a> and want to change some of its settings. Whatever you are trying to do, many shells actually offer a full suite of command-line editting shortcuts.</p>
<p>Some of them are built into the shell itself and others are configured elsewhere. Unfortunately, different distributions and different operating systems sometimes don&#8217;t have the same shortcut configuration. There are lots of lists out there for Bash keyboard shortcuts for Linux, and many of these work on Mac <acronym title="Operating System">OS</acronym> X, but they don&#8217;t all work.</p>
<p>So here&#8217;s a list as complete as I can make it of the default keyboard editting shortcuts configured on a Mac <acronym title="Operating System">OS</acronym> X machine running bash. An extra goodie is that some of these movement shortcuts work in <em>any Coacoa text field</em>, which means you don&#8217;t have to keep switching between bash&#8217;s command line movement shortcuts and the +arrow keys shortcuts anymore.</p>
<dl>
<dt><kbd>CTRL+a</kbd></dt>
<dd>Move cursor to beginning of the line. (I think of this as <strong>a</strong>nchoring my cursor to the start.)</dd>
<dt><kbd>CTRL+e</kbd></dt>
<dd>Move cursor to the <strong>e</strong>nd of the line.</dd>
<dt><kbd>CTRL+k</kbd></dt>
<dd>Delete everything from under the cursor to the end of the line. (I think of this as <strong>k</strong>illing the rest of my line.)</dd>
<dt><kbd>CTRL+f</kbd></dt>
<dd>Move <strong>f</strong>orward one character. Identical to <kbd>&rarr;</kbd>.</dd>
<dt><kbd>CTRL+b</kbd></dt>
<dd>Move <strong>b</strong>ackward one character. Identical to <kbd>&larr;</kbd>.</dd>
<dt><kbd>ESC+f</kbd></dt>
<dd>Move <strong>f</strong>orward one word.</dd>
<dt><kbd>ESC+b</kbd></dt>
<dd>Move <strong>b</strong>ackward one word.</dd>
<dt><kbd>CTRL+u</kbd></dt>
<dd>Delete everything from under the cursor the beginning of the line.</dd>
<dt><kbd>CTRL+w</kbd></dt>
<dd>Delete from under the cursor to the beginning of the <strong>w</strong>ord.</dd>
<dt><kbd>CTRL+r</kbd></dt>
<dd><strong>R</strong>ecall previous commands by searching for them.</dd>
<dt><kbd>CTRL+t</kbd></dt>
<dd><strong>T</strong>ranspose (swap) the two characters before the cursor with one another.</dd>
<dt><kbd>ESC+t</kbd></dt>
<dd><strong>T</strong>ranspose (swap) the two words before the cursor with one another.</dd>
<dt><kbd>CTRL+y</kbd></dt>
<dd>Paste the most previously-deleted string. Basically a sort of command-line editting &#8220;undo.&#8221;</dd>
<dt><kbd>CTRL+z</kbd></dt>
<dd>Stop the current process and send it to the background.</dd>
<dt><kbd>CTRL+c</kbd></dt>
<dd>Send an SIG_HUP to the current process. The net effect of doing this on the command line is that you <strong>c</strong>ancel your current command and are presented with a blank new line.</dd>
<dt><kbd>CTRL+d</kbd></dt>
<dd>Send an end-of-file special character to the current process. Doing this at the command line is identical to closing your terminal window.</dd>
<dt><kbd>CTRL+p</kbd></dt>
<dd>Recall previous command executed. Identical to <kbd>&uarr;</kbd>.</dd>
<dt><kbd>CTRL+d</kbd></dt>
<dd>Forward <strong>d</strong>elete.</dd>
<dt><kbd>CTRL+h</kbd></dt>
<dd>Backspace.</dd>
<dt><kbd>CTRL+j</kbd></dt>
<dd>Carriage return. Identical to hitting the <kbd>return</kbd> key.</dd>
<dt><kbd>CTRL+m</kbd></dt>
<dd>Newline. Identical to <kbd>return</kbd>.</dd>
<dt><kbd>CTRL+l</kbd></dt>
<dd>Repaint screen. This is useful if a program&#8217;s output is overwriting some text on your terminal. The effect of doing this on a command line is that you clear the screen. Note than in Apple&#8217;s Terminal.app, you can also press <kbd>+K</kbd> to clear the screen.</dd>
<dt><kbd>CTRL-x + CTRL-x</kbd></dt>
<dd>Mark current location in line and jump to beginning of line or second mark if defined. Repeat to jump to between both marks.</dd>
<dt><kbd>CTRL+v</kbd></dt>
<dd>Insert next character <strong>v</strong>erbatim. This is how you escape control sequences. For instance, to literally send a </dd>
<dt><kbd>CTRL+[</kbd></dt>
<dd>Identical to <kbd>ESC</kbd>.</dd>
<dt><kbd>ESC+c</kbd></dt>
<dd><strong>C</strong>apitolize word under cursor and move to next word.</dd>
<dt><kbd>ESC+u</kbd></dt>
<dd><strong>U</strong>ppercase word under cursor and move to next word.</dd>
<dt><kbd>ESC+l</kbd></dt>
<dd><strong>L</strong>owercase word under cursor and move to next word.</dd>
<dt><kbd>ESC+.</kbd></dt>
<dd>Insert last word from previous command after cursor.</dd>
<dt><kbd><kbd>TAB</kbd></kbd></dt>
<dd>Auto-completes file, folder, and program names.</dd>
<dt><kbd>ESC-?</kbd></dt>
<dd>List the possible completions</dd>
<dt><kbd>CTRL-x /</kbd></dt>
<dd>List the possible filename completions</dd>
<dt><kbd>ESC-/</kbd></dt>
<dd>Attempt filename completion</dd>
<dt><kbd>CTRL-x ~</kbd></dt>
<dd>List the possible variable completions</dd>
<dt><kbd>ESC- ~</kbd></dt>
<dd>Attempt username completion</dd>
<dt><kbd>CTRL-x $</kbd></dt>
<dd>List the possible variable completions</dd>
<dt><kbd>ESC-$</kbd></dt>
<dd>Attempt variable completion</dd>
<dt><kbd>CTRL-x @</kbd></dt>
<dd>List the possible hostname completion</dd>
<dt><kbd>ESC-@</kbd></dt>
<dd>Attempt hostname completion</dd>
<dt><kbd>CTRL-x !</kbd></dt>
<dd>List the possible command completions</dd>
<dt><kbd>ESC-!</kbd></dt>
<dd>Attempt command completion</dd>
<dt><kbd>ESC-TAB</kbd>
<dt>
<dd>Attempt completion from previous commands in the history list</dd>
</dl>
<p>Note that this list assumes you&#8217;ve not reconfigured any of these shortcuts. Again, they&#8217;re the <em>default</em> keyboard assignments. Furthermore, they&#8217;re the default keyboard assignments for the default command-line editting mode, which is <em>emacs</em> mode. If you&#8217;re familiar with the <code>vi</code> editor, you can change this to use all the cursor movement and deletion keys you&#8217;re familiar with by saying <code>set -o vi</code> to your shell.</p>
<h3>External references</h3>
<p>Here&#8217;s some other people&#8217;s lists. They&#8217;re basically the same, but what the hey.</p>
<ul>
<li><a href="http://blog.lxpages.com/2007/06/26/bash-command-line-editing/">BASH Command-Line Editing at lxpages</a> &#8211; Also has a listing of vi-mode key shortcuts.</li>
<li><a href="http://www.faqs.org/docs/bashman/bashref_81.html">The BASH Reference Manual for Command Line Editing</a></li>
<li><a href="http://www.math.utah.edu/docs/info/features_7.html">Bash Features &#8211; Command Line Editing</a> &#8211; discusses even more commands that <code>Readline</code> can do for you when using bash.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2007/07/18/list-of-default-mac-os-x-command-line-editing-bash-keyboard-shortcuts/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>A Better Expect Subversion Post-Commit Hook</title>
		<link>http://maymay.net/blog/2007/06/21/a-better-expect-subversion-post-commit-hook/</link>
		<comments>http://maymay.net/blog/2007/06/21/a-better-expect-subversion-post-commit-hook/#comments</comments>
		<pubDate>Fri, 22 Jun 2007 04:41:19 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tech/Computing]]></category>
		<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[expect]]></category>
		<category><![CDATA[Subversion]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/archives/2007/06/21/a-better-expect-subversion-post-commit-hook/</guid>
		<description><![CDATA[In a previous post I wrote a small expect script to update a remote web server&#8217;s deployed code on a new commit to a Subversion repository using Expect and Subversion&#8217;s post-commit hooks. That first script was extraordinarily basic, so I&#8217;ve been wanting to add some sanity and error checking to it for a while. I [...]]]></description>
			<content:encoded><![CDATA[<p>In a <a href="/blog/archives/2007/05/18/use-expect-with-subversions-post-commit-hook-to-automatically-update-remote-servers/">previous post</a> I wrote a small expect script to update a remote web server&#8217;s deployed code on a new commit to a Subversion repository using Expect and Subversion&#8217;s post-commit hooks. That first script was extraordinarily basic, so I&#8217;ve been wanting to add some sanity and error checking to it for a while. I finally got around to it today.</p>
<p>This improved version of the post-commit hook does the same thing as the last one (that is, it logs into your web server over <acronym title="Secure SHell">SSH</acronym> with the given user and password, and yes, I&#8217;m aware of the scariness of embedding a password in such a way, so you should really set up <acronym title="Secure SHell">SSH</acronym> to use public keys for authentication for this), except now it also produces useful output.</p>
<p>Here&#8217;s the same script as before, but improved:</p>
<pre>#!/usr/bin/expect -f

#
# AUTHOR: Meitar Moscovitz <meitar@digitalpulp.com>
# DATE  : Thu Jun 21 16:32:42 EDT 2007
#

set HOST my.web.server
set USER someuser
set PASS xxx

# the working copy we're going to update
set WC /path/to/working/copy

# the path to the svn executable on the remote web server
set SVNBIN /usr/local/bin/svn

# our network is slow, set a long timeout
set timeout 30

##### DO NOT EDIT PAST THIS LINE! #####

# POST-COMMIT HOOK
#
# The post-commit hook is invoked after a commit.  Subversion runs
# this hook by invoking a program (script, executable, binary, etc.)
# named 'post-commit' (this file) with the
# following ordered arguments:
#
#   [1] REPOS-PATH   (the path to this repository)
#   [2] REV          (the number of the revision just committed)
#
# Note that Subversion does not provide this program with an environment
# of any kind. That means this program lacks a current working directory,
# a home directory, a $PATH, and so on.

set REPOS [lindex $argv 0]
set REV [lindex $argv 1]

# Define error codes
set E_NO_SSH     1 ;# can't find a usable <acronym title="Secure SHell">SSH</acronym> on our system
set E_NO_CONNECT 2 ;# failure to connect to remote server (timed out)
set E_WRONG_PASS 3 ;# password provided does not work
set E_UNKNOWN   25 ;# unexpected failure

# find the <acronym title="Secure SHell">SSH</acronym> binary on our system
if {[file executable /usr/bin/ssh]} {
	set SSHBIN /usr/bin/ssh
} elseif {[file executable /usr/local/bin/ssh]} {
	set SSHBIN /usr/local/bin/ssh
} else {
	send_error "Can't find a usable <acronym title="Secure SHell">SSH</acronym> on this system.&#92;n"
	exit $E_NO_SSH
}

spawn $SSHBIN $USER@$HOST $SVNBIN update $WC

expect {
    "continue connecting (yes/no)? " { send "yes&#92;r"; exp_continue; }
    -nocase "password:" { send "$PASS&#92;r"; }
    timeout {
        send_error "&#92;nWe have timed out after $timeout seconds while trying to connect to $HOST!&#92;n";
        exit $E_NO_CONNECT;
    }
}

expect {
	-nocase "password:" { ;# if we are asked for the password again, then we have provided the wrong password
		send_error "&#92;nCan not log in to $HOST because the password provided for user $USER has been rejected.&#92;n";
		exit $E_WRONG_PASS;
	}
	-re "revision (&#92;[0-9]+)." {
		if {$REV == $expect_out(1,string)} {
			send_user "&#92;nSuccessfully updated $WC on $HOST to revision $REV.&#92;n"
		} else {
			send_user "&#92;nUpdated repository to revision $expect_out(1,string), but svn reports that we are at revision number $REV.&#92;n"
			send_error "CAUTION: Repository updated to revision $expect_out(1,string), but committed revision $REV.&#92;n"
		}
	}
	default {
		send_error "An unexpected error has occured. The process at spawn ID $spawn_id has produced the following output:&#92;n"
		send_error $expect_out(buffer)
		exit $E_UNKNOWN
	}
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2007/06/21/a-better-expect-subversion-post-commit-hook/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Use expect with Subversion&#8217;s post-commit hook to automatically update remote servers</title>
		<link>http://maymay.net/blog/2007/05/18/use-expect-with-subversions-post-commit-hook-to-automatically-update-remote-servers/</link>
		<comments>http://maymay.net/blog/2007/05/18/use-expect-with-subversions-post-commit-hook-to-automatically-update-remote-servers/#comments</comments>
		<pubDate>Fri, 18 May 2007 22:25:30 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tech/Computing]]></category>
		<category><![CDATA[Unix/Linux]]></category>
		<category><![CDATA[expect]]></category>
		<category><![CDATA[Subversion]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/archives/2007/05/18/use-expect-with-subversions-post-commit-hook-to-automatically-update-remote-servers/</guid>
		<description><![CDATA[In one of my web development projects, it became important to keep the staging web server in sync with the latest code that myself and several other developers were working on. There are a number of ways to mirror files and directories across machines, rsync being one of the most widely known. However, in addition [...]]]></description>
			<content:encoded><![CDATA[<p>In one of my web development projects, it became important to keep the staging web server in sync with the latest code that myself and several other developers were working on. There are a number of ways to mirror files and directories across machines, <code>rsync</code> being one of the most widely known. However, in addition to simply mirroring the files across the two servers, we also needed a way to kick off the mirroring process that cleanly integrated with our development workflow. Subversion&#8217;s <code>post-commit</code> hook allowed us to do just that.</p>
<p>Still, however, the problem was not exactly straightforward. We needed to execute a <code>svn update</code> command on a server other than the server on which the Subversion repository was being hosted. Shell scripts are the obvious choice for command-line automation in UNIX, but they don&#8217;t deal with interactive commands very well. So instead of writing a shell script, I wrote an <code>expect</code> script.</p>
<p><ins datetime="2007-06-21T22:00-0500"><strong>This expect script is really basic. There&#8217;s <a href="/blog/archives/2007/06/21/a-better-expect-subversion-post-commit-hook/">a better one</a> in a future post on this topic.</strong></ins></p>
<pre>#!/usr/bin/expect -f

#
# This expect post-commit hook connects to <var>staging-webserver</var>
# and updates the working copy hosted there to the latest checked-in code.
# This means that whenever code is committed to the repository, the web site hosted
# will always be running the latest version of the code.
#
# AUTHOR: Meitar Moscovitz
#

# POST-COMMIT HOOK
#
# [...]
#

set REPOS [lindex $argv 0]
set REV [lindex $argv 1]
set HOST <var>staging-webserver</var>
# Use <var>update-user</var> to log in to <var>staging-webserver</var>
# to update the working copy, but this can probably be improved so as not
# to expose this user's password.
set USER <var>update-user</var>
set PASS <var>update-user's-password</var>

spawn /usr/bin/ssh $USER@$HOST svn update <var>/path/to/web/site/directory</var>
expect "continue connecting (yes/no)? "
send "yes&#92;r"
expect "password: "
send "$PASS&#92;r"
expect eof</pre>
<p>There&#8217;s one really tricky bit to this script, which is the understanding that when Subversion runs the post-commit hook, no environment information is passed to this script. As a result, there is no home directory or path information set for this executable. This is why everything is defined using absolute paths. Also, because there is no home directory for <var>update-user</var>, the expect script will always be prompted by <acronym title="Secure SHell">SSH</acronym> to re-verify the server&#8217;s identity. So rather than just expecting &#8220;password: &#8220;, we always expect &#8220;continue connecting (yes/no)? &#8221; and say yes, and <em>then</em> send our password.</p>
<p>Note, of course, that <var>update-user</var> should be a user with limited access to the system, yet enough so that he may update the working copy on the web server. I&#8217;m sure there is probably a more secure way of doing this as well, so any sort of feedback on securing this or scaling it would be welcome.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2007/05/18/use-expect-with-subversions-post-commit-hook-to-automatically-update-remote-servers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Mac User&#8217;s Introduction to the UNIX Command Line</title>
		<link>http://maymay.net/blog/2006/09/14/a-mac-users-introduction-to-the-unix-command-line/</link>
		<comments>http://maymay.net/blog/2006/09/14/a-mac-users-introduction-to-the-unix-command-line/#comments</comments>
		<pubDate>Thu, 14 Sep 2006 23:29:18 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Tech/Computing]]></category>
		<category><![CDATA[Unix/Linux]]></category>

		<guid isPermaLink="false">http://maymay.net/blog/archives/2006/09/14/a-mac-users-introduction-to-the-unix-command-line/</guid>
		<description><![CDATA[I&#8217;ve always loved teaching (for many reasons, some of which are too arrogant to get away with mentioning) and today my supervisor asked me if we could spend a little while talking about the command line and Mac OS X&#8217;s UNIX underbelly. Of course, I was thrilled at the prospect (see earlier statement on my [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve always loved teaching (for many reasons, some of which are too arrogant to get away with mentioning) and today my supervisor asked me if we could spend a little while talking about the command line and Mac <acronym title="Operating System">OS</acronym> X&#8217;s UNIX underbelly. Of course, I was thrilled at the prospect (see earlier statement on my love of teaching) and so I offered up a couple of resources. Since I think they&#8217;d be helpful for a lot of Mac users who&#8217;ve gotten bit by the UNIX bug (no pun intended), I expanded my list into a mini-guide.</p>
<h3>Shells and Terminals: What&#8217;s the difference?</h3>
<p>The very first thing anyone thinks about when they think UNIX is the command line interface (or <acronym title="Common Language Interpreter or Command Line Interpreter">CLI</acronym>, for short). The funny thing about the <acronym title="Common Language Interpreter or Command Line Interpreter">CLI</acronym> is that it&#8217;s actually a program in and of itself called a shell that takes what you write on the command line and basically translates it to the computer so it will do what you tell it to do.</p>
<p>So the computer (or the <acronym title="Operating System">OS</acronym>) is really only accessible through this shell. This is fairly straightforward until you realize that the shell is usually only accessible through another program, commonly called a terminal, which on <a href="//apple.com/macosx/">Mac <acronym title="Operating System">OS</acronym> X</a> is called Terminal.app. Therefor the terminal is really a window to a shell which is another window to the <acronym title="Operating System">OS</acronym>, which then talks to the computer for you. So when people say they want to learn to use the command line, you can understand the confusion that might cause. What shell do they want to use? And on top of that, which program are they intending to use to access their shell? Even on the Mac, there are at least two built-in terminals you can use (Terminal.app and XTerm) and maybe half a dozen shells.</p>
<p>As far as terminals go, Terminal.app is the most accessible (and you can find it in your Utilities folder in your Applications folder on your startup disk). My favorite resource for getting started with Terminal was <a href="//macdevcenter.com/">MacDevCenter</a>&#8216;s excellent article, <a href="//macdevcenter.com/pub/a/mac/2001/12/14/terminal_one.html">Learning the Mac <acronym title="Operating System">OS</acronym> X Terminal</a>, the title of which makes a lot more sense after understanding the previous two paragraphs. That article will show off some of Terminal&#8217;s impressive features that make a <acronym title="Graphical User Interface">GUI</acronym> environment complement the command line environment nicely.</p>
<h3>The Command Line: Speak and it will be so</h3>
<p>The command line itself is, of course, yet another subject entirely. Thanks to its spartan appearance, I think the best way to learn it is to just use it. If you&#8217;re feeling brave and have a spare computer lying around, take the leap and install a <a href="//www.linux.org/">Linux</a> or a <acronym title="Berkely Standard Distribution">BSD</acronym> distro, but run it all from the command line (which is simply a matter of <a href="//www.tuxfiles.org/linuxhelp/xbootup.html">changing the active runlevel</a> on most UNIX-like <acronym title="Operating System">OS</acronym> distros). This will effectively boot you into a shell, with no <acronym title="Graphical User Interface">GUI</acronym> coating. For Mac users who want to stay closer to home, you can do the same thing by logging into Mac <acronym title="Operating System">OS</acronym> X as the <code>>console</code> user (with no password). This strips Mac <acronym title="Operating System">OS</acronym> X of its Aqua interface and drops you into a login shell.</p>
<p>The important thing to remember is that, while in a shell, you can do everything you can do in a <acronym title="Graphical User Interface">GUI</acronym> mode. You can <a href="http://www.pgts.com.au/pgtsj/pgtsj0208e.html">browse the web</a>, <a href="http://www.westwind.com/reference/OS-X/commandline/text-files.html">edit and view documents</a>, and even <a href="http://www.linuxdevcenter.com/pub/a/linux/2003/05/22/email_history.html">read and compose email</a>. Of course, there won&#8217;t be any pictures, but the point remains that these things can be done. A week of running your computer in a shell and you&#8217;ll feel more comfortable than ever at the command line.</p>
<p>But while you&#8217;re there, you&#8217;ll want to acquaint yourself with several commands you can use to get help. The most important is the <code>man</code> command, which will let you browse the documentation for any command you want to use. You can even browse the documentation on the <code>man</code> command itself by typing <code>man man</code> (and I strongly recommend that you do that).</p>
<p>Another command you&#8217;ll want to get familiar with is <code>apropos</code>. If you type <code>man apropos</code>, you&#8217;ll get a very description of what that command does. (I won&#8217;t spoil the treat for you.) A similar command to <code>apropos</code> is <code>whatis</code>. All these commands are just programs like any other, absolutely identical to the ones you&#8217;re already using with the sole exception that instead of outputting pixels to a screen, they output characters to a shell.</p>
<p>On the web, one of my oft-referenced resources for learning the basics of a shell environment (and thus the command line) is <a href="//www.tuxfiles.org/">TuxFiles</a>. It&#8217;s geared towards Linux users, but the things you can learn there apply to all UNIX-like operating systems. Another one is <a href="//gd.tuwien.ac.at/linuxcommand.org/">LinuxCommand</a>. Check them both out.</p>
<h3>Inside the Shells</h3>
<p>By now you&#8217;re hopefully running your computer with a terminal window constantly open in the background, or at least you&#8217;re excited about trying it. So what&#8217;s next? Learn a new shell! By default, most <acronym title="Operating System">OS</acronym>&#8216;s will use <code>bash</code>, an abbreviation for the Bourne Again Shell, which itself is based on the <a href="//en.wikipedia.org/wiki/Bourne_shell">Bourne Shell</a> (get it, get it?), written by Steve Bourne.</p>
<p>Different shells all do the same thing, which is enable you to speak with (by typing to) your computer and have it do your bidding, but they understand different dialects so you need to speak to them in slightly different ways. There are dozens of shells you can use, and which one you ultimately choose depends on the features and syntax of each. I spent a good deal of time <a href="//en.wikipedia.org/wiki/Shell_%28computing%29">reading about them all on Wikipedia</a> before I decided to scrap the whole ordeal and stick with Mac <acronym title="Operating System">OS</acronym> X&#8217;s default <code>bash</code> shell. However, I learned a lot along the way, and that was really the point.</p>
<h3>Speaking Command Line is like learning a new language</h3>
<p>Ultimately however, it&#8217;s not about the shell or terminal you use, but about the things you can do. This, unfortunately, has to come with time. It&#8217;s exactly like learning a language. Every command you learn is akin to learning and using a new verb. The more you use a new language to communicate, the better you&#8217;ll become at speaking it. The same is true of the command line.</p>
<p>Keep your terminal program open 24/7/365, and whenever you&#8217;re doing something, ask yourself if you could do the same thing on the command line. If you&#8217;re not sure, Google it, and if the answer is yes, do it that way the next time. This is especially useful when what you&#8217;re doing is more than one thing. It takes a dozen or so clicks to open a file in TextEdit, copy it to the clipboard, past it to a new document, then add some text to the end of the new document, and finally save it again, but all of that can be done by typing a single line in a terminal. (Hint: use your shell&#8217;s <a href="//www.linuxdevcenter.com/pub/a/linux/lpt/13_01.html">piping and I/O redirection features</a>.)</p>
<p>The more you immerse yourself, the better you&#8217;ll become. If you&#8217;re really dedicated, I&#8217;ve heard nothing but great things about the book <a href="http://www.amazon.com/gp/redirect.html%3FASIN=0596009151%26tag=maymaydotnet-20%26lcode=xm2%26cID=2025%26ccmID=165953%26location=/o/ASIN/0596009151%253FSubscriptionId=0EMV44A9A5YT1RVDGZ82" title="View product details at Amazon">Learning Unix for Mac <acronym title="Operating System">OS</acronym> X Tiger</a>, which describes itself as a guided tour of Unix designed for a Mac user. Ah, just what the curiosity ordered.</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2006/09/14/a-mac-users-introduction-to-the-unix-command-line/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Fedora Fumbles, FreeBSD Functions</title>
		<link>http://maymay.net/blog/2005/01/26/fedora-fumbles-freebsd-functions/</link>
		<comments>http://maymay.net/blog/2005/01/26/fedora-fumbles-freebsd-functions/#comments</comments>
		<pubDate>Wed, 26 Jan 2005 16:56:53 +0000</pubDate>
		<dc:creator>Meitar</dc:creator>
				<category><![CDATA[Unix/Linux]]></category>

		<guid isPermaLink="false">/?p=170</guid>
		<description><![CDATA[Say what you will about competing commercial operating systems, but at least they install easily. Linux, or at least the Linux distros trying to be Windows clones, for all their advantages are still daunting to newbies. Here's a brief recount of my trials and tribulations and, eventually, my success.]]></description>
			<content:encoded><![CDATA[<p>Fedora Core is a bipolar Linux distribution. There, I&#8217;ve said it. I know there are legions of Fedora devotees out there, but they have probably had no such headaches installing the damn distro as I have had in the past week or so.</p>
<p>For all my troubles, it was easier to get FreeBSD up and running (a mere two attempts instead of the several dozen with Fedora) <em>and</em> get a full graphical desktop running. To their credit, the Fedora Project is trying to create a &ldquo;fully functional&rdquo; graphical desktop environment right out of the box, which is a bit more of a challenge than FreeBSD&#8217;s standard install which drops the user straight into a command-line shell. Thankfully, I am not that much of a computer cripple, and so I was able to find my way into the full <acronym title="GNU Network Object Model Environment">GNOME</acronym> desktop environment in a matter of minutes.</p>
<p>Even so, there are many things left undone in FreeBSD&#8217;s standard installation (which are supposed to work almost immediately with a Fedora Linux installation), and which I will end up having to go back and configure myself later. For what its worth, I am at least getting a far more hands-on introduction to a real UNIX than what I would have gotten if Fedora Core worked as advertised. Whether or not that is a good thing only time will tell. In the mean time, I am merely happy to be experiencing a new <acronym title="Operating System">OS</acronym>.</p>
<h3>Further Fedora Failures</h3>
<p>I had tried to install Fedora Core 3 on several PCs of very different hardware makes last week. In <em>each</em> case I was unable to complete the Fedora Core 3 installer and get a working version of Fedora Linux onto the computers. Despite spending the better part of this week researching the topic and attempting to find solutions to the problems, I simply could not get it to work.</p>
<h4>Fedora Core 3 Installation Problems</h4>
<p>I was constantly confronted, in some point during either the graphical or text-based installation of Fedora with the console message <samp>Install exited abnormally</samp> followed by lines that read <samp>Sending termination signals&#8230;done.</samp>, unmounting filesystems, and finally stating that <samp>You may safely reboot your system</samp>.</p>
<p>Whether or not it was, indeed, safe to reboot the system is up for debate. In some cases my previous <acronym title="Operating System">OS</acronym> had already been rendered unbootable by the installer having written a new partition table to the hard drive before &ldquo;exitting abnormally.&rdquo; This is why I had rescue CDs before attempting a Linux migration (and is why you need to have them, too)!</p>
<p>In all the mailing list archives and installation guides I could find, several common motifs echoed in the various &ldquo;Help me&rdquo; posts I perused:</p>
<ol>
<li>
<p>Using certain kinds of mice, most notably <em>any form of LogiTech&reg; or serial mice</em> can cause crashes of the graphical installer and should not be probed for automatically, or&mdash;in the worst cases&mdash;should not be used during installation, period. This is not really a problem because the installer provides ample keyboard navigation support, but is a rather annoying bug anyway.</p>
<p>Workarounds that I have tried included:</p>
<ul>
<li>Using a generic mouse instead of any major brand mouse. Specifically, I used an InterAct PS/2 (6-pin mini-<acronym title="Deutsches Institut f&uuml;r Normung">DIN</acronym>) mouse instead of a LogiTech, IntelliMouse, or serial mouse.</li>
<li>Unplugging the mouse for the duration of the automatic hardware probing and then manually configuring the installer to use a generic 3-button mouse.</li>
<li>Unplugging the mouse for the duration of the installer. Or for the durations that worked, anyway.</li>
<li>Using the text-based installer (which does not use a mouse at all) instead of the graphical one.</li>
</ul>
<p>Unfortunately, none of this had any effect other than to drive me crazy when trying to combine these various workarounds with the following workarounds.</p>
</li>
<li>
<p>Hardware probing itself is sometimes, allegedely, to blame for the failed installs. Disabling the hardware probe, or certain parts of it, by passing special options to the Linux kernel at boot time sometimes fixes the problem. Additionally, sometimes certain options regarding the power management features of the hardware and the kernel cause problems, and they should also be disabled during the installation boot-up process via special kernel arguments. The list of special boot options I tried were:</p>
<ul>
<li><code>linux noprobe</code></li>
<li><code>linux noacpi</code></li>
<li><code>linux nofb</code></li>
<li><code>linux mem=<var>mem_amount</var></code> (with the appropriate amount of memory available on whatever system I was trying to install onto in place of <var>mem_amount</var>)</li>
<li>Various others I can&#8217;t remember right now.</li>
<li>Various combinations of the above options in conjunction with other attempts.</li>
</ul>
<p>In my case, the automatic hardware probe always managed to correctly guess my video card and monitor type (Intel 810 and ViewSonic EF70, respectively), so I was left to believe that the mouse was the only likely hardware issue. Nevertheless, I did notice that when the X server was starting up, parts of the usually gray screen were corrupted (think horizontal or vertical &ldquo;snow&rdquo; on an old <acronym title="TeleVision, though our British and Aussie friends like to say 'tellie'">TV</acronym> set) and later, scrolling text and pop-up windows would not display correctly.</p>
</li>
</ol>
<p>Sooner or later, usually sooner and almost always during the <samp>Searching for Fedora Core installations&#8230;</samp> progress dialogue, the X server would exit abnormally (or crash) and I would be told that it was safe to reboot my system. To which I scoffed and went to eat more cake.</p>
<p>I suspect that I may be lacking some kind of knowledge about either</p>
<ul>
<li>how the Linux kernel works or how <acronym title="Operating System">OS</acronym> kernels in general work, or</li>
<li>how physical media such as hard disk drives interact with their software counterparts and how they store information (partitions, blocks, clusters, sectors, heads, cylinders, etcetera&hellip;)</li>
</ul>
<p>that I need to understand in order to solve this problem. Unfortunately, despite all that I am reading on that topic these days I just could not get Fedora Core 3 to install successfully.</p>
<p>The really frustrating part in all of this is that there are no explicit error messages that come up to help me diagnose the issue. Even with the most braindead implementation issues on Windows, an error message, cryptic as it usually is, never fails to pop up and let the user know something is wrong. (Of course, the sheer frequency with which that happens is actually a prime motivator to my fondness for Unix-like systems.)</p>
<p>In this case, Fedora Core&#8217;s installer never warns me of a problem until its too late. In two cases, during a graphical installation on a machine that had already logged a failed installation attempt an error window <em>did</em> show itself and read something like <samp>BUG! Assertion (heads > 0) failed!</samp> which I understood to mean that something was either royally screwed with my partition table, BIOS drive geometry, or physical hard disk drive, and thus induced my search for the <a href="http://lwn.net/Articles/86835/">bugfix at LWN.net</a>. Some common sense tells me it is more likely to be a problem with the partition table than anything else because both Windows and Knoppix work without any problems at all.</p>
<h4>Fedora Core 2 Installation Succeses <em>and</em> Woes</h4>
<p>It was suggested to me, when I finally gave up and sent a rare and detailed &ldquo;help me&rdquo; request to a very nice (and far more skilled) acquaintence of mine, that I should try to install Fedora Core 2 instead of Fedora Core 3 because it was likely to be far more stable.</p>
<p>The good news is that I have actually managed to get <acronym title="Fedora Core 2">FC2</acronym> working on one (1!) machine of mine. Surprisingly, the docile computer is the extremely old PeoplePC-branded box with extremely low resources. (PeoplePC was a prevalent <acronym title="Internet Service Provider">ISP</acronym> in the mid-1990&#8242;s who were, I believe, the first to offer cheap computers as a bonus to new subscribers.)</p>
<p>Unfortunately, this machine runs painfully slowly (especially with a huge application like <acronym title="GNU Network Object Model Environment">GNOME</acronym>) and so even opening windows is an exercise in patience. Doing anything actually <em>productive</em> is simply unrealistic, as it took nearly 2 hours to get the latest updates in <code>up2date</code> from the Red Hat Network, and I actually cancelled the update in the middle of that process. So I had been hoping that Fedora Core 2 would install nicely on the other machines I have.</p>
<p>Of course, that&#8217;s when the bad news hit. The bad news is that bugs are in <acronym title="Fedora Core 2">FC2</acronym> as well and the same thing happened with it as what happened with <acronym title="Fedora Core 3">FC3</acronym> on one of the machines I tried to install it on. I was greeted with that very familiar <samp>Install exited abnormally</samp> message and was told to reboot my system. I spent a few minutes trying a few of the workarounds I talked about above on this version of Fedora on this machine, but gave up after about half an hour.</p>
<p>Interestingly, on the other machine which didn&#8217;t take the install the problem was entirely different. Rather than even getting to the graphical installer, when I pressed <code>Enter</code> at the <code>boot:</code>-prompt I was inexplicably dropped into the text-based installer instead. There was not the slightest indication that the computer was even <em>trying</em> to load the graphical installer. Wierd! This didn&#8217;t happen with Fedora Core 3 at all.</p>
<p>Optimistic as I was, I thought it still might work; perhaps it was just the graphical installer that wouldn&#8217;t function. But alas, this was not to be. When I was asked where the installation media is to be found and responded with &ldquo;Local <acronym title="Compact Disc">CD</acronym>-<acronym title="Read Only Memory">ROM</acronym>,&rdquo; the text-based installer reported being unable to locate Fedora Core on the <acronym title="Compact Disc">CD</acronym>-<acronym title="Read Only Memory">ROM</acronym>, even though the install disk was right there in the <acronym title="Compact Disc">CD</acronym> drive and I had used that very disc to get <acronym title="Fedora Core 2">FC2</acronym> working on the first, oldest machine I tried!</p>
<p>Thus, I have decided that Fedora is a bipolar Linux distribution which needs heavy doses of appropriate patience and medications. I am at a total loss to explain this except to say that I am not left with a great taste for Fedora or Red Hat in my mouth. Ew.</p>
<h3>FreeBSD is Less Moody, but also Potentially Confusing</h3>
<p>To make matters even more confusing, I had tried to install FreeBSD some days ago on the old machine which now holds the only working Fedora Core installation I have. When I tried to install FreeBSD on it the other day I was unable to proceed due to an error that read something like <samp>Unable to locate Hard Disk Drive</samp> or similar. I can&#8217;t remember the exact wording.</p>
<p>After giving up with Fedora tonight, I tried to install FreeBSD on the machine which forced me into the text-based installer for <acronym title="Fedora Core 2">FC2</acronym>. It has completed without a hitch, and it only took me a few moments to orient myself within the system (<code>man hier</code> was incredibly helpful) in order to find out how to start a <acronym title="GNU Network Object Model Environment">GNOME</acronym> session and get back to the still-comforting <acronym title="Graphical User Interface">GUI</acronym> desktop.</p>
<h3>Final Fumbling Thoughts</h3>
<p>It might be of interest that both machines on which Fedora Core 2 failed to install for one reason or the other are HP Pavillion machines of somewhat different makes. One has a Pentium III processor and the other a Celeron, for instance.</p>
<p>Since FreeBSD has worked on one of these Pavillion towers but not on the old PeoplePC-branded tower (where Fedora 2 <em>did</em> work) I am hoping that at the very least some other <acronym title="Berkely Standard Distribution">BSD</acronym> will take to the other Pavillion. That way, I can get different operating systems on my various computers and finally get to start playing with the many options out there, like I have been wanting to do for months now.</p>
<p>While I hope this is certainly not the end, I am not at all opposed to the idea of giving up on Linux (or at least Red Hat) for the time being. Perhaps all I really need is to go build myself a new system with <em>new</em> and (hopefully) supported hardware. That really shouldn&#8217;t be such a big deal, and I need to upgrade that old PeoplePC box anyway. 200-something mhz is just not acceptable these days. (It wasn&#8217;t even in the mid 1990&#8242;s, but PeoplePC was cheap and we are not rich.)</p>
<p>I am already far more comfortable with FreeBSD than I was even in the graphical environment of Fedora Core 2&#8242;s default <acronym title="GNU Network Object Model Environment">GNOME</acronym> themes. Perhaps it is the shell. I spend a lot of time on Mac <acronym title="Operating System">OS</acronym> X within Terminal at a <code>tcsh</code> prompt (though I have playing with <code>bash</code> lately) and, after all, FreeBSD is one of Mac <acronym title="Operating System">OS</acronym> X&#8217;s parents.</p>
<p>Seems only fitting that I should feel more comfortable with the <acronym title="Berkely Standard Distribution">BSD</acronym>&#8216;s than with a Linux. In the end, <strong>L</strong>inux <strong>I</strong>s <strong>N</strong>ot <strong>U</strong>ni<strong>X</strong>. ;)</p>
]]></content:encoded>
			<wfw:commentRss>http://maymay.net/blog/2005/01/26/fedora-fumbles-freebsd-functions/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

