Steal My Bash Profile

Feel free to skip the monologue and just get the goodies.

I am in love with the Bourne Again Shell. Bash is a fantastic terminal environment, and a very interesting programming language in its own right.

I grew up using DOS. Unix shells always seemed scary and foreign, for some reason. I think a big part of the reason that I stayed on Windows for as long as I did was that I knew DOS, and could always resort to it in times of need. As a support tech in college, I got very familiar with DOS. It was comfortable and handy.

When I got into web programming, I had no choice but to learn at least the rudimentary basics of a unix-style environment. At that time, I was as a support tech at a software company whose product uses VisualBasic ASP over IIS, and had started playing around in that environment. However, I had no money, and web hosts that support ASP cost money.

By some stroke of luck or persistence, I managed to find a host that was free, Beigetower. That link doesn’t work any more, of course. I don’t know how long that server’s been down. Cuong Nghiem’s still listed as the owner on whois, though.) On top of that, they provided shell access. Not being able to resist the temptation to tinker with a real live web server, I learned enough Bash to poke around. As I learned more PHP, I picked up more bits and pieces along the way.

When I started at Yahoo, it was sink or swim to some extent. I was issued a FreeBSD dev box, and a windows desktop. I did most of my development in my safe windows world, but there are a lot of things you have to do on your dev box as an engineer at Yahoo that simply can’t be done in any other way. Bash was a regular part of my daily routine almost from the first day.

Eventually, I fell so head over heels in love with Bash that I had to say goodbye to Windows and get a Mac.

There are many good reasons to get a Mac instead of a PC. They’re easier and more intuitive in a lot of ways. They certainly look a lot nicer on almost every level. But I’d be lying if I said that having Bash right there all the time wasn’t the ultimate dealmaker.

One of the best things about Bash, in my opinion, is the fact that you can add shortcuts to your .profile (or .bash_profile or .bashrc, of course) that will be loaded every time you log in. As soon as I learned this, I started adding stuff.

Eventually, I had my profile so tricked out that it was hideously painful to have to work on a machine that didn’t have my shortcuts. Without my customized prompt, I’d get really confused about which directory I was currently in, and have to type pwd every three seconds just to not get lost. The sequence would usually go like this:

$ la -bash: la: command not found $ la -bash: la: command not found $ la -bash: la: command not found $ alias la="ls -laF"

Those first few entries of la were accompanied by plenty of growling and confusion, every. single. time.

So, I got into the habit of using scp or rsync to send my bash profile to any machine that I’d have to work on. However, some machines have vi, and some don’t. I’d make a change on the profile on my mac, and forget to sync it to my dev box. Machines that I didn’t log into often would be so far out of date that it was the “la” situation all over again. What’s worse, I put some stuff in other shell script files that were called by the profile to do other things, so it was no longer straightforward to keep them in sync. I’d send half the package, and then log in, and be inundated with errors all over the place.

When I switched from FreeBSD to a Red Hat Linux box, half my stuff didn’t work quite the same way. Also, I moved Foo Hack to a great new host, which is running Ubuntu. On the Mac, I use MacPorts, and the Ubuntu slice uses apt-get, and the RHEL of course uses yinst, the Yahoo! package management tool that quite simply makes all others look like crap by comparison. (Sadly, yinst is not open source. There’s this hack to simulate yinst on top of apt, though.) The Ubuntu and RHEL environments used vi as the default editor, but I’d changed that on the Mac to point to mate, the command-line interface to TextMate.

To say the least, a simple sync wasn’t cutting it even a little.

I re-wrote all my bash profile goodies to fit in a single file. Shell scripts were replaced with functions so that they could all live together. The edit command was defined to use the first available editor from a list of alternatives. Then, I put it in a file that was external from the main .profile or .bashrc file, so that it could be synced without overwriting anything that the OS placed in there by default. The only thing to do on a new server was to add . ~/.extra.bashrc to the bottom of whatever profile script it was already using.

I had already added a command called editprof that would bring my profile up in an editor. All that was needed then was a pushprof command that would rsync the .extra.bashrc file to a given host.

I’m releasing it under the WTFPL. There are actually a few files, since some stuff simply didn’t make any sense to have in certain environments. The copy here on on github is symlinked from my home directory updated frequently, so it’ll stay pretty up to date. Feel free to copy, learn, fork, or, like the license says, just do wtf you like with it.

A word of warning: like government regulation, this file increases in size but rarely gets revised. Some stuff may be completely useless or pointless. Some of it I hardly ever use any more. Figuring out better solutions to these problems is left as an exercise for the reader.

Get my bash extras.

Applescript for iTerm (and a request for help with it)

iTerm is a major part of my workspace. I’m a big fan of tabbed interfaces, and my fingers have gotten really good at the Apple-← and Apple-→ key combos to swap between them. I usually have three tabs going:

  1. One that runs Unison in batch mode to keep my mac and BSD machines in sync. I set the title of this one to “unisoner”.
  2. A second logged into my BSD machine in the package folder to easily relink the site package when I add files to it. This is the “relinker”. (Also, this one occasionally is used to tail -f on the apache log file.)
  3. A third sitting in my code folder to do CVS updates, open files, grep for stuff, etc. This is “cvser”.

Of course, it’s a pain to go through the steps to set all this up. So, I wrote this Applescript, and it does it all:

tell Application "iTerm"   activate   set myterm to (make new terminal)   tell myterm     if (count of sessions) < 3 then       my open_tab("title unisoner cd dev/orion unisonpush unisondev")       my open_tab("v yroot orion_front title relinker-tailer cd dev/orion/front/package yapl")       my open_tab("title cvser cd dev/orion open -a TextMate orion.tmproj")     end if   end tell   terminate first session of current terminal end tell on open_tab(command)   tell Application "iTerm" to tell first terminal     launch session "Default Session"     tell last session       write text command     end tell   end tell end run_command

The only problem is, it requests a password when it ssh'es into my dev box and changes to the project root. So, that whole piece falls down.

Anyone out there in geek land know of a way to make an Applescript respond to things like that? Something like this:

whenever the last line is "Password:" then   write text returned of (display dialog "Password:" default answer "") end if


Turns out, what I suggested is pretty close to what works. However, since there’s no event to listen for that would tell the script that the display has been updated, it takes a bit of fudging, and doesn’t always work perfectly. Basically, you put @@@PASSWORD@@@ in the list of commands where you may expect a password prompt, and it’ll wait for a second and display a dialog if necessary.

on open_tab(command)   set commands to paragraphs in command      tell Application "iTerm" to tell first terminal     launch session "Default Session"     repeat with currentCommand in commands              if (text of currentCommand = "@@@PASSWORD@@@") then         do shell script "sleep 1"         set pw to last word of (get contents of last session)         if pw = "Password" then           tell Application "Finder"             activate             set pw to text returned of (display dialog "Password:" default answer "" with hidden answer)           end tell           tell Application "iTerm" to activate           tell last session to write text pw         end if                else         tell last session to write text currentCommand       end if                   end repeat        end tell end open_tab

Get the finished product: Applescript for iTerm. You’ll want to change up the specific commands up near the top, of course.

Fix for Vi's broken arrow key support in iTerm

I originally posted this at on Tuesday, April 17th, 2007. I’ve incorporated the info from the comments into the main post. Special thanks to: radius, benstiglitz, and Higgaion for helping to provide more information.

So, I got turned on to iTerm, a prettier and more user-friendly alternative to Apple’s native

However, for some reason, I got the following error message whenever I tried to use arrow keys in Vi:

Usage: [[

The problem is that Vi is faithfully responding to the TERM variable that iTerm is sending. (I’m not sure why and PuTTY don’t suffer from this issue, but c'est la vie.) So, I thought, you should keep the terminal setting in iTerm to xterm-color, since this is great for most things, but then add this setting to your .exrc file to tame Vi:

set term=linux

I wasn’t sure why that fixed it, but it did. set term=cons25 was another fix that I found, but it seemed to break when I had line numbers turned on, because all tab characters are turned into backticks (`).

Of course, that’ll break if you use a different terminal setting on another program, so Higgaion suggested putting this into your .vimrc or .exrc instead:

if $TERM_PROGRAM == '' set term=linux endif

However, the same problem occurs when using the more and less commands—the arrow keys are broken, but the hjkl keys worked just like they do in Vi. Since there’s no .morerc or .lessrc to set the term variable, I was dismayed.

According to benstiglitz:

The default termcap on Mac OS X specifies that applications should enter application-specific cursor mode when capturing the display. iTerm is faithfully sending the application-mode sequences, but most terminal emulators just ignore the app-mode escape sequences and send normal key sequences instead.

So, this is being determined by iTerm’s behavior, so should be fixable in iTerm’s settings. I poked around in iTerm’s menus. Under Bookmarks > Manage Profiles > Terminal Profiles > Default, you can set the default terminal type to linux. Then you can enjoy proper arrow key support in every situation under iTerm, without futzing with config files in your home directory. Incidentally, it seems that linux has the same color support as xterm-color, so nothing is lost.

Broken Mac Wireless Driver in 10.4.10

Note: This post is regarding an issue that has since been fixed by Apple. If you’ve run this script, then please run the included to reverse the changes, and then get the actual patch from the Software Update command in the Apple Menu.

If you’ve upgraded to 10.4.10, and you use wireless (who doesn’t, these days?) and you work off the battery (why else would you have a laptop?), then you’ve probably run into issues with kernel panics and fast-dying batteries.

The fix is a bit tricky, and involves finding and downloading 3 different files, and then moving stuff around manually. Not being able to suffer the thought of doing this by hand, I decided to write a fix that’s all packaged up in a single download and one step.

Download the tgz file. Unpack it, and run It’ll create a backup of the files that are touched, and can be easily reverted to said backup with

Enjoy using wireless on battery power, MBP lovers!

Like it says in the script: I make NO gaurantees about the quality or reliability of this code. It worked for me, but it might make your machine explode. Use at your own risk!


Updated the scripts to work when run from Sorry for the confusion, guys!