Réponses:
Comme mentionné par @Kusalananda, les mises à niveau sont généralement effectuées en supprimant l'ancien fichier et en créant un nouveau avec le même nom. Cela créera en fait un nouveau fichier avec un nouvel inode, laissant le système libre d'utiliser l'ancien tant qu'il est ouvert.
Comme exemple simplifié, des trucs comme
rm /bin/cat
cp /new/version/of/cat /bin/cat
va créer un nouveau fichier logique et fonctionne même s'il cat
est en cours d'exécution. Il en va de même pour les bibliothèques. (Ce qui précède est un exemple, pas un moyen robuste de mettre à niveau un fichier dans le monde réel.)
Quelqu'un pourrait essayer de changer le binaire en place au lieu d'en créer un nouveau avec le même nom. Dans ce cas, au moins Linux empêche en fait d'apporter des modifications à un exécutable en cours d'utilisation:
window 1 # ./cat
window 2 # echo foobar > cat
-bash: cat: Text file busy
Cependant, cela ne semble pas fonctionner avec les bibliothèques chargées dynamiquement ...
J'ai fait une copie de libc.so.6
pour tester et l' ai remplie de zéros pendant son utilisation:
window 1 /tmp/lib# LD_LIBRARY_PATH=/tmp/lib ldd ./cat
linux-vdso.so.1 (0x00007ffcfaf30000)
libc.so.6 => /tmp/lib/libc.so.6 (0x00007f1145e67000)
/lib64/ld-linux-x86-64.so.2 (0x00007f1146212000)
window 1 /tmp/lib# LD_LIBRARY_PATH=/tmp/lib ./cat
foo
foo
Segmentation fault
(Pendant ce temps dans une autre fenêtre, après le foo
, avant la faute de segmentation)
window 2 /tmp/lib# dd if=/dev/zero of=libc.so.6 bs=1024 count=2000
Il n'y a vraiment rien que le programme lui-même puisse faire contre cela, car j'ai effectivement édité son code en ligne.
(Cela dépendrait probablement du système, j'ai testé sur Debian Jessie 8.5, Linux 3.16.7-ckt25-2 + deb8u3. Les systèmes Windows IIRC en particulier sont encore plus agressifs pour empêcher la modification des fichiers en cours d'utilisation.)
Donc, je suppose que la réponse est que les mises à niveau sont généralement effectuées de manière à éviter tout problème, et cela est aidé par les internes du système de fichiers. Mais (sous Linux) il ne semble pas y avoir de protection contre la corruption des bibliothèques dynamiques.
install
utilitaire est couramment utilisé pour des trucs comme celui-ci. Vous n'avez pas besoin de explicitement rm
le fichier de destination. De plus, il préserve les autorisations du fichier existant, peut faire une sauvegarde, définir un nouveau mode, etc. Exemple d'utilisation:install /new/version/of/cat /bin/cat
rm
+ cp
était donné à titre d'exemple. Il peut également être judicieux de mettre le nouveau fichier en place de manière atomique avec un renommage, afin d'éviter une courte fenêtre dans laquelle aucune version n'est disponible. (Bien que GNU install
ne semble même pas faire ça, hmpf.)
rm
), il n'est pas encore supprimé. Il existera sur le disque et pourra toujours être lu par tous les processus qui l'ont ouvert. Il ne sera supprimé que lorsque son nombre de liens durs atteindra zéro ET que le nombre de précessions avec le fichier ouvert atteindra zéro.
install
utilitaire est particulièrement dangereux! Il écrase le fichier cible en place plutôt que de le remplacer atomiquement. mv
(avec source et dest dans le même répertoire, source généralement un fichier temporaire) est le seul moyen sûr d'installer des fichiers.
strace
dise, install
dans GNU coreutils dissocie le fichier cible, puis copie un nouveau à sa place. Ce qui signifie qu'il y a une courte fenêtre pendant laquelle le fichier est partiel. Il ne définit pas le fichier atomiquement en place avec un renommage.
Les fichiers ne seront pas "correctement supprimés" s'ils ne sont pas liés lorsqu'ils sont encore ouverts. Lorsqu'ils sont fermés, l'espace disque qu'ils ont utilisé sera à nouveau considéré comme "libre". Cela vaut également pour les applications en cours d'exécution et leurs bibliothèques partagées.
La seule chose que je pouvais voir échouer serait si un programme utilisé dlopen()
pour charger une bibliothèque partagée à la demande, ou si le programme devait accéder à d'autres fichiers à la demande tels que des dictionnaires, des fichiers de thème ou d'autres fichiers qui ont soudainement disparu.
Pour illustrer: Exécuter vim
dans une session shell tout en supprimant l'installation de vim
dans une autre session shell ne "corrompra" pas ou ne mettra pas fin à la vim
session en cours d'exécution . Mais certaines choses vont commencer à échouer, comme la vérification orthographique par exemple, qui nécessite vim
d'ouvrir des fichiers dans son installation.
ln -sf
lorsque vous permutez des bibliothèques, car cela-f
vous permet de "remplacer" la destination existante du lien symbolique par une nouvelle, sans qu'il soit jamais "cassé" (contrairement à si vous avez fait unrm
suivi par aln -s
). Donc, avant la commande, library.so pointait vers l'ancienne version, par exemple. library.so.4 ... après la commande, il suffit pointé library.so.5 (ou autre) à la place - sans jamais ne pointant vers une bibliothèque valide.