Comment change-t-on atomiquement un lien symbolique vers un répertoire dans busybox?

18

J'essaie (aussi près que possible) de changer atomiquement un lien symbolique. J'ai essayé:

ln -sf other_dir existing_symlink

Cela vient de mettre le nouveau lien symbolique dans le répertoire vers lequel point_symlink pointé.

ln -sf other_dir new_symlink
mv -f new_symlink existing_symlink

Cela a fait la même chose: il a déplacé le lien symbolique dans le répertoire.

cp -s other_dir existing_symlink

Il refuse car c'est un répertoire.

J'ai lu que mv -Tc'était fait pour ça, mais busybox n'a pas le -Tdrapeau.

Shawn J. Goff
la source

Réponses:

1

Je ne vois pas comment vous pouvez obtenir un fonctionnement atomique. La page de manuel pour symlink(2)indique qu'elle donne EEXISTsi la cible existe déjà. Si le noyau ne prend pas en charge le fonctionnement atomique, les limitations de votre espace utilisateur ne sont pas pertinentes.

Je ne vois pas non plus en quoi cela mv -Taide, même si vous l'avez. Essayez-le sur une boîte Linux standard, une avec GNU mv:

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

Je pense que vous allez devoir le faire en deux étapes: supprimer l'ancien lien symbolique et le recréer.

Warren Young
la source
1
En effet, il n'y a malheureusement aucun moyen de modifier atomiquement un symbolique. Le mieux que vous puissiez faire est de supprimer l'ancien lien et d'en créer un nouveau. GNU coreutils a une option pour le faire avec une seule commande ( ln -snf), mais il y a toujours deux appels système sous le capot.
Gilles 'SO- arrête d'être méchant'
43

Cela peut en effet être fait de manière atomique rename(2), en créant d'abord le nouveau lien symbolique sous un nom temporaire, puis en écrasant proprement l'ancien lien symbolique en une seule fois. Comme l'indique la page de manuel :

Si newpath fait référence à un lien symbolique, le lien sera écrasé.

Dans le shell, vous le feriez mv -Tcomme suit:

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

Vous pouvez straceutiliser cette dernière commande pour vous assurer qu'elle est bien utilisée rename(2)sous le capot:

$ 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

Notez que dans ce qui précède, les deux mv -Tet stracesont spécifiques à Linux.

Sur FreeBSD, utilisez mv -halternativement.

Arto Bendiken
la source
1
Très agréable! Il pourrait être utile de dire qu'à la fin, vous avez un lien de z à b!
Vincenzo Pii
Pour une solution indépendante du système d'exploitation, utilisez un langage de script capable d'utiliser renamedirectement le syscall au lieu de mv -hou mv -T. Par exemple avec Perl:perl -e 'rename "z.new", "z" or die $!'
Slaven Rezic
8

Reprenant là où Arto s'est arrêté ici, cela est tout à fait possible, même sans mv -T, il vous suffit de créer un nouveau lien symbolique avec le même nom que le répertoire cible et mvdans le répertoire parent de votre cible:

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

Exemple de code pris via ( http://axialcorps.wordpress.com/2013/07/03/atomically-replacing-files-and-directories/ )

mssaxm
la source
3

As-tu essayé ln -snf?

L'option -nécrase la destination plutôt que d'écrire en dessous lorsque la destination est un lien symbolique vers un répertoire.

À votre santé

sokai
la source
3
ln -snfn'est pas atomique: il dissocie la destination, puis crée le lien symbolique souhaité.
Gilles 'SO- arrête d'être méchant'
2
Étant donné que l'OP était intéressé à se rapprocher le plus possible du changement atomique d'un lien symbolique, c'est une réponse parfaitement raisonnable. S'il y en a un meilleur qui peut se rapprocher (ou être) atomique, celui-là peut être accepté. Je ne pense pas qu'il soit nécessaire de diminuer les votes.
Wilco