# How to change symlinks atomically

Posted on
Tags:

Many people don’t realize that changing the target of a symbolic link (symlink) is not an atomic operation. “Changing” a symlink really means deleting it and creating a new link with the same file name. For example, if I have a symlink current that points to a directory old, and I want to change it to point to a directory new, I might use the following command:

$ln -snf new current Strace shows what really happens when I run the command:$ strace ln -snf new current 2>&1 | grep link

First, the existing symlink is deleted via the unlink system call. Then a new, identically named symlink is created via the symlink system call. It’s a two-step process, and in between the steps, there is no symlink.

This can be a problem if you expect the symlink to be there always, such as when using the link to point to the active version of a live web site. If you change the symlink while deploying a new version of your site, for example, the web server might try to dereference the link during the small window of time when it doesn’t exist. Oops.

The solution to this problem is to effect the change by creating a new symlink and then renaming it over the old symlink. On Unix-like systems, renaming is an atomic operation, and thus the symlink “change” will be atomic too. By hand, the process looks like this:

\$ ln -s new current_tmp && mv -Tf current_tmp current

In Ruby, I make atomic symlinking available everywhere by extending the Pathname class with a new method atomic_symlink:

require 'pathname'

class Pathname
suffix = [Array.new(6){rand(256).chr}.join].pack("m").strip.tr('/','_');
tmplink = Pathname.new(self.to_s + "_" + suffix)
begin