Linux From Scratch XXXVI: Gestión de paquetes con pacman I

En el anterior artículo sobre Linux From Scratch hemos creado un initrd y arrancado nuestro LFS desde USB. Aunque últimamente me han surgido varios temas y he estado un tiempo sin escribir nada, no me he olvidado. 🙂 En este artículo vamos a instalar pacman, el gestor de paquetes de ArchLinux, que usaremos para hacer gestión de paquetes en nuestro sistema.

Este post iba a ser más largo, pero como no tengo mucho tiempo y se está complicando más de lo esperado, voy a dividirlo en dos partes. En esta primera parte instalaremos los paquetes necesarios y os hablaré de la estructura de la base de datos y la caché de paquetes instalados. En el siguiente artículo, crearemos esa base de datos y esa caché. Hasta que no esté creada al menos la base de datos de paquetes, pacman no funcionará, o sea que de momento no vamos a poder probar nada.

En principio ya hemos cubierto los objetivos del libro Linux From Scratch, así que a partir de aquí todo lo que vamos a instalar va a ser según el libro Beyond Linux From Scratch o según las instrucciones de instalación del paquete que descarguemos. Además de los objetivos de Linux From Scratch, yo tenía mis propios objetivos, los cuales incluían instalar un gestor de paquetes, así que, aunque voy a usar paquetes de Beyond Linux From Scratch, oficialmente todavía no hemos pasado a ese libro. Primero quiero terminar con los objetivos que tenía para éste.

Instalación

Para instalar pacman, lo primero que tenemos que hacer es instalar algunas de sus dependencias que todavía no tenemos en nuestro LFS. Las que necesitamos son libarchive y curl. De momento seguiremos haciendo las instalaciones como siempre, entrando en el chroot desde nuestra distro.

libarchive

En primer lugar, instalamos libarchive siguiendo las instrucciones del libro Beyond Linux From Scratch. Previamente, dscargamos el paquete con wget desde la dirección que nos indica.

[~/lfs]$ sudo lfs libarchive-3.1.2
[root@corellia:/]# cd sources/
[root@corellia:/sources]# wget http://www.libarchive.org/downloads/libarchive-3.1.2.tar.gz
[root@corellia:/sources]# tar xvf libarchive-3.1.2.tar.gz
[root@corellia:/sources]# cd libarchive-3.1.2
[root@corellia:/sources/libarchive-3.1.2]# ./configure --prefix=/usr --disable-static &&
> make
[root@corellia:/sources/libarchive-3.1.2]# make check

Los test pasan sin problemas, así que terminamos la instalación por el método de siempre.

[root@corellia:/sources/libarchive-3.1.2]# make install
[root@corellia:/sources/libarchive-3.1.2]# exit
[~/lfs]$ sudo lfsinst libarchive-3.1.2.txz

curl

Pacman necesita también la librería libcurl, que se instala junto con el paquete curl, así que vamos a instalarlo ahora. Curl también es un paquete de Beyond Linux From Scratch, así que el procedimiento es el mismo que antes.

[~/lfs]$ sudo lfs curl-7.30.0
[root@corellia:/]# cd sources/
[root@corellia:/sources]# wget http://curl.haxx.se/download/curl-7.30.0.tar.bz2
[root@corellia:/sources]# tar xvf curl-7.30.0.tar.bz2
[root@corellia:/sources]# cd curl-7.30.0
[root@corellia:/sources/curl-7.30.0]# sed -i '/--static-libs)/{N;s#echo .*#echo #;}' curl-config.in
[root@corellia:/sources/curl-7.30.0]# ./configure --prefix=/usr              \
>             --disable-static           \
>             --enable-threaded-resolver \
>             --with-ca-path=/etc/ssl/certs
[root@corellia:/sources/curl-7.30.0]# make

El comando sed que lanzamos antes del configure sirve para eliminar las librerías estáticas, ya que no las necesitamos para nada. Para los tests hace falta stunnel. Como no quiero instalar ahora mismo más paquetes de los estrictamente necesarios, no voy a pasar los tests. Procedo directamente con la instalación.

[root@corellia:/sources/curl-7.30.0]# make install
[root@corellia:/sources/curl-7.30.0]# find docs \( -name "Makefile*" -o -name "*.1" -o -name "*.3" \) -exec rm {} \;
[root@corellia:/sources/curl-7.30.0]# install -v -d -m755 /usr/share/doc/curl-7.30.0
[root@corellia:/sources/curl-7.30.0]# cp -v -R docs/* /usr/share/doc/curl-7.30.0
[root@corellia:/sources/curl-7.30.0]# exit
[~/lfs]$ sudo lfsinst curl-7.30.0.txz

El comando find lo que hace es eliminar algunos ficheros de más que se cuelan al instalar la documentación.

pacman

Por fin toca instalar pacman. Para este paquete no hay información en ninguno de los libros de Linux From Scratch, ya que no contempla hacer gestión de paquetes. Ni siquiera he visto nada sobre pacman en el Hints Project. En este caso, tendremos que descargarlo del FTP de ArchLinux y leer la documentación que trae el propio paquete. El resultado es este:

[~/lfs]$ sudo lfs pacman-4.1.0
[root@corellia:/]# cd sources/
[root@corellia:/sources]# wget ftp://ftp.archlinux.org/other/pacman/pacman-4.1.0.tar.gz
[root@corellia:/sources]# tar xvf pacman-4.1.0.tar.gz
[root@corellia:/sources]# cd pacman-4.1.0
[root@corellia:/sources/pacman-4.1.0]# ./configure --prefix=/usr \
>             --sysconfdir=/etc \
>             --localstatedir=/var \
>             --enable-doc
[root@corellia:/sources/pacman-4.1.0]# make

Una vez compilado, hacemos la instalación como siempre.

[root@corellia:/sources/pacman-4.1.0]# make install
[root@corellia:/sources/pacman-4.1.0]# exit
[~/lfs]$ sudo lfsinst pacman-4.1.0.txz

El siguiente paso es configurarlo. Para ello entramos en el chroot y editamos el fichero de configuración de makepkg, que es /etc/makepkg.conf. Makepkg es el programa que usa pacman para compilar los paquetes de código fuente. Como LFS es una distro basada en código fuente, vamos a usarlo bastante.

[~/lfs]$ sudo lfs
[root@corellia:/] vim /etc/makepkg.conf

El primer cambio consiste en modificar las variables CFLAGS, CXXFLAGS y MAKEFLAGS en la sección “ARCHITECTURE, COMPILE FLAGS” poniendo estos valores.

CFLAGS="-march=native -O2 -pipe -fstack-protector --param=ssp-buffer-size=4 -D_FORTIFY_SOURCE=2"
CXXFLAGS="${CFLAGS}"
MAKEFLAGS="-j5"

El valor de MAKEFLAGS depende del número de cores que tengáis. Tenéis que poner uno más que vuestro número de cores. Si vuestro procesador tiene hyperthreading, cada core cuenta por dos. Podéis saber cuántos cores tiene vuestro procesador con el comando:

lscpu | grep '^CPU('

Un poco más abajo, en la sección “PACKAGE OUTPUT“, cambiamos el valor de PACKAGER por uno que identifique a la persona encargada de crear los paquetes. Podéis poner vuestro nick y dirección de email, por ejemplo. Yo he puesto esto:

PACKAGER="hexborg <hexborg@borg.collective.unimatrix.0023>"

Con esto ya lo tenemos configurado, ahora vamos a ver cómo es la información que necesita para funcionar. También veremos la estructura que tienen los paquetes de pacman. Una de las cosas que tendremos que hacer es convertir todos los paquetes que tenemos en paquetes de pacman.

La base de datos de paquetes instalados

Pacman, al igual que todos los gestores de paquetes, necesita guardar información para saber qué paquetes hay instalados y qué características tienen. Normalmente, el propio pacman crea esta información cuando se usa para instalar un paquete, pero el problema es que hemos instalado un montón de paquetes sin haber usado pacman y ahora no sabe nada de esos paquetes, así que hay que crear a mano la base de datos para que sepa lo que tenemos instalado.

La base de datos de paquetes se guarda en el directorio /var/lib/pacman/local. En este directorio hay un subdirectorio por cada paquete que tengamos instalado. El nombre de cada uno de estos subdirectorios está formado por el nombre del paquete seguido por su versión del upstream y de la versión del paquete. Por ejemplo, el nombre xorg-server-1.14.1-1 está formado por estas tres partes:

  • xorg-server: Nombre del paquete que han decidido ponerle los desarrolladores de la distribución. No tiene por qué coincidir con el nombre que le pone el upstream, pero muchas veces coincide.
  • 1.14.1: Versión del paquete en el upstream. Si los desarrolladores de la distro encuentran algún problema y necesitan modificar este paquete, sacarán una versión nueva del paquete, pero siempre será la versión 1.14.1 del servidor gráfico xorg.
  • 1: La versión del paquete en la distro. Si los desarrolladores de la distro sacaran una versión modificada para corregir algún fallo, sería la xorg-server-1.14.1-2.

Aquí hay dos temas importantes. El primero es que el nombre del paquete puede tener guiones, tal como se ve en xorg-server, pero el número de versión no puede contenerlos. El segundo es que cada una de estas tres partes es obligatoria. La versión del paquete siempre es 1 cuando se añade un paquete por primera vez.

Si usáis ArchLinux o alguna derivada o que use pacman, podéis ver el aspecto que tiene la base de datos de paquetes usando este comando:

ls /var/lib/pacman/local

Dentro de cada uno de estos directorios pueden existir los siguientes ficheros:

  • desc: Contiene información con la descripción del paquete. Nombre, versión, dependencias, etc.
  • files: Básicamente es una lista con los ficheros instalados y modificados por el paquete.
  • install: Es un script que define varias funciones que se usan antes y después de instalar, actualizar o desinstalar el paquete.
  • mtree: Contiene metainformación sobre los ficheros del paquete. Propietario, grupo, permisos, etc. Se usa solo para verificar la integridad.

Si vuestra distro usa pacman, podéis curiosear por cada directorio para ver lo que contienen. Vamos a ver cada uno de estos ficheros con más detalle. No todos existen siempre, ya que hay paquetes que no los necesitan. Los únicos obligatorios son desc y files.

El fichero desc

Este fichero está formado por varias secciones de tres lineas cada una. La primera linea es el nombre de sección entre “%“, la segunda linea es el valor asociado a esta sección y la tercera es una linea en blanco de separación. A continuación pongo como ejemplo las primeras lineas del fichero desc de mi xorg-server-1.14.1-1.

%NAME%
xorg-server

%VERSION%
1.14.1-1

%DESC%
Xorg X server

%URL%
http://xorg.freedesktop.org

Es un poco como definir valores para variables, solo que poniendo los valores en una linea separada. Hay secciones que pueden tener más lineas, ya que admiten una lista de valores. Algunas de las secciones que nos podemos encontrar en este fichero son las siguientes:

  • NAME: Es el nombre del paquete igual que figura en la primera parte del nombre del directorio.
  • VERSION: La versión del paquete. Se trata del número completo incluyendo la parte del upstream y la de la distro.
  • DESC: Una linea con una descripción corta del paquete.
  • URL: La URL de la página oficial del paquete desde la que podemos descargarlo o conseguir información.
  • LICENSE: La licencia bajo la que se distribuye el paquete. Esta sección puede tener varias lineas, ya que hay paquetes que se distribuyen bajo varias licencias. Cada licencia se pone en una linea separada.
  • ARCH: La arquitectura para la que ha sido compilado el paquete. Normalmente “i686” o “x86_64“, pero hay paquetes que no necesitan compilarse porque no solo ficheros de datos o scripts. En estos casos, se pone “any“.
  • BUILDDATE: La fecha en la que se compiló el paquete en tiempo UNIX.
  • INSTALLDATE: La fecha en la que se instaló el paquete. También en tiempo UNIX.
  • PACKAGER: El nombre y dirección de la persona responsable de generar y mantener el paquete. Es el mismo que pusimos cuando configuramos makepkg.
  • SIZE: El tamaño que ocupa el paquete en el sistema de ficheros una vez descomprimido. Esto es una aproximación, ya que el tamaño real depende de las características del sistema de ficheros, pero sirve para calcular si hay suficiente espacio libre.
  • REASON: Este campo contiene un valor que codifica la razón por la que se ha instalado el paquete. Por ejemplo, puede ser que se haya instalado porque el usuario lo ha solicitado o como dependencia de algún otro paquete.
  • DEPENDS: Esta es una lista de dependencias del paquete. Esta sección también puede tener varias lineas, una por cada paquete que sea necesario para que este funcione. Opcionalmente, cada linea puede incluir la versión del paquete que necesita para funcionar.

El fichero desc puede tener unas cuantas secciones más, pero para lo que vamos a necesitar con estas son suficientes.

El fichero files

La estructura de este fichero es similar a la de desc, salvo porque en este caso solo hay dos secciones y cada una de ellas contiene una lista de ficheros uno en cada linea. Las secciones son las siguientes:

  • FILES: Lista de ficheros y directorios creados al instalar el paquete con la ruta completa desde la raíz, pero sin incluir la “/” inicial. Por ejemplo: “usr/bin/makepkg“.
  • BACKUP: Lista de ficheros y directorios modificados al instalar el paquete. En el mismo formato que los de FILES.

El fichero install

Este fichero es un script bash que no contiene directamente código ejecutable, sino que define una serie de funciones que pacman va a llamar cuando las necesite. Este fichero es opcional, ya que no todos los paquetes tienen por qué necesitarlo. En nuestro caso no lo vamos a crear. Las funciones que puede contener son las siguientes:

  • pre_install: Esta función se llama antes de instalar el paquete. Se le pasa como parámetro el numero de versión del paquete que se está instalando.
  • post_install: Esta función es llamada después de hacer la instalación. También recibe como parámetro la versión del paquete.
  • pre_upgrade: Pacman llama a esta función antes de hacer una actualización del paquete. A esta función se le pasan dos parámetros: el número de versión del nuevo paquete que se instala y el número del versión que ya estaba instalado.
  • post_upgrade: A esta función se la llama después de actualizar el paquete. Recibe los mismos dos parámetros que pre_upgrade.
  • pre_remove: Llamada antes de eliminar un paquete de nuestro sistema. El parámetro que recibe es el número de versión del paquete que se está eliminando.
  • post_remove: Por último, esta función es llamada despues de eliminar el paquete. Es parámetro que recibe es el mismo que el de pre_remove.

No todas las funciones tienen por qué existir. Solo las que el paquete necesite. También puede haber más funciones que vayan a ser llamadas desde estas e incluso variables que puedan necesitar. Como ejemplo pongo el de mi versión de nano:

infodir=/usr/share/info
filelist=(nano.info.gz)

post_install() {
  [ -x usr/bin/install-info ] || return 0
  for file in ${filelist[@]}; do
    install-info $infodir/$file $infodir/dir 2> /dev/null
  done
}

post_upgrade() {
  post_install $1
}

pre_remove() {
  [ -x usr/bin/install-info ] || return 0
  for file in ${filelist[@]}; do
    install-info --delete $infodir/$file $infodir/dir 2> /dev/null
  done
}

El fichero mtree

Este fichero no es obligatorio y nosotros no lo vamos a crear. Contiene metainformación sobre cada uno de los ficheros del paquete. Cosas como el propietario, el grupo, los permisos, sumas de control, etc. Un fichero por linea. Se trata de un fichero de texto comprimido con gzip, así que para verlo tenéis que usar un comando como este:

zless /var/lib/pacman/local/xorg-server-1.14.1-1/mtree

La cache de paquetes

Sobre la caché de paquetes no voy a decir mucho. Se trata de un directorio en el que pacman guarda todos los paquetes que va descargando del repositorio. Está en /var/cache/pacman/pkg y no tiene ninguna estructura extrana. Simplemente es un directorio en el que se guardan los paquetes descargados tal cual.

En nuestro caso, todavía no tenemos un repositorio remoto, así que la vamos a usar como almacen de paquetes instalados. Por si queremos desinstalar algo y volver a instalarlo más tarde. Por supuesto, podríamos guardar los paquetes en cualquier otro sitio, pero creo que está bien que estén en la caché. Es el lugar para ello. Aunque si tenemos poco espacio en el disco es normal que queramos borrar la caché. Suele ser una de las cosas que más crece.

Si tenéis una ArchLinux podéis comprobar cómo es esta caché con el siguiente comando:

ls /var/cache/pacman/pkg

Estructura de los paquetes

Otra cosa que tenemos que hacer es convertir los paquetes que tenemos en paquetes de pacman. De momento solo son archivos comprimidos que contienen todos los ficheros y directorios creados al instalar cada programa con sus rutas completas desde la raíz, pero un paquete de pacman tiene un poco más de información.

Además de estos ficheros, un paquete de pacman tiene algunos ficheros más. Se trata de ficheros ocultos, de los que empiezan por “.”, que contienen información similar a la que os he comentado sobre la base de datos de paquetes instalados. Vamos a ver cómo son estos ficheros:

  • .PKGINFO: Este fichero contiene información similar a la del fichero desc de la base de datos de paquetes. No todos los campos existen, porque algunos no tienen sentido en el interior de un paquete. Además el formato es completamente diferente, pero la información es más o menos la misma. Más abajo os hablaré de él con más detalle.
  • .INSTALL: El contenido de este fichero es exactamente el mismo que el del fichero install de la base de datos de paquetes. Contiene los mismos scripts y de la misma manera. Pacman copia este fichero a la base de datos de paquetes al instalar el paquete.
  • .MTREE: Del mismo modo que .INSTALL, este fichero es exactamente igual que el fichero mtree de la base de datos de paquetes. Pacman también lo copia al hacer la instalación.

Los dos últimos ficheros no son imprescindibles y no todos los paquetes los contienen. El único obligatorio es .PKGINFO. Los que tenéis ArchLinux u alguna otra distro que use pacman podéis comprobar de primera mano el aspecto que tiene un paquete usando un comando similar a este:

sudo bash -c "tar tJf /var/cache/pacman/pkg/xorg-server-1.14.1-1-x86_64.pkg.tar.xz | less"

Si queréis, podéis descomprimir alguno de estos paquetes en un directorio aparte y curiosear un poco para ver cómo son los ficheros que contiene. Es necesario usar root para esto, estos ficheros no tienen permisos para un usuario normal.

El fichero .PKGINFO

De los tres ficheros que os he comentado, el único interesante en .PKGINFO, ya que los otros dos son copias exactas de los de la base de datos, así que os voy a comentar ahora la estructura que tiene.

Este fichero esta formado por varias lineas, cada una de las cuales es el nombre de una variable seguida de un signo “=” y su valor. En los casos en los que la variable puede tener varios valores, habrá una linea por cada valor. Cada una de estas lineas empieza por el nombre de la variable y el signo “=“, de manera que parece como si estuviera asignando varios valores a la variable. Esto es posible porque este fichero en realidad no es un script, sino un fichero que pacman puede procesar. También pueden existir lineas con comentarios empezando por “#“.

Como ejemplo, os pongo el .PKGINFO que pertenece al paquete tar que tengo actualmente en mi arch. No lo voy a poner entero. Solo las lineas más relevantes. Ya se puede ver cómo las dependencias van en dos lineas.

# Generated by makepkg 4.1.0
# using fakeroot version 1.18.4
# Tue Apr 16 04:28:14 UTC 2013
pkgname = tar
pkgver = 1.26-3
pkgdesc = Utility used to store, backup, and transport files
url = http://www.gnu.org/software/tar/tar.html
builddate = 1366086494
packager = Allan McRae <allan@archlinux.org>
size = 2448384
arch = x86_64
license = GPL3
depend = glibc
depend = sh

Las variables más importantes que podemos encontrar en este fichero son las siguientes:

  • pkgname: El nombre del paquete. Igual que %NAME% en el desc.
  • pkgver: La versión. Como %VERSION%.
  • pkgdesc: La descripción corta del paquete. Es la misma que aparece en %DESC% en el fichero desc.
  • url: La URL en la que se puede encontrar el paquete. Igual que %URL%.
  • builddate: La fecha de creación del paquete. Corresponde a %BUILDDATE% en el desc.
  • packager: El responsable de mantener el paquete. El mismo dato que aparece en %PACKAGER% en el desc.
  • size: El tamaño aproximado del paquete una vez instalado. Como %SIZE% en el desc.
  • arch: La arquitectura para la cual ha sido generado el paquete siguiendo la misma lógica que os he contado cuando os hablé de %ARCH% en el desc.
  • license: La licencia bajo la que se distribuye el paquete. Corresponde a %LICENSE% en el desc y puede repetirse a lo largo de varias lineas en caso de que el paquete se distribuya bajo más de una licencia.
  • depend: Las dependencias del paquete una en cada linea. Como %DEPENDS% en el desc. Es curioso ver que en los demas casos el nombre de las variables de este fichero coincide con las secciones del desc, pero en este cambia. En el desc, el nombre de la sección termina en “S” mientras que aquí no.

Como en el caso del desc, hay más posibles variables, pero no las voy a comentar porque de momento no son importantes para lo que queremos. Hay que destacar el hecho de que no todas las secciones del fichero desc aparecen en el .PKGINFO. Por ejemplo, no están ni %INSTALLDATE% ni %REASON%. Eso es porque la información que aparece en ellas está relaccionada con el momento de la instalación y, por lo tanto, no tiene sentido que esté en el paquete, ya que al crear el paquete todavía no se conoce.

Por ahora nada más. En el próximo artículo, que espero no tardar mucho en publicar, crearemos la base de datos de paquetes y la cache. Con eso ya podremos hacer algunas pruebas con pacman. Sí que me ha quedado largo el post. Menos mal que lo he dividido en dos partes. 🙂

EOF

Anuncios