---
created_at: '2016-08-21T01:34:11.000Z'
title: How to change symlinks atomically (2005)
url: http://blog.moertel.com/posts/2005-08-22-how-to-change-symlinks-atomically.html
author: ffggvv
points: 70
story_text: 
comment_text: 
num_comments: 63
story_id: 
story_title: 
story_url: 
parent_id: 
created_at_i: 1471743251
_tags:
- story
- author_ffggvv
- story_12329066
objectID: '12329066'

---
[Source](http://blog.moertel.com/posts/2005-08-22-how-to-change-symlinks-atomically.html "Permalink to How to change symlinks atomically - Tom Moertel’s Blog")

# How to change symlinks atomically - Tom Moertel’s Blog

[Tom Moertel's Blog][1]

[Home][1] [About][2] [Archive][3]

# How to change symlinks atomically

By [Tom Moertel][4]

Posted on August 22, 2005

Tags: [ruby][5], [symlink][6], [safe][7]

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
    unlink("current")         = 0
    symlink("new", "current") = 0

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
      def atomic_symlink(old)
        suffix = [Array.new(6){rand(256).chr}.join].pack("m").strip.tr('/','_');
        tmplink = Pathname.new(self.to_s + "_" + suffix)
        tmplink.make_symlink(old)
        begin
          tmplink.rename(self)
        rescue
          # if rename fails, we must remove the temporary link manually
          File.unlink(tmplink.to_s)
          raise
        end
      end
    end

This code is nothing more than a robustified version of the by-hand method. It picks better names for temporary links, and it cleans up after itself, should something go wrong, but otherwise it does the same thing.

Given how easy it is to change symlinks atomically, why do it any other way? Life is hard enough without having to worry about another race condition.

Please enable JavaScript to view the [comments powered by Disqus.][8] [comments powered by Disqus][9]

Site proudly generated by [Hakyll][10]

[1]: http://blog.moertel.com/
[2]: http://blog.moertel.com/about.html
[3]: http://blog.moertel.com/archive.html
[4]: https://plus.google.com/103957126301745359889?rel=author
[5]: http://blog.moertel.com/tags/ruby.html
[6]: http://blog.moertel.com/tags/symlink.html
[7]: http://blog.moertel.com/tags/safe.html
[8]: http://disqus.com/?ref_noscript
[9]: http://disqus.com
[10]: http://jaspervdj.be/hakyll

