Product SiteDocumentation Site

5.2. Metainformación de un paquete

Un paquete Debian no es sólo un compendio de archivos a instalar. Forma parte de un todo más grande y describe su relación con otros paquetes Debian (requisitos, dependencias, conflictos, sugerencias). También provee scripts que permiten la ejecución de órdenes en diferentes etapas del ciclo de vida del paquete (instalación, actualización, eliminación). Estos datos utilizados por las herramientas de gestión de paquetes no son parte del software empaquetado, son lo que se denomina «metainformación» (información sobre otra información) dentro del paquete.

5.2.1. Descripción: el archivo control

Este archivo usa una estructura similar a las cabeceras de correo electrónico (según define RFC 2822) y se describe con detalle en la Normativa de Debian y en las páginas de manual deb-control(5) y deb822(5).
Por ejemplo el archivo control de apt se ve de la siguiente forma:
$ apt-cache show apt
Package: apt
Architecture: amd64
Version: 2.6.1
Priority: required
Section: admin
Maintainer: APT Development Team <deity@lists.debian.org>
Installed-Size: 4232
Provides: apt-transport-https (= 2.6.1)
Depends: adduser, gpgv | gpgv2 | gpgv1, libapt-pkg6.0 (>= 2.6.1), debian-archive-keyring, libc6 (>= 2.34), libgcc-s1 (>= 3.0), libgnutls30 (>= 3.7.5), libseccomp2 (>= 2.4.2), libstdc++6 (>= 11), libsystemd0
Recommends: ca-certificates
Suggests: apt-doc, aptitude | synaptic | wajig, dpkg-dev (>= 1.17.2), gnupg | gnupg2 | gnupg1, powermgmt-base
Breaks: apt-transport-https (<< 1.5~alpha4~), apt-utils (<< 1.3~exp2~), aptitude (<< 0.8.10)
Replaces: apt-transport-https (<< 1.5~alpha4~), apt-utils (<< 1.3~exp2~)
Filename: pool/main/a/apt/apt_2.6.1_amd64.deb
Size: 1372852
MD5sum: 2a077296b9b9f4f8b027f86d9500192b
SHA256: 6ea03cbbc7a7bfcee601c9fb08d4e026fd522ede5350561f06867ad9c0a0fa6b
Description-en: commandline package manager
 This package provides commandline tools for searching and
 managing as well as querying information about packages
 as a low-level access to all features of the libapt-pkg library.
 .
 These include:
  * apt-get for retrieval of packages and information about them
    from authenticated sources and for installation, upgrade and
    removal of packages together with their dependencies
  * apt-cache for querying available information about installed
    as well as installable packages
  * apt-cdrom to use removable media as a source for packages
  * apt-config as an interface to the configuration settings
  * apt-key as an interface to manage authentication keys
Description-md5: 9fb97a88cb7383934ef963352b53b4a7
Tag: admin::package-management, devel::lang:ruby, hardware::storage,
 hardware::storage:cd, implemented-in::c++, implemented-in::perl,
 implemented-in::ruby, interface::commandline, network::client,
 protocol::ftp, protocol::http, protocol::ipv6, role::program,
 scope::application, scope::utility, suite::debian, use::downloading,
 use::organizing, use::playing, use::searching, works-with-format::html,
 works-with::audio, works-with::software:package, works-with::text
Echemos una cuidadosa mirada al propósito de algunos de los campos enumerados en el comando anterior.

5.2.1.1. Dependencias: el campo Depends

Las dependencias están definidas en el campo Depends en la cabecera del paquete. Es una lista de condiciones a cumplir para que el paquete funcione correctamente. Las herramientas como apt utilizan esta información para instalar las bibliotecas, herramientas, controladores, etc. necesarios, en versiones apropiadas para satisfacer las dependencias del paquete a instalar. Para cada dependencia es posible restringir el rango de versiones que cumplen dicha condición. En otras palabras, es posible expresar el hecho de que necesitamos el paquete libc6 en una versión igual o mayor a «2.15» (escrito como «libc6 (>= 2.15)». Los operadores de comparación de versiones son los siguientes:
  • <<: menor que;
  • <=: menor o igual que;
  • =: igual a (note que «2.6.1» no es igual a «2.6.1-1»);
  • >=: mayor o igual que;
  • >>: mayor que.
En una lista de condiciones a cumplir, la coma sirve como separador. Debe interpretarse como un «and» lógico. En las condiciones una barra vertical («|») expresa un «or» lógica (es un «or» inclusivo, no un exclusivo “either/or”). Tiene más prioridad que «and» y se puede usar tantas veces como sea necesario. Por lo tanto, la dependencia «(A o B) y C» se escribe A | B, C. Por otro lado, la expresión «A o (B y C)» debe escribirse «(A o B) y (A o C)» ya que el campo Depends no permite paréntesis que cambien el orden de las prioridades entre los operadores lógicos «or» e «and». Por lo tanto, se escribiría A | B, A | C.
El sistema de dependencias es un buen mecanismo para garantizar el funcionamiento de un programa, pero tiene otro uso con los «metapaquetes». Éstos son paquetes vacíos que sólo describen dependencias. Facilitan la instalación de un grupo consistente de programas preseleccionados por el desarrollador del metapaquete; como tal apt install meta-package instalará automáticamente todos estos programas utilizando las dependencias del metapaquete. Los paquetes gnome, kde-full y linux-image-amd64, por ejemplo, son metapaquetes.

5.2.1.2. Conflictos: el campo Conflicts

El campo Conflicts indica que un paquete no puede instalarse simultáneamente con otro. La razón más común es que ambos paquetes contienen un archivo con el mismo nombre y ruta, proveen el mismo servicio en el mismo puerto TCP o estorban el funcionamiento del otro.
dpkg se negará a instalar un paquete si genera un conflicto con un paquete ya instalado, excepto si el nuevo paquete especifica que «reemplazará» al paquete instalado en cuyo caso dpkg elegirá reemplazar el paquete existente con el nuevo. apt siempre seguirá sus instrucciones: si desea instalar un nuevo paquete ofrecerá automáticamente desinstalar el paquete que genera problemas.

5.2.1.3. Incompatibilidades: el campo Breaks

El campo Breaks tiene un efecto similar al del campo Conflicts pero con un significado especial. Indica que la instalación de un paquete «romperá» otro paquete (o versiones particulares del mismo). En general, esta incompatibilidad entre dos paquetes es temporal y la relación Breaks se refiere específicamente a las versiones incompatibles.
dpkg se negará a instalar un paquete que rompe un paquete ya instalado y apt intentará resolver el problema actualizando a una nueva versión el paquete que se rompería (que se asume estaría arreglado y, por lo tanto, sería compatible nuevamente).
Este tipo de situaciones pueden ocurrir en casos de actualizaciones que no sean compatibles con versiones anteriores: este es el caso si una nueva versión ya no funciona con la versión anterior y causa un mal funcionamiento en otros programas si no se toman medidas especiales. El campo Breaks previene que el usuario se tope con estos problemas.

5.2.1.4. Elementos provistos: el campo Provides

Este campo introduce el concepto interesante de un «paquete virtual». Tiene muchos roles pero hay dos particularmente importantes. El primero consiste en utilizar un paquete virtual para asociar un servicio genérico con él (el paquete «provee» el servicio). El segundo indica que un paquete reemplaza completamente a otro y, para esos propósitos, también puede satisfacer las dependencias que otros satisfacen. Es posible, entonces, crear un paquete substituto sin tener que utilizar el mismo nombre de paquete.
5.2.1.4.1. Proveyendo un «servicio»
Discutamos con más detalles el primer caso con un ejemplo: se dice que todos los servicios de correo, como postfix o sendmail «proveen» el paquete virtual mail-transport-agent. Por lo tanto, cualquier paquete que necesite este servicio para funcionar (por ejemplo, un gestor de listas de correo como smartlist o sympa) simplemente indican en sus dependencias que requieren de mail-transport-agent en lugar de especificar una lista larga y aún incompleta de posibles soluciones (por ejemplo postfix | sendmail | exim4 | ...). Lo que es más, es inútil instalar dos servidores de correo en el mismo equipo, por lo que cada uno de estos paquetes declara un conflicto con el paquete virtual mail-transport-agent. Un conflicto de un paquete con sí mismo es ignorado por el sistema, pero esta técnica prohibirá la instalación de dos servidores de correo simultáneamente.
5.2.1.4.2. Intercambio con otro paquete
The Provides field is also interesting when the content of a package is included in a larger package. For example, the libdigest-md5-perl Perl module was an optional module in Perl 5.6, and has been integrated as standard in Perl 5.8 (and later versions, such as 5.36.0 present in Bookworm). As such, the package perl has since version 5.8 declared Provides: libdigest-md5-perl so that the dependencies on this package are met if the user has Perl 5.8 (or newer). The libdigest-md5-perl package itself has eventually been deleted, since it no longer had any purpose when old Perl versions were removed.
Utilización del campo Provides para no romper dependencias

Figura 5.1. Utilización del campo Provides para no romper dependencias

Esta funcionalidad es muy útil ya que nunca es posible anticipar los caprichos del desarrollo y es necesario que sea posible adaptarse a cambios de nombre y otros reemplazos automáticos de software obsoleto.
5.2.1.4.3. Limitaciones anteriores
Los paquetes virtuales solían sufrir algunas limitaciones, la más importante de ellas era la ausencia de un número de versión. Volviendo al ejemplo anterior, una dependencia como Depends: libdigest-md5-perl (>= 1.6) nunca se considerará como satisfecha por el sistema de empaquetado aún en presencia de Perl 5.10 — aunque de hecho es más que probable que esté satisfecha. Desconociendo esto el sistema de paquetes selecciona la opción menos arriesgada, asumiendo que las versiones no coinciden.
This limitation has been lifted in dpkg 1.17.11, and is no longer relevant. Packages, like perl 5.36.0, can assign a version to the virtual packages they provide, such as Provides: libdigest-md5-perl (= 2.58), and thus allow other packages to use versioned dependencies.

5.2.1.5. Reemplazo de archivos: el campo Replaces

El campo Replaces indica que el paquete contiene archivos que también están presentes en otro paquete, pero que el paquete tiene derecho legítimo a reemplazarlos. Sin esta especificación, dpkg falla al instalar el paquete, indicando que no puede sobrescribir los archivos de otro paquete (técnicamente, es posible forzarlo a hacerlo con la opción --force-overwrite, pero no se considera una operación estándar). Esto permite identificar problemas potenciales y requiere que el mantenedor estudie el asunto antes de elegir si añadir o no dicho campo.
El uso de este campo está justificado cuando cambian los nombres de los paquetes o cuando un paquete está incluido en otro. Esto sucede cuando el desarrollador decide distribuir los archivos de otra forma entre los varios paquetes binarios producidos del mismo paquete fuente: un archivo reemplazado no le corresponde al paquete antiguo, sólo al nuevo.
Si todos los archivos de un paquete instalado fueron reemplazados, se considera que se eliminó el paquete. Finalmente, este campo incita que dpkg elimie los paquetes reemplazados en casos de conflictos.

5.2.2. Scripts de configuración

Además del archivo control, el compendio control.tar.gz de cada paquete Debian puede contener una cantidad de scripts que serán ejecutados por dpkg en diferentes etapas del procesamiento de un paquete. La Normativa Debian describe los casos posibles en detalle, especificando los scripts que serán llamados y los argumentos que recibirán. Estas secuencias pueden ser complicadas ya que si falla uno de los scripts dpkg intentará volver a un estado satisfactorio cancelando la instalación o eliminación en curso (siempre que sea posible).
En general, se ejecuta el script preinst antes de la instalación del paquete, y postinst luego. De la misma forma, se invoca prerm antes de la eliminación de un paquete y postrm luego. Actualizar un paquete es equivalente a eliminar la versión anterior e instalar la nueva. No es posible describir en detalle todos los escenarios posibles aquí, pero discutiremos los dos más comunes: instalación/actualización y eliminación.

5.2.2.1. Instalación y actualización

Durante la instalación inicial y para cada actualización de un paquete, dpkg llama a los llamados scripts de mantenimiento, como prerm o scripts preinst. Estos scripts pueden realizar acciones adicionales durante las diferentes etapas del ciclo de vida de un paquete. Los nombres de los scripts precedidos por new- son los scripts de la nueva versión de un paquete que se está instalando o actualizando. Los nombres de los scripts precedidos por old- son los scripts de la versión antigua de un paquete desde el que se está actualizando.
Durante cada invocación, dpkg pasará ciertos argumentos a cada script, como upgrade nueva-versión. El script invocado puede entonces manejar los argumentos y realizar una acción particular, o ignorar los argumentos y regresar con un código de salida de 0, si no es necesario hacer nada durante ese paso. En la práctica, muchos paquetes no necesitarán realizar una acción durante cada paso del ciclo de vida. Por lo tanto, un script de configuración típico buscará un argumento en particular e ignorará todos los demás, regresando implícitamente con el código de salida 0.
Esto es lo que sucede durante una instalación (o actualización). Los argumentos old-version, new-version y last-version-configured son marcadores de posición para los números de versión reales (antiguos y nuevos) del paquete:
  1. Para una actualización, dpkg llama al script old-prerm y pasa upgrade new-version como argumentos.
  2. Aún para una actualización, dpkg luego ejecuta el script new-preinst con los argumentos upgrade old-version; para la instalación inicial, ejecuta el script new-preinst y pasa install como argumento. Se puede agregar la versión anterior en el último parámetro, si el paquete ya se instaló y eliminó desde entonces (pero no se eliminó y, por lo tanto, se conservaron los archivos de configuración).
  3. Se descomprimen los archivos del nuevo paquete. Si un archivo ya existe, es reemplazado pero se guarda una copia de respaldo de forma temporal.
  4. Para una actualización, dpkg ejecutar el script old-postrm y pasar upgrade new-version como argumentos.
  5. dpkg actualiza toda su información interna (lista de archivos, scripts de configuración, etc.) y elimina los respaldos de los archivos reemplazados. Este es el punto sin retorno: dpkg ya no tiene acceso a todos los elementos necesarios para volver al estado anterior.
  6. dpkg actualizará los archivos de configuración, pidiéndole al usuario que decida si no es capaz de administrar esta tarea automáticamente. Los detalles de este proceso son discutidos en la Sección 5.2.3, “Sumas de comprobación, lista de archivos de configuración y más.”.
  7. Finalmente, dpkg configura el paquete ejecutando el script new-postinst con los argumentos configure last-version-configured .

5.2.2.2. Eliminación de un paquete

Los pasos para eliminar un paquete son análogos a los pasos de instalación. La principal diferencia es que los scripts de eliminación del paquete se llaman:
  1. dpkg llama al script prerm y pasa el argumento remove.
  2. dpkg elimina todos los archivos del paquete, con la excepción de los archivos de configuración y scripts de mantenimiento.
  3. dpkg ejecuta el script postrm y pasa remove como argumento. Después, se eliminan todos los scripts de mantenimiento, excepto el script postrm. Si el usuario no ha utilizado la opción “purgar”, el proceso se detiene aquí.
  4. Para eliminar completamente un paquete (con la orden dpkg --purge o dpkg -P), los archivos de configuración también son eliminados junto con una cantidad de copias (*.dpkg-tmp, *.dpkg-old, *.dpkg-new) y archivos temporales; dpkg luego ejecuta el script postrm y pasa purge como argumento.
Los cuatro scripts que aparecen detallados anteriormente se complementan con un script config provisto por los paquetes que utilizan debconf para adquirir información de configuración del usuario. Durante la instalación este script define en detalle las preguntas realizadas por debconf. Se graban las respuestas en la base de datos de debconf para futuras referencias. Generalmente apt ejecuta el script antes de instalar los paquetes uno por uno para agrupar las preguntas y realizarlas todas al usuario al comienzo del proceso. Los scripts de pre y postinstalación pueden utilizar esta información para operar según los deseos del usuario.

5.2.3. Sumas de comprobación, lista de archivos de configuración y más.

Además de los scripts de mantenimiento y los datos de control ya mencionados en las secciones anteriores, el archivo control.tar.gz de un paquete Debian puede contener otros archivos interesantes.
El primer, md5sums contiene una lista sumas de verificación MD5 de todos los archivos del paquete. Su principal ventaja es que permite que dpkg-verify (que estudiaremos en Sección 14.3.4.1, “Auditoría de paquetes mediante dpkg --verify) y debsums (del paquete homónimo; ver Sección 14.3.4.2, “Auditoría de paquetes: debsums y sus límites”) chequear si estos archivos fueron modificados desde su instalación. Tener en cuenta que cuando este archivo no existe, lo que podría ser el caso de algunos paquetes más antiguos, dpkg lo generará dinámicamente en el momento de la instalación (y lo almacenará en la base de datos dpkg como otros archivos de control).
conffiles enumera los archivos del paquete que tienen que administrarse como archivos de configuración (ver también deb-conffiles(5)). El administrador puede modificar los archivos de configuración y dpkg intentará preservar estos cambios durante la actualización de un paquete.
De hecho, en esta situación, dpkg se comporta tan inteligentemente como le es posible: si el archivo de configuración estándar no fue modificado entre dos versiones, no hace nada. Si, sin embargo, el archivo cambió intentará actualizar este archivo. Son posibles dos casos: o bien el administrador no modificó el archivo, en cuyo caso dpkg automáticamente instalará la nueva versión; o el archivo fue modificado, en cuyo caso dpkg le preguntará al administrador qué versión desea utilizar (la antigua con modificaciones o la nueva provista con el paquete). Para asistirlo en esta decisión dpkg ofrece mostrar las diferencias entre las dos versiones («diff»). Si el usuario decide mantener la versión anterior, la nueva será almacenada en la misma ubicación con el sufijo .dpkg-dist. Si el usuario selecciona la nueva versión, se mantiene la versión anterior en la misma ubicación con el sufijo .dpkg-old. Otra acción posible consiste en interrumpir momentáneamente dpkg para editar el archivo e intentar rehacer las modificaciones relevantes (identificadas previamente con diff).
Con frecuencia, el archivo de control también contiene otros archivos, como triggers, shlibs o symbols. Estos ficheros están bien descritos en deb-triggers(5), deb-shlibs(5) y deb-symbols(5).
Triggers were introduced to reduce the amount of duplicated events during package installation, such as file registration or catalog/database update tasks. Packages can define their own or activate defined triggers. A more comprehensive documentation can be found in /usr/share/doc/dpkg/triggers.txt.gz.
El sistema shlibs es una alternativa más antigua y sencilla al sistema symbols para declarar dependencias para bibliotecas compartidas. Define el nombre del paquete y la versión en la que encontrar una versión SONAME específica de una biblioteca compartida. El sistema symbols más nuevo permite definir la dependencia mediante el seguimiento de los símbolos y cuándo se han introducido o modificado en la biblioteca.