Some Cool Shell Aliases
Over the last couple of years I’ve worked out some cool shell tricks, which I use as aliases. Like any good software developer, if I notice a pattern I take steps to generalize and reduce it. For shells, it might be as simple as replacing a regularly typed long command with a short alias, but the coolest tricks are the ones that reduce an entire habit.
The first one is the singleton pattern. Say you have a terminal program that should only have a single process instance but should only start on demand. Some programs may enforce that rule, if it makes sense to, but some do not.
In my case, that program was
rtorrent. I only want a single
instance of this program running at a time, but I also don’t want to
have to think about whether or not I’ve started it already. I always
run it in
screen so that I can detach it and
let it run in the background. My shell habits looked like this.
# Assume it's there already $ screen -r rtorrent # If not, fire it up $ screen -S rtorrent rtorrent
If I needed to start rtorrent for the first time I was often typing in that first command just to see it fail. Fortunately, it really does fail: the exit code is non-zero. This allows me to make this cool alias,
alias rt='screen -r rtorrent || screen -S rtorrent rtorrent'
Either it attaches to the existing instance or fires a new one up for me and attaches me to that one. Now, there is a race condition here. That “or” operator isn’t atomic, so something else might spawn an rtorrent instance in between check and creation. Since I’m only ever running this by hand, and there is only one of me, that’s not a problem.
The next trick has to do with
my habit of throwing up a temporary web server
when I need to share files. I noticed that I would launch it, run it
for a minute, kill it, run one or two commands, and launch it
again. For example, if I’m working on a program and I want to share
the build with someone else. I might drop out of it just to do
something with git and rebuild. Once again, my alias fix involves
alias httpd='screen -S http python -m SimpleHTTPServer 8080'
Rather than kill the server only to restart it again, I always run it
screen. So instead I detach, but I don’t even need to bother
This next one is my Emacs alias. Emacs has the really, really cool
ability to become a daemon. You can launch a daemon instance, then
connect to it as needed with clients to do your editing (
--create-frame or just
-c). This allows your Emacs session to live
for a long time, preserving all your buffers. Long-living sessions are
an old Lisp tradition. Also, being a daemon
eliminates any lengthy startup penalty, because it only happens once
$ emacs --daemon $ emacsclient -c # Close it and sometime later start another client $ emacsclient -c
This is another case of the single-instance problem. However, Emacs is
really smart about managing this by itself. It has an argument,
-a), which allows you to specify another
editor to use in case the daemon isn’t started.
emacsclient -ca nano
The most important part of this option is its hidden feature. When the argument is empty it defaults to launching a daemon. No need to launch it manually, it’s just one command.
alias e='emacsclient -cna ""'
Naturally, Emacs gets to be in one of the coveted, single-letter
slots. I also set one up for terminal mode Emacs (
-t instead of
alias et='emacsclient -ta ""'
And just to teach the editor heathens a lesson or two, this command has a second alias,
alias vi='emacsclient -ta ""'
The final trick is one I just figured out this week, and it involves
passphrase agents. Just in case you are not familiar, both
gpg have daemons which will securely store your passphrases for
Update June 2012: I have a better solution for this problem.
OpenSSH is loaded with extremely useful functionality. One of them is
key authentication. Rather than use a password to log into a system,
you can prove your identity cryptographically — you solve a math
problem that only you have the information to solve. This is
invaluable to Git, because it allows for passwordless access to remote
repositories. You can host a repository for a bunch of users without
the awkward password step (“Pst … your password is
Change it after you first log in.”). Instead, they all send you their
To use this feature, you first you generate a public/private keypair
for yourself, which gets stored in
At one point in this process you will be asked for a passphrase, which is used to encrypt your private key. At first you might wonder why you bother with the key at all if you’re going to encrypt it. Rather than enter a password to log into a system, you have to enter a passphrase, which is even worse because it’s longer. So you don’t bother with a passphrase. This is dangerous because it’s practically the same as storing your login password in a file! If someone got a hold of your private key file, they have full access to your systems.
This is where
ssh-agent comes in. It runs as a service in the
background. You register your private key with it with
it queries for your passphrase, storing it in memory. It’s very
careful about this. It’s stored on a memory page that has been
registered with the operating system such that it’s never written to
permanent storage (swap). When the process dies, or zeros out that
memory, the passphrase is completely lost.
gpg-agent, works very similarly. It holds onto your
PGP passphrase so you can perform a number of actions with it without
needing to enter it a bunch of times.
ssh know how communicate with their agents through
information stored in environmental variables. However, this creates a
problem when launching the agents. They can’t change the environment
of their parent process, your shell. The easiest way to do it is to
reverse the relationship, with the agent becoming the parent of your
$ exec ssh-agent bash
ssh-agent to launch a new shell with the proper
environment. In case you’re not familiar, the
exec causes the new
shell replace the current one. It’s the same
exec() as the POSIX
function. You could leave it off, but you’ll be left with nested
shells, which can be very confusing.
GnuPG’s agent is launched like this,
$ exec gpg-agent --daemon bash
My problem was that I often want both of these at the same time. I could run them back to back, but making them into a single, alias-able command is tricky. This naive expression will not work,
$ exec ssh-agent bash && exec gpg-agent bash
exec causes the current shell to end, so the second part
is never evaluated. I can’t simply remove the
execs and live with
nested shells because the next agent isn’t launched until the first
agent’s shell dies. The very cool solution is to chain them together!
alias agent='exec ssh-agent gpg-agent --daemon bash'
The current shell turns into the
ssh-agent, which spawns
with the proper environment for
ssh, which forwards its environment
along to spawn a new shell with the proper environment for both.
If I ever need another agent I just add it to the chain. That command
should probably be at the end of my
.bashrc or something, but it’s
just an alias for now. Sometimes I log into X first, sometimes
first, so I’m not sure what the correct place would be.