Replace important symbolic link ‘safely’

Michał Górny picture Michał Górny · Sep 6, 2009 · Viewed 9.8k times · Source

I would like to change the target of symbolic link from within a bash script. The problem is that the symlink is quite important (it's /bin/sh, namely) and I would to do it in fashion that:

  1. New target will be available immediately after removing old, i.e. there will be no possibility that something will notice disappearing of it,
  2. There will be no possibility that the change will fail in the middle, i.e. leaving user with symlink removed and no new one.

I thought about two methods. Either using plain ln:

ln -fs /bin/bash /bin/sh

or using mv:

ln -s /bin/bash /bin/sh.new
mv /bin/sh.new /bin/sh

Which one will suit my needs better? Is there any possibility that one of them would try to replace the symlink target instead of symlink itself?

Answer

ire_and_curses picture ire_and_curses · Sep 6, 2009

Renaming (mv) is an atomic operation; creating a new symlink is not (delete old symlink; create new one). So you should use mv:

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

Here's a blog post discussing this. Also, if you're worried about what will happen, why not try it on a non-critical symlink first?