Wie ändert man einen Symlink atomar in ein Verzeichnis in der Busybox?


18

Ich versuche (so nah wie möglich) einen Symlink atomar zu ändern. Ich habe es versucht:

ln -sf other_dir existing_symlink

Dadurch wurde der neue Symlink in das Verzeichnis gestellt, auf das existing_symlink zeigte.

ln -sf other_dir new_symlink
mv -f new_symlink existing_symlink

Das hat das Gleiche bewirkt: Der Symlink wurde in das Verzeichnis verschoben.

cp -s other_dir existing_symlink

Es lehnt ab, weil es ein Verzeichnis ist.

Ich habe gelesen, dass mv -Tes dafür gemacht wurde, aber busybox hat die -TFlagge nicht.

Antworten:


1

Ich verstehe nicht, wie man eine atomare Operation erreichen kann. Die Manpage für symlink(2)sagt, dass es gibt, EEXISTwenn das Ziel bereits existiert. Wenn der Kernel keinen atomaren Betrieb unterstützt, sind die Einschränkungen Ihres Benutzerlandes irrelevant.

Ich sehe auch nicht, wie es mv -Thilft, auch wenn Sie es haben. Probieren Sie es auf einer normalen Linux-Box aus, eine mit GNU mv:

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

Ich denke, Sie müssen dies in zwei Schritten tun: Entfernen Sie den alten Symlink und erstellen Sie ihn neu.


1
In der Tat gibt es leider keine Möglichkeit, ein Symbol atomar zu modifizieren. Das Beste, was Sie tun können, ist, den alten Link zu entfernen und einen neuen zu erstellen. GNU coreutils hat die Option, dies mit einem einzigen Befehl ( ln -snf) zu tun , aber es gibt immer noch zwei Systemaufrufe unter der Haube.
Gilles 'SO- hör auf böse zu sein'

43

Dies kann in der Tat atomar erfolgen rename(2), indem zuerst der neue Symlink unter einem temporären Namen erstellt und dann der alte Symlink auf einmal sauber überschrieben wird. Wie die Manpage sagt:

Wenn newpath auf einen symbolischen Link verweist, wird der Link überschrieben.

In der Shell würden Sie dies mv -Tfolgendermaßen tun :

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

Sie können stracediesen letzten Befehl ausführen, um sicherzustellen, dass er tatsächlich rename(2)unter der Haube verwendet wird:

$ 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

Beachten Sie, dass in den obigen Abschnitten beide mv -Tund straceLinux-spezifisch sind.

Verwenden Sie unter FreeBSD mv -halternativ.


1
Sehr schön! Es könnte hilfreich sein zu sagen, dass Sie am Ende einen Link von z nach b haben!
Vincenzo Pii

Verwenden Sie für eine betriebssystemunabhängige Lösung eine Skriptsprache, die in der Lage ist, den renameSyscall direkt anstelle von mv -hoder zu verwenden mv -T. Zum Beispiel mit Perl:perl -e 'rename "z.new", "z" or die $!'
Slaven Rezic

8

An der Stelle, an der Arto hier aufgehört hat, ist dies durchaus möglich, auch ohne mv -T, Sie müssen lediglich einen neuen Symlink mit demselben Namen wie das Zielverzeichnis erstellen und mvin das übergeordnete Verzeichnis Ihres Ziels kopieren:

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 ./

Codebeispiel aufgenommen über ( http://axialcorps.wordpress.com/2013/07/03/atomically-replacing-files-and-directories/ )


3

Hast du es versucht ln -snf?

Die Option -nüberschreibt das Ziel, anstatt darunter zu schreiben, wenn das Ziel eine symbolische Verknüpfung zu einem Verzeichnis ist.

Prost


3
ln -snfist nicht atomar: Es hebt die Verknüpfung zum Ziel auf und erstellt dann den gewünschten Symlink.
Gilles 'SO - hör auf böse zu sein'

2
Da das OP daran interessiert war, "so nah wie möglich an der atomaren Änderung eines Symlinks heranzukommen", ist dies eine absolut vernünftige Antwort. Wenn es einen besseren gibt, der näher kommt (oder atomar ist), kann dieser akzeptiert werden. Ich glaube nicht, dass es notwendig ist, eine Gegenstimme abzuhalten.
Wilco
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.