2009-09-06 6 views
18

Je voudrais changer la cible du lien symbolique dans un script bash. Le problème est que le lien symbolique est très important (il est /bin/sh, à savoir) et je le faire de manière que:Remplacer le lien symbolique important 'en toute sécurité'

  1. cible Nouveau sera disponible immédiatement après le retrait de vieux, dire qu'il n'y aura pas de possibilité que quelque chose remarque disparaissant,
  2. Il n'y aura aucune possibilité que le changement échouera au milieu, c'est à dire laisser l'utilisateur avec le lien symbolique supprimé et pas de nouveau.

J'ai pensé à deux méthodes. Soit en utilisant ln simple:

ln -fs /bin/bash /bin/sh 

ou en utilisant mv:

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

Lequel conviendra à mieux mes besoins? Est-il possible que l'un d'entre eux essaie de remplacer la cible de lien symbolique au lieu de lien symbolique lui-même?

Répondre

22

Renommer (mv) est une opération atomique; créer un nouveau lien symbolique ne l'est pas (supprimer le lien symbolique ancien, en créer un nouveau). Vous devez donc utiliser mv:

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

Voici une blog post en discuter. Aussi, si vous êtes inquiet de ce qui va arriver, pourquoi ne pas l'essayer sur un lien symbolique non critique en premier?

+1

Vous ne pouvez pas être sûr qu'il n'y aura pas de problèmes potentiels si vous venez de l'essayer :). Il est très difficile de faire un test pour "quelque chose avis disparaissant ". – Eugene

+1

A propos de l'article de blog - '-T' ne semble pas être une option portable. –

-1

Il semble que (à partir de la page man) ln -f supprime le lien symbolique avant de créer le nouveau, ce qui signifie que mv est la meilleure option pour cela.

Je recommanderais cependant fortement contre reliant /bin/sh à bash. De nombreux scripts utilisent:

#!/bin/sh 

et sont écrits en supposant que le shell est le shell Bourne classique. Si cela devait fonctionner bash à la place, vous pourriez facilement obtenir des incompatibilités obscures entre ce que le script suppose sh fait et bashen fait fait fait. Ceux-ci seront presque impossible à traquer.

+5

Sauf bien sûr pour le fait que sur beaucoup de systèmes,/bin/sh * est * un lien symbolique vers/bin/bash; et lorsqu'il est invoqué à travers, bash entrera en mode de compatibilité sh. –

+0

bash ne peut pas être compatible sh. Essayez ceci dans un vrai sh et dans bash: i = 0; ls | en lisant a; do i = expr $ i + 1; terminé ; echo $ i Si vous faites ne pas avoir un vrai sh, essayez avec ksh Notez que le résultat ci-dessus diffère même parmi les versions sh. Sur solaris le très ancien sh imprime 0, alors que la version xpg4 donne non nul (comme ksh) – Gunstick

+1

@Gun: donc, vous raisonnez que puisque "sh" ne peut pas être "sh" -compatible (c'est ce que vous dites). .. ouais, bien sûr, rien, y compris bash, ne peut être compatible avec tout le comportement indéfini des anciens "sh".Ce que bash * peut * être, cependant, est compatible avec un certain sh-standard communément supposé/accepté/défini. POSIX ou SUSv2 me vient à l'esprit. –