Product SiteDocumentation Site

5.2. Metainformación de un paquete

Un paquete Debian no es sólo un compendio de archivos a instalar. Es parte de un todo más grande y describe su relación con otros paquetes Debian (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, eliminación, actualizació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 utiliza una estructura similar a las cabeceras de email (definidas en RFC 2822). Por ejemplo el archivo control de apt se ve de la siguiente forma:
$ apt-cache show apt
Package: apt
Version: 1.0.9.6
Installed-Size: 3788
Maintainer: APT Development Team <deity@lists.debian.org>
Architecture: amd64
Replaces: manpages-it (<< 2.80-4~), manpages-pl (<< 20060617-3~), openjdk-6-jdk (<< 6b24-1.11-0ubuntu1~), sun-java5-jdk (>> 0), sun-java6-jdk (>> 0)
Depends: libapt-pkg4.12 (>= 1.0.9.6), libc6 (>= 2.15), libgcc1 (>= 1:4.1.1), libstdc++6 (>= 4.9), debian-archive-keyring, gnupg
Suggests: aptitude | synaptic | wajig, dpkg-dev (>= 1.17.2), apt-doc, python-apt
Conflicts: python-apt (<< 0.7.93.2~)
Breaks: manpages-it (<< 2.80-4~), manpages-pl (<< 20060617-3~), openjdk-6-jdk (<< 6b24-1.11-0ubuntu1~), sun-java5-jdk (>> 0), sun-java6-jdk (>> 0)
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,
 role::shared-lib, scope::application, scope::utility, sound::player,
 suite::debian, use::downloading, use::organizing, use::searching,
 works-with::audio, works-with::software:package, works-with::text
Section: admin
Priority: important
Filename: pool/main/a/apt/apt_1.0.9.6_amd64.deb
Size: 1107560
MD5sum: a325ccb14e69fef2c50da54e035a4df4
SHA1: 635d09fcb600ec12810e3136d51e696bcfa636a6
SHA256: 371a559ce741394b59dbc6460470a9399be5245356a9183bbeea0f89ecaabb03

5.2.1.1. Dependencias: el campo Depends

Las dependencias están definidas en el campo Depends en la cabecera del paquete. Esta 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 necesarias, las 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 interpretársela como un «y» lógico. En las condiciones una barra vertical («|») expresa un «o» lógico (es un «o» inclusivo, no uno exclusivo que significa «o uno o el otro»). Tiene más prioridad que «y» y puede ser utilizado 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 «o» e «y». Por lo tanto, se lo 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 metapaquete 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, 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
El campo Provides es tambien interesante cuando se incluye el contenido del paquete en un paquete más grande. Por ejemplo, el módulo Perl libdigest-md5-perl era un módulo opcional en Perl 5.6 y fue integrado como estándar en Perl 5.8 (y versiones siguientes, como 5.20 que está presente en Jessie). Como tal, el paquete perl desde su versión 5.8 declara Provides: libdigest-md5-perl para que se cumplan las dependencias de este paquete si el usuario tiene Perl 5.8 (o una versión más reciente). El paquete libdigest-md5-perl en sí fue eventualmente eliminado ya que no tenía propósito cuando las versiones antiguas de Perl fueron retiradas.
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 será considerada como satisfecha aún en presencia de Perl 5.10 — cuando de hecho es altamente probable que esté satisfecha. Sin conocimientos de esto el sistema de paquetes selecciona la opción menos riesgosa y asume que las versiones no coinciden.
Esta limitación ha sido levantada dpkg 1.17.11 y ya no es más relevante en Jessie. Los paquetes pueden asignar una una versión a los paquetes virtuales que proveen con una dependencia como Provides: libdigest-md5-perl (= 1.8).

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 el derecho legítimo de reemplazarlo. Sin esta especificación, dpkg fallará indicando que no puede sobreescribir los archivos de otro paquete (técnicamente es posible forzar que lo haga con la opción --force-overwrite, pero no se considera una operación estándar). Esto permite identificar problemas potenciales y requiere que el desarrollador estudie el hecho antes de decidir agregar 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

Esto es lo que ocurre durante una instalación (o actualización):
  1. En una actualización, dpkg ejecuta old-prerm upgrade nueva-versión.
  2. En una actualización dpkg ejecuta luego new-preinst upgrade antigua-versión; para una primera instalación ejecuta new-preinst install. También puede agregar la versión anterior en el último parámetro si el paquete ya ha sido instalada y eliminada desde entonces (pero no purgada, se mantuvieron 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. En una actualización, dpkg ejecuta old-postrm upgrade nueva-versión.
  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 verificación («checksum»), lista de archivos de configuración”.
  7. Finalmente, dpkg configura el paquete ejecutando new-postinst configure última-versión-configurada.

5.2.2.2. Eliminación de un paquete

Esto es lo que sucede durante la eliminación de un paquete:
  1. dpkg ejecuta prerm remove.
  2. dpkg elimina todos los archivos del paquete, con la excepción de los archivos de configuración y scripts de configuración.
  3. dpkg ejecuta postrm remove. Se eliminan todos los scripts de configuración excepto postrm. Si el usuario no utilizó la opción «purgar» («purge»), el proceso termina 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; luego dpkg ejecuta postrm purge.
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 verificación («checksum»), lista de archivos de configuración

Además de los scripts de gestión y los datos de control mencionados en las secciones anteriores, el compendio control.tar.gz en un paquete Debian puede contener otros archivos interesantes. El primero, 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 la Sección 14.3.3.1, “Auditoría de paquetes mediante dpkg --verify) chequee si estos archivos fueron modificados desde su instalación. Sepa que cuando este archivo no existe, dpkg lo generará dinámicamente en el momento de la instalación (y lo almacenará en la base de datos de dpkg al igual que cualquier otro archivo de control).
conffiles enumera los archivos del paquete que tienen que administrarse como archivos de configuración. 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).