Syncing settings across computers

September 15, 2011 in Data

Please note this is intended for a Mac audience (all Unix users may of course apply... but I'm sure they've all cooked up something more sophisticated than this already). Windows users, I'm afraid you may be out in the cold.

One problem I've had while traveling (especially since my first laptop died and has been replaced) is needing to keep files and settings synced across computers. When I return home in a few months, I'll have a computer that is not only running a different operating system (Lion) from my main computer (Snow Leopard), but has a host of different tools and settings stored on it. I'm not talking about typical files like images and documents, I'm talking about system-level files, settings, configurations, and tools like Python which lack friendly icons.

I thought about a few ways to tackle this problem, ultimately settling on a Dropbox-based solution which I'm quite happy with. I'm detailing it here in case anyone is interested, or has any suggestions for improvement. This will work for any Unix-based system (including any Mac)... I'm not too sure about Windows. I imagine some adjustments might be required. The only caveat is that I think .bash_profile would be .bash_rc on a Linux box, but the spirit here is the same regardless: stick the global settings in a shared synced directory, and symlink them to wherever the computer expects to find them.

Before I begin, I should note that I considered using a version-control system, like GitHub, but decided not to because I don't want all of my files to be publicly available and I don't want to have to waste a private repository just for this purpose. Furthermore, I'm more interested in syncing the files; I don't care too much about retaining their history. As I become more comfortable with git, I can foresee my opinion changing.

The default Dropbox folder is at ~/Dropbox. Since this is the same across my computers, that suits me fine.

First, I need a repository for my configuration files. I created a hidden directory at ~/Dropbox/.system and moved the following files into it (for example): .bash_profile, .vimrc, .gvimrc, the entire .vim folder, etc.

Next, I need to actually do something with those files. I created another directory at ~/Dropbox/Scripts and wrote a few shell scripts to symlink the computer's configurations to the Dropbox ones. For example, my script for Terminal configuration looks something like this:

#!/bin/bash

# Symlink .bash_profile and other profiles
echo "Making Terminal symlinks..."
cd ~; rm .bash_profile; ln -s ~/Dropbox/.system/.bash_profile .bash_profile
cd ~; rm .bash_ps1; ln -s ~/Dropbox/.system/.bash_ps1 .bash_ps1

echo ""
echo "Finished!"
read -p "Press any key to exit."

It's important to note that only two lines of this script actually do anything -- the rest is just user-friendly filler (except the shebang in the first line). The line beginning with a # is a comment. The lines starting with echo are telling the system to print something to the screen, as is the line beginning read -p, which simply waits for a keypress before continuing.

The two lines beginning cd are doing the heavy lifting. First, they navigate to the home folder (cd stands for "Change Directory" and ~ represents the home folder). Then, they delete their target files (rm stands for "ReMove"). Finally, they create the symlinks. To create a symlink, use the ln ("LiNk") command with a -s argument, standing for "Symbolic link". Next, provide the symlink target in the Dropbox folder and give the link a name in the current directory.

By the way, Mac users, you may recognize the new symlinks as alias files -- in fact, that's all they are. You could accomplish this as easily with Apple-L, but what's the fun in that? (It's also terribly non-algorithmic, wouldn't save you time at all!)

If you save the script as a .command file (i.e. Terminal_symlinks.command), your Mac will execute it when you double-click it, no need to muck around in the command line. For me, this means I can execute all my scripts just by opening them all, like any other file. Some of them have dependencies (i.e. the SciPy script needs NumPy, which needs Python, which needs Homebrew), so I put numbers in front of those to indicate they should be run in order.

Now, when I move to a new computer, I just run the main script (that nests all the other scripts) and it links the current computer's settings to the stored ones. I never need to run the scripts again as long as the location of the files doesn't change. Any updates are saved and synced automatically, no need for commits. If I make a change on computer A, the file is automatically updated and computer B reflects it immediately.

As another example, the following script walks through the Homebrew installation process (or see my post here) -- note that this gives root access to /usr/local, which I'm fine with but you may not be!

#!/bin/bash

# Install Homebrew
echo "Installing Homebrew..."
/usr/bin/ruby -e "$(curl -fsSL https://raw.github.com/gist/323731)"
export PATH=/usr/local/bin:$PATH

# Get root access to /usr/local
echo ""
echo "Getting root access to /usr/local..."
sudo chown -R `whoami` /usr/local

# Warn about PATH
echo ""
echo "Add the following to ~/.bash_profile to use Homebrew:"
echo ""
echo "# Homebrew path"
echo "export PATH=/usr/local/bin:\$PATH"

echo ""
echo "Finished installing Homebrew!"
read -p "Press any key to exit."

I've seen many different people with as many different opinions on how to do this "best" -- what are your suggestions?

{ 8 comments… read them below or add one }

Leave a Comment

Previous post:

Next post: