Help us understand the problem. What is going on with this article?

アトミックなシンボリックリンク更新

More than 1 year has passed since last update.

はじめに

Linuxでシンボリックリンクの参照先を更新したい場合、以下のようにするのが簡単です。

> ln -snf src dst

今回他のプロセスがdstにアクセス中に更新したかったので、この方法で安全に更新できるかどうか調べてみました。
確認した環境はRHEL7.2/Gentoo Linuxですが大抵のLinux環境で同じような挙動になるのではないかと思います。
(POSIXとかで決まってそうな気もしますが調べてません…)

straceで調べる

まずlnコマンドでの更新の様子を見てみます。

> strace ln -snf src dst
...
symlink("src", "dst")                   = -1 EEXIST (File exists)
unlink("dst")                           = 0
symlink("src", "dst")                   = 0
...

このようにlnは1コマンドですが、システムコール的には「unlinkで削除してからsymlinkでシンボリックリンクを作る」という実装になっているようです。
そのためunlinksymlinkの間にdstにアクセスされると失敗する可能性があります。

更新中に割り込めるか?

2つのシステムコールの間にアクセスされる可能性はありそうだったので、
実際に起きるかどうか以下のようなシェルスクリプトで実験してみました。

ln.sh
#!/bin/sh
echo test1 > src1
echo test2 > src2
while :
do
    ln -snf src1 dst
    ln -snf src2 dst
done
cat.sh
#!/bin/sh
while :
do
    cat dst
done

ln.shdstsrc1/src2に交互に更新し、cat.shdstを読みます。この2つを同時に実行すると以下のような結果になりました。

> ./cat.sh
test1
test2
test1
test2
test1
cat: dst: そのようなファイルやディレクトリはありません
test2
test1
test2
test1
test2

上記は抜粋ですが20~30回に1回程度はcatに失敗するようです。

アトミックなシンボリックリンク更新

先ほどのln.shの代わりに

ln_atomic.sh
#!/bin/sh
echo test1 > src1
echo test2 > src2
while :
do
    ln -s src1 tmp
    mv -Tf tmp dst
    ln -s src2 tmp
    mv -Tf tmp dst
done

このln_atomic.shを使ってみると

> ./cat.sh
test1
test2
test1
test2
test1
test2
test1
test2
test1
test2

という感じでcatの失敗は発生しなくなりました。

実際にシンボリックリンクを更新しているのはmvコマンドです。このコマンドは同一ファイルシステム内に限り、単一のシステムコールrenameで実装されています。従って更新中に割り込まれることはありません。

ちなみにファイルシステム間のmvは単にファイルコピー+削除になるようです。
そのためsrcdstはファイルシステムが異なっていてもよいのですが、tmpdstは同一ファイルシステムになければいけません。

まとめ

シンボリックリンクをアトミックに更新したい場合は以下のようにするといいようです。
tmpdstが同一ファイルシステムになるよう注意)

> ln -s src tmp
> mv -Tf tmp dst
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした