¿Cómo actualizar la biblioteca compartida sin fallar?

18

Aquí dice que puede reescribir un archivo ejecutable y el proceso se ejecutará bien, se volverá a leer cuando se reinicie un proceso.

Sin embargo, cuando trato de reemplazar un archivo binario mientras se ejecuta el proceso (con scp, desde dev hasta el servidor de prueba) dice 'archivo ocupado'. Y si reemplazo un archivo de biblioteca compartida (* .so), todos los procesos que lo vinculan fallan.

¿Porque? ¿Me estoy perdiendo de algo? ¿Cómo puedo reemplazar los archivos binarios sin detener / bloquear un proceso?

Sam
fuente
Puede verificar el .soarchivo usando ldd filename.sopara verificar las dependencias
Rahul Patil
Conozco las dependencias. Quiero una forma de reemplazar esos archivos sin afectar los procesos en ejecución. Como la pregunta vinculada implica
Sam
se requiere tiempo de inactividad ... o puede hacerlo como stop app && create symlink of .so && start app
Rahul Patil

Respuestas:

21

Como se mencionó en ¿Por qué un paquete de software funciona bien incluso cuando se está actualizando? , el bloqueo se coloca en inode no en nombre de archivo. Cuando carga y ejecuta un archivo binario, el archivo se marca como ocupado, razón por la cual obtiene el error ETXTBSY (archivo ocupado) cuando intenta escribir en él.

Ahora, para las bibliotecas compartidas es ligeramente diferente: las bibliotecas asignan memoria al espacio de direcciones del proceso con mmap(). Aunque MAP_DENYWRITEse puede especificar, al menos Glibc en Linux lo ignora silenciosamente (de acuerdo con la página del manual, no dude en verificar las fuentes) - verifique este hilo . De ahí que en realidad se le permite escribir el archivo y, ya que es la memoria asignada, los cambios son visibles casi de inmediato - que significa que si se esfuerza lo suficiente se pueden gestionar a ladrillo su máquina al sobrescribir la biblioteca.

Por lo tanto, la forma correcta de actualizar es:

  1. eliminar el archivo, que elimina la referencia a los datos del sistema de archivos, de modo que no sea accesible para ninguna aplicación recién generada que pueda querer usarlo, mientras mantiene los datos accesibles para cualquier persona que ya lo tenga abierto (o asignado) ;

  2. creando un nuevo archivo con contenido actualizado.

Los procesos recién creados utilizarán los contenidos actualizados, las aplicaciones en ejecución accederán a la versión anterior. Esto es lo que hace cualquier utilidad de administración de paquetes sensata. Sin embargo, tenga en cuenta que no está completamente libre de peligro: por ejemplo, las aplicaciones que cargan dinámicamente código (usando dlsym()y amigos) experimentarán problemas si la API de la biblioteca cambia en silencio.

Si desea estar realmente seguro, apague el sistema, monte el sistema de archivos desde otra instancia del sistema operativo, actualice y vuelva a abrir el sistema actualizado.

Peterph
fuente
6

Una actualización de rpm hace lo mismo: ejecuta binarios y bibliotecas mientras nada falla.

Entonces cuál es la diferencia:

  1. desvincular archivo
  2. escribir un nuevo archivo con el mismo nombre

Esto NO reemplazará el archivo in situ: el inodo que se refiere al binario en uso todavía está "ocupado" hasta que finalice el último objeto que lo mantiene abierto. El nuevo archivo se creará con un nuevo número de inodo.

Ahora scpo cpintentará reemplazar el archivo en el lugar, lo que cambiaría el contenido al que se refiere el inodo. Esto no funciona, como lo describiste.

Nils
fuente