<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Tom Moertel's Weblog: How to change symlinks atomically</title>
    <link>http://blog.moertel.com/articles/2005/08/22/how-to-change-symlinks-atomically</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Quality rants on programming theory and stuff geeks like</description>
    <item>
      <title>How to change symlinks atomically</title>
      <description>&lt;p&gt;Many people don&amp;#8217;t realize that changing the target of a symbolic link (symlink) is
not an atomic operation. &amp;#8220;Changing&amp;#8221; a symlink really means deleting it
and creating a new link with the same file name. For example, if I have a
symlink &lt;em&gt;current&lt;/em&gt; that points to a directory &lt;em&gt;old&lt;/em&gt;, and I want to change
it to point to a directory &lt;em&gt;new&lt;/em&gt;, I might use the following command:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;$ ln -snf new current
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Strace shows what really happens when I run the command:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;$ strace ln -snf new current 2&amp;gt;&amp;#38;1 | grep link
unlink("current")         = 0
symlink("new", "current") = 0
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;First, the existing symlink is deleted via the &lt;em&gt;unlink&lt;/em&gt; system
call. Then a new, identically named symlink is created via the &lt;em&gt;symlink&lt;/em&gt;
system call. It&amp;#8217;s a two-step process, and in between the steps, &lt;strong&gt;there
is no symlink.&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;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&amp;#8217;t exist. Oops.&lt;/p&gt;


	&lt;p&gt;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
&amp;#8220;change&amp;#8221; will be atomic too. By hand, the process looks like this:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;$ ln -s new current_tmp &amp;#38;&amp;#38; mv -Tf current_tmp current
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;In Ruby, I make atomic symlinking available everywhere by extending
the Pathname class with a new method &lt;em&gt;atomic_symlink&lt;/em&gt;:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;pathname&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Pathname&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;atomic_symlink&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;old&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;suffix&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="constant"&gt;Array&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;6&lt;/span&gt;&lt;span class="punct"&gt;){&lt;/span&gt;&lt;span class="ident"&gt;rand&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;256&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;chr&lt;/span&gt;&lt;span class="punct"&gt;}.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;pack&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;m&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;).&lt;/span&gt;&lt;span class="ident"&gt;strip&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;tr&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;/&lt;/span&gt;&lt;span class="punct"&gt;','&lt;/span&gt;&lt;span class="string"&gt;_&lt;/span&gt;&lt;span class="punct"&gt;');&lt;/span&gt;
    &lt;span class="ident"&gt;tmplink&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Pathname&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;_&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="ident"&gt;suffix&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;tmplink&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;make_symlink&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;old&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;begin&lt;/span&gt;
      &lt;span class="ident"&gt;tmplink&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;rename&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;rescue&lt;/span&gt;
      &lt;span class="comment"&gt;# if rename fails, we must remove the temporary link manually&lt;/span&gt;
      &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;unlink&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;tmplink&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="keyword"&gt;raise&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;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.&lt;/p&gt;


	&lt;p&gt;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.&lt;/p&gt;</description>
      <pubDate>Mon, 22 Aug 2005 12:00:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:c36fd19bb1406d2022c4d525c6ddb6fb</guid>
      <author>Tom Moertel</author>
      <link>http://blog.moertel.com/articles/2005/08/22/how-to-change-symlinks-atomically</link>
      <category>programming</category>
      <category>ruby</category>
      <category>web development</category>
      <category>ruby</category>
      <category>safe</category>
      <category>symlink</category>
      <trackback:ping>http://blog.moertel.com/articles/trackback/49</trackback:ping>
    </item>
    <item>
      <title>"How to change symlinks atomically" by anon</title>
      <description>&lt;p&gt;The &amp;#8216;-T&amp;#8217; in &amp;#8216;mv -T&amp;#8217; is kind of recent,
an alternative for older systems is the slightly gaudier&lt;/p&gt;


	&lt;p&gt;&amp;#8216;rename current_tmp current current_tmp&amp;#8217;&lt;/p&gt;


	&lt;p&gt;Also passes the &amp;#8216;strace&amp;#8217; atomic test in that it calls rename(2) w/o calling unlink(2) first.&lt;/p&gt;</description>
      <pubDate>Thu, 03 Apr 2008 18:08:15 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:4f91a203-8438-4ecb-b6e2-245415eb5d93</guid>
      <link>http://blog.moertel.com/articles/2005/08/22/how-to-change-symlinks-atomically#comment-713</link>
    </item>
    <item>
      <title>"How to change symlinks atomically" by anon</title>
      <description>&lt;p&gt;Excellent post! Thanks :)&lt;/p&gt;</description>
      <pubDate>Wed, 05 Mar 2008 09:12:31 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:c07a768c-e71e-4a6c-ab7a-187b853b3f21</guid>
      <link>http://blog.moertel.com/articles/2005/08/22/how-to-change-symlinks-atomically#comment-703</link>
    </item>
    <item>
      <title>"How to change symlinks atomically" by Eiki Martinson</title>
      <description>&lt;p&gt;Ah, okay. I&amp;#8217;ve been doing it with a line of perl instead, like:
perl -e &amp;#8216;rename(&amp;#8220;current_tmp&amp;#8221;, &amp;#8220;current&amp;#8221;)&amp;#8217;&lt;/p&gt;


	&lt;p&gt;But I think I like yours better.&lt;/p&gt;


	&lt;p&gt;Thanks!&lt;/p&gt;</description>
      <pubDate>Mon, 19 Nov 2007 18:10:36 -0500</pubDate>
      <guid isPermaLink="false">urn:uuid:f233db7d-da86-485f-bc92-8cebdbabcf71</guid>
      <link>http://blog.moertel.com/articles/2005/08/22/how-to-change-symlinks-atomically#comment-626</link>
    </item>
    <item>
      <title>"How to change symlinks atomically" by Tom Moertel</title>
      <description>&lt;p&gt;Darn!  I forgot the -T flag on mv.  Fixed.&lt;/p&gt;


	&lt;p&gt;Thanks for the catch, Eiki!&lt;/p&gt;


	&lt;p&gt;Cheers,&lt;br /&gt;
Tom&lt;/p&gt;</description>
      <pubDate>Wed, 10 Oct 2007 11:12:30 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:92195d0a-f6c4-4258-9d8f-097d1cea0f05</guid>
      <link>http://blog.moertel.com/articles/2005/08/22/how-to-change-symlinks-atomically#comment-591</link>
    </item>
    <item>
      <title>"How to change symlinks atomically" by Eiki Martinson</title>
      <description>&lt;p&gt;Nice tip, but the manual example doesn&amp;#8217;t work &amp;#8211; it just moves the current_tmp symlink into the directory pointed to by current.&lt;/p&gt;


	&lt;p&gt;Any idea how to fix it?&lt;/p&gt;</description>
      <pubDate>Wed, 10 Oct 2007 02:55:05 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:712c4738-a2de-4502-866e-40a13fb379e6</guid>
      <link>http://blog.moertel.com/articles/2005/08/22/how-to-change-symlinks-atomically#comment-590</link>
    </item>
  </channel>
</rss>
