Respuestas:
Como mencionó @Kusalananda, por lo general, las actualizaciones se realizan eliminando el archivo antiguo y creando uno nuevo con el mismo nombre. En realidad, esto creará un nuevo archivo con un nuevo inodo, dejando al sistema libre para usar el antiguo siempre que esté abierto.
Como ejemplo simplificado, cosas como
rm /bin/cat
cp /new/version/of/cat /bin/cat
creará un archivo lógicamente nuevo y funciona aunque cat
pueda estar ejecutándose. Lo mismo vale para las bibliotecas. (Lo anterior es un ejemplo, no una forma sólida de actualizar un archivo en el mundo real).
Alguien podría intentar cambiar el binario in situ en lugar de crear uno nuevo con el mismo nombre. En este caso, al menos Linux realmente evita realizar cambios en un ejecutable que está en uso:
window 1 # ./cat
window 2 # echo foobar > cat
-bash: cat: Text file busy
Sin embargo, esto no parece funcionar con bibliotecas cargadas dinámicamente ...
Hice una copia libc.so.6
para probar y la llené con ceros mientras estaba en uso:
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
(Mientras tanto, en otra ventana, después de foo
, antes de la segfault)
window 2 /tmp/lib# dd if=/dev/zero of=libc.so.6 bs=1024 count=2000
Realmente no hay nada que el programa en sí pueda hacer contra esto, ya que efectivamente edité su código en línea.
(Esto probablemente dependerá del sistema, probé en Debian Jessie 8.5, Linux 3.16.7-ckt25-2 + deb8u3. Los sistemas Windows IIRC en particular son aún más agresivos para evitar que se modifiquen los archivos en uso).
Entonces, supongo que la respuesta es que las actualizaciones generalmente se realizan de una manera que evita cualquier problema, y esto es ayudado por los componentes internos del sistema de archivos. Pero (en Linux) no parece haber ninguna protección contra la corrupción de las bibliotecas dinámicas.
install
utilidad se usa comúnmente para cosas como esta. No necesita explícitamente rm
el archivo de destino. Además, conserva los permisos del archivo existente, puede hacer una copia de seguridad, establecer un nuevo modo, etc. Ejemplo de uso:install /new/version/of/cat /bin/cat
rm
+ cp
se entiende como un ejemplo. También podría ser inteligente colocar el nuevo archivo atómicamente con un cambio de nombre, para evitar una ventana corta en la que ninguna versión esté disponible. (Aunque GNU install
ni siquiera parece hacer eso, hmpf.)
rm
), aún no se ha eliminado. Existirá en el disco y aún puede ser leído por todos los procesos que lo tienen abierto. Solo se eliminará cuando su recuento de enlaces duros llegue a cero Y el número de precesos con el archivo abierto llegue a cero.
install
utilidad es específicamente insegura! Sobrescribe el archivo de destino en su lugar en lugar de reemplazarlo atómicamente. mv
(con fuente y destino en el mismo directorio, la fuente suele ser un archivo temporal) es la única forma segura de instalar archivos.
strace
, install
en GNU coreutils desvincula el archivo de destino y luego copia uno nuevo en su lugar. Lo que significa que hay una ventana corta durante la cual el archivo es parcial. No establece el archivo atómicamente en su lugar con un cambio de nombre.
Los archivos no se "eliminarán correctamente" si se desvinculan mientras todavía están abiertos. Cuando están cerrados, el espacio en disco que usaron se considerará "libre" nuevamente. Esto también se aplica a las aplicaciones que se ejecutan actualmente y sus bibliotecas compartidas.
Lo único que podría ver fallar sería si un programa solía dlopen()
cargar una biblioteca compartida a pedido, o si el programa tuviera que acceder a otros archivos a pedido, como diccionarios, archivos de temas u otros archivos que desaparecieron repentinamente.
Para ilustrar: la ejecución vim
en una sesión de shell mientras se elimina la instalación de vim
otra sesión de shell no "corromperá" ni terminará la vim
sesión actualmente en ejecución . Pero algunas cosas comenzarán a fallar, como la corrección ortográfica, por ejemplo, que requiere vim
abrir archivos en su instalación.
ln -sf
al intercambiar bibliotecas, ya-f
que le permite "sobrescribir" el destino existente del enlace simbólico con uno nuevo, sin que nunca se "rompa" (a diferencia de si hiciera unrm
seguimiento por aln -s
) Entonces, antes del comando, library.so apuntaba a la versión anterior, por ejemplo. library.so.4 ... después de la orden, se limitó a señalar library.so.5 (o lo que sea) en vez - sin tener que no apunta a una biblioteca válida.