web-dev-qa-db-ja.com

どのようにビジーボックスのディレクトリへのシンボリックリンクをアトミックに変更しますか?

私はシンボリックリンクを(可能な限り近くに)アトミックに変更しようとしています。私はもう試した:

ln -sf other_dir existing_symlink

それは、existing_symlinkが指すディレクトリに新しいsymlinkを置くだけです。

ln -sf other_dir new_symlink
mv -f new_symlink existing_symlink

これも同じことでした。シンボリックリンクをディレクトリに移動しました。

cp -s other_dir existing_symlink

ディレクトリなので拒否します。

mv -Tはこのために作成されたと読みましたが、busyboxには-Tフラグがありません。

18
Shawn J. Goff

どのようにアトミック操作を取得できるかわかりません。 symlink(2)のmanページには、ターゲットがすでに存在する場合はEEXISTと表示されています。カーネルがアトミック操作をサポートしていない場合、ユーザーランドの制限は関係ありません。

mv -T持っている場合でも役立ちます。 GNU mv:

$ mkdir a b
$ ln -s a z
$ mv -T b z
mv: cannot overwrite non-directory `z' with directory `b'

古いシンボリックリンクを削除して再作成するという2つの手順でこれを行う必要があると思います。

1
Warren Young

これはcanで実際にrename(2)を使用してアトミックに実行できます。最初に一時的な名前で新しいシンボリックリンクを作成し、次に古いシンボリックリンクを完全に上書きします。一度に。 man page のように:

newpathがシンボリックリンクを参照している場合、リンクは上書きされます。

シェルでは、次のように_mv -T_を使用してこれを行います。

_$ mkdir a b
$ ln -s a z
$ ln -s b z.new
$ mv -T z.new z
_

その最後のコマンドをstraceして、実際にrename(2)を使用していることを確認できます。

_$ strace mv -T z.new z
lstat64("z.new", {st_mode=S_IFLNK|0777, st_size=1, ...}) = 0
lstat64("z", {st_mode=S_IFLNK|0777, st_size=1, ...}) = 0
rename("z.new", "z")                    = 0
_

上記では、_mv -T_とstraceの両方がLinux固有であることに注意してください。

FreeBSDでは、_mv -h_を交互に使用します。

43
Arto Bendiken

Artoがここで中断したところから始めると、これは完全に可能です。mv -Tがなくても、ターゲットディレクトリと同じ名前で新しいシンボリックリンクを作成し、mvをその親ディレクトリに作成するだけです。あなたの目標:

mkdir -p tmp/real_dir1 tmp/real_dir2
touch tmp/real_dir1/a tmp/real_dir2/a
# start with ./target_dir pointing to tmp/real_dir1
ln -s tmp/real_dir1 target_dir
# create a symlink named target_dir in tmp, pointing to real_dir2
ln -sf tmp/real_dir2 tmp/target_dir
# atomically mv it into ./ replacing ./target_dir
mv tmp/target_dir ./

http://axialcorps.wordpress.com/2013/07/03/atomically-replacing-files-and-directories/ )で取得したコード例

8
mssaxm

やってみました ln -snf

オプション -nは、宛先がディレクトリへのシンボリックリンクである場合、宛先の下に書き込むのではなく、宛先を上書きします。

乾杯

3
sokai