En esta entrada vamos a ver los pasos necesarios para crear nuestro propio paquete rpm (Red Hat Package Manager). En este caso se trata de un paquete muy sencillo que únicamente va a tener un script ejecutable y unos ficheros extra de configuración, pero una vez que sabemos como hacerlo podemos hacer paquetes muchos más complejos y similares a los reales que nos podemos encontrar en cualquier repositorio.
Lo primero es instalar los paquetes y herramientas necesarias para poder crear rpms (rpm-build y rpmdevtools):
# yum install rpm-build rpmdevtools -y
Vamos a trabajar con un usuario sin privilegios y comenzamos creando una carpeta en nuestra home que contendrá los ficheros que formarán el RPM:
$ ls -l test-package-1.0/ total 8 -rw-rw-r--. 1 alex alex 27 Nov 10 16:04 README.txt -rw-rw-r--. 1 alex alex 92 Nov 10 16:06 test-check -rwxr--r--. 1 alex alex 0 Nov 10 16:38 configure
Como podéis ver simplemente he creado un fichero de texto README.txt y un script en bash llamado «test-check». El fichero configure es necesario aunque no vayamos a compilar nada de código fuente, si no lo incluís os aparecerá un error al crear el RPM:
/var/tmp/rpm-tmp.zzXus7: line 32: ./configure: No such file or directory error: Bad exit status from /var/tmp/rpm-tmp.zzXus7 (%build)
$ touch configure $ chmod 0744 configure
Esto va a ser todo lo que contendrá nuestro RPM. Para poder comenzar a crearlo antes debemos crear en nuestra home la estructura de directorios necesaria para la gestión de rpms, código fuente, specs, etc. En lugar de crearlo a mano utilizamos el comando «rpmdev-setuptree» disponible gracias a la instalación de los paquetes del comienzo de la entrada:
$ rpmdev-setuptree
Y ya tenemos la estructura creada:
$ ls -ltrh rpmbuild/ total 20K drwxrwxr-x. 2 alex alex 4.0K Nov 10 16:08 RPMS drwxrwxr-x. 2 alex alex 4.0K Nov 10 16:08 SOURCES drwxrwxr-x. 2 alex alex 4.0K Nov 10 16:08 SPECS drwxrwxr-x. 2 alex alex 4.0K Nov 10 16:08 SRPMS drwxrwxr-x. 2 alex alex 4.0K Nov 10 16:08 BUILD
Lo siguiente que debemos hacer es comprimir las sources de nuestro paquete (carpeta test-package-1.0/) y copiarla o moverla a la carpeta SOURCES dentro de rpmbuild:
$ tar -czvf test-package-1.0.tar.gz test-package-1.0/ test-package-1.0/ test-package-1.0/README.txt test-package-1.0/test-check $ cp -p test-package-1.0.tar.gz rpmbuild/SOURCES/
El último fichero que tenemos que crear para poder construir el rpm es el fichero.spec. Este fichero contiene toda la información del paquete rpm: nombre, número de versión, arquitectura, descripción, dependencias, ordenes de ejecución para la instalación… no es necesario crearlo desde cero. Podemos ejecutar el siguiente comando dentro de la carpeta SOURCES para que nos cree uno de muestra:
$ rpmdev-newspec Skeleton specfile (minimal) has been created to "newpackage.spec".
Lo copiamos o renombramos con el nombre de nuestro paquete:
$ cp -p newpackage.spec test-package.spec
Ahora lo editamos añadiendo los parámetros correspondientes, los más importantes serían:
El nombre del paquete rpm:
Name: test-package
Número de versión:
Version: 1.0
Release de la distribución (lo dejamos por defecto):
Release: 1%{?dist}
Summary, simplemente descriptivo. Indica el contenido del rpm, no es necesario:
Summary: Paquete de muestra que contiene un fichero de texto y un ejecutable
Group hace referencia al grupo al que pertenece el paquete (definidos en un XML en el sistema), en nuestro caso no pertenece a ningún grupo concreto (Base, System Environment, Database…) así que ponemos uno genérico:
Group: Miscellaneous
También podemos especificar términos de licencia del paquete y URL en la que revisarlos:
License: RPM de prueba sin licencia URL: https://rm-rf.es
Ojo con el siguiente parámetro pues sí que es importante, especifica donde se encuentran las sources (del paquete, en este caso nuestro tar.gz (podría ser una url remota), no se especifica rpmbuild/SOURCES porque es la ruta en la que tienen que estar:
Source0: test-package-1.0.tar.gz
En nuestro caso no hay ninguna dependencia para el paquete RPM, pero para paquetes complejos puede ser necesario que algún paquete extra esté instalado para el funcionamiento correcto, los especificaríamos en este punto:
#BuildRequires: #Requires:
Podemos especificar una descripción del paquete que se verá al buscarlo por yum o el comando rpm:
%description Este es un paquete de prueba para el artículo de https://rm-rf.es
Los dos comandos siguientes sirven para preparar el código fuente antes de su instalación, en este caso básicamente descomprimirán el .tar.gz en el directorio rpmbuild/SOURCES:
%prep %setup -q
El siguiente apartado sirve para compilar el código fuente (cuando es necesario). Como nuestro RPM es muy sencillo y no necesita compilación comentamos las líneas:
%build #%configure #make %{?_smp_mflags}
El siguiente apartado (%install) es en el que se especifican las acciones a realizar cuando instalemos el RPM. En nuestro caso básicamente es crear una nueva carpeta en «/usr/local» y copiar ahí los ficheros. Por defecto aparece así:
%install rm -rf $RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT
Lo que hace es en primera instancia borrar cualquier resto de instalaciones anteriores del mismo paquete y después ejecuta un make si hemos realizado tareas de compilación. Vamos a comentar el make ya que nosotros no compilamos nada:
%install rm -rf $RPM_BUILD_ROOT #make install DESTDIR=$RPM_BUILD_ROOT install -d -m 0755 /var/tmp/test-package install -m 0644 README.txt /var/tmp/test-package install -m 0755 test-check /var/tmp/test-package
El comando install -d nos permite crear un directorio e install -m mover ficheros. Lo instalamos en /var/tmp simplemente porque es un rpm de prueba, lo normal sería /usr/local, /opt o lo que quisierais. Finalmente se limpian restos de la instalación:
%clean rm -rf $RPM_BUILD_ROOT
Así quedaría nuestro test-package.spec:
Name: test-package Version: 1.0 Release: 1%{?dist} Summary: Paquete de muestra que contiene un fichero de texto y un ejecutable Group: Miscellaneous License: RPM de prueba sin licencia URL: https://rm-rf.es Source0: test-package-1.0.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) #BuildRequires: #Requires: %description Este es un paquete de prueba para el artículo de https://rm-rf.es %prep %setup -q %build #%configure #make %{?_smp_mflags} %install rm -rf $RPM_BUILD_ROOT #make install DESTDIR=$RPM_BUILD_ROOT install -d -m 0755 /var/tmp/test-package install -m 0644 README.txt /var/tmp/test-package install -m 0755 test-check /var/tmp/test-package %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root,-) %doc %changelog
El último paso ya es empaquetar todo y crear el RPM, para ello utilizamos el siguiente comando pasando como argumento el fichero spec. Debemos esperar un exit 0 al final para descartar fallos:
$ rpmbuild -ba rpmbuild/SOURCES/test-package.spec Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.9azqfP + umask 022 + cd /home/alex/rpmbuild/BUILD + cd /home/alex/rpmbuild/BUILD + rm -rf test-package-1.0 + /bin/tar -xf - + /usr/bin/gzip -dc /home/alex/rpmbuild/SOURCES/test-package-1.0.tar.gz + STATUS=0 + '[' 0 -ne 0 ']' + cd test-package-1.0 + /bin/chmod -Rf a+rX,u+w,g-w,o-w . + exit 0 Executing(%build): /bin/sh -e /var/tmp/rpm-tmp.VqJuDV + umask 022 + cd /home/alex/rpmbuild/BUILD + cd test-package-1.0 + CFLAGS='-O2 -g -march=i386 -mtune=i686' + export CFLAGS + CXXFLAGS='-O2 -g -march=i386 -mtune=i686' + export CXXFLAGS + FFLAGS='-O2 -g -march=i386 -mtune=i686' + export FFLAGS + ./configure --host=i686-pc-linux-gnu --build=i686-pc-linux-gnu --program-prefix= --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --sysconfdir=/etc --datadir=/usr/share --includedir=/usr/include --libdir=/usr/lib --libexecdir=/usr/libexec --localstatedir=/var --sharedstatedir=/var/lib --mandir=/usr/share/man --infodir=/usr/share/info + exit 0 Executing(%install): /bin/sh -e /var/tmp/rpm-tmp.U4egr2 + umask 022 + cd /home/alex/rpmbuild/BUILD + cd test-package-1.0 + rm -rf /home/alex/rpmbuild/BUILDROOT/test-package-1.0-1.el6.i386 + install -d -m 0755 /var/tmp/test-package + install -m 0644 README.txt /var/tmp/test-package + install -m 0755 test-check /var/tmp/test-package + /usr/lib/rpm/check-rpaths /usr/lib/rpm/check-buildroot find: `/home/alex/rpmbuild/BUILDROOT/test-package-1.0-1.el6.i386': No such file or directory + /usr/lib/rpm/brp-compress /usr/lib/rpm/brp-compress: line 8: cd: /home/alex/rpmbuild/BUILDROOT/test-package-1.0-1.el6.i386: No such file or directory + /usr/lib/rpm/brp-strip find: `/home/alex/rpmbuild/BUILDROOT/test-package-1.0-1.el6.i386': No such file or directory + /usr/lib/rpm/brp-strip-static-archive find: `/home/alex/rpmbuild/BUILDROOT/test-package-1.0-1.el6.i386': No such file or directory + /usr/lib/rpm/brp-strip-comment-note find: `/home/alex/rpmbuild/BUILDROOT/test-package-1.0-1.el6.i386': No such file or directory Processing files: test-package-1.0-1.el6.i386 Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/alex/rpmbuild/BUILDROOT/test-package-1.0-1.el6.i386 warning: Could not canonicalize hostname: CentOS Wrote: /home/alex/rpmbuild/SRPMS/test-package-1.0-1.el6.src.rpm Wrote: /home/alex/rpmbuild/RPMS/i386/test-package-1.0-1.el6.i386.rpm Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.byNcVu + umask 022 + cd /home/alex/rpmbuild/BUILD + cd test-package-1.0 + rm -rf /home/alex/rpmbuild/BUILDROOT/test-package-1.0-1.el6.i386 + exit 0
Vemos que todo ha ido bien así que ya deberíamos tener nuestro nuevo RPM en la carpeta RPMS:
$ ls -l rpmbuild/RPMS/i386/test-package-1.0-1.el6.i386.rpm -rw-rw-r--. 1 alex alex 1365 Nov 10 16:43 rpmbuild/RPMS/i386/test-package-1.0-1.el6.i386.rpm
Y el RPM de las sources:
$ ls -l rpmbuild/SRPMS/test-package-1.0-1.el6.src.rpm -rw-rw-r--. 1 alex alex 2458 Nov 10 16:43 rpmbuild/SRPMS/test-package-1.0-1.el6.src.rpm
Lo podemos instalar como cualquier otro rpm:
# rpm -ivh rpmbuild/RPMS/i386/test-package-1.0-1.el6.i386.rpm Preparing... ########################################### [100%] 1:test-package ########################################### [100%]
Vemos que se ha instalado correctamente:
# ls -l /var/tmp/test-package/ total 8 -rw-r--r--. 1 alex alex 27 Nov 10 16:43 README.txt -rwxr-xr-x. 1 alex alex 92 Nov 10 16:43 test-check
Y podemos ver también toda la información del paquete rpm que indicamos en el fichero spec:
# rpm -qi test-package Name : test-package Relocations: (not relocatable) Version : 1.0 Vendor: (none) Release : 1.el6 Build Date: Sat 10 Nov 2012 04:43:48 PM CET Install Date: Sat 10 Nov 2012 04:45:12 PM CET Build Host: CentOS Group : Miscellaneous Source RPM: test-package-1.0-1.el6.src.rpm Size : 0 License: RPM de prueba sin licencia Signature : (none) URL : https://rm-rf.es Summary : Paquete de muestra que contiene un fichero de texto y un ejecutable Description : Este es un paquete de prueba para el artículo de https://rm-rf.es
Este es el modo de crear un paquete rpm muy básico, a partir de aquí es cuestión de buscar más información para poder tener vuestras aplicaciones empaquetadas ;)
Hola, he leido la guia y la he seguido al pie de la letra pero siempre que ejecuto la construccion del rpm (rpmbuild -ba rpmbuild/SOURCES/test-package.spec) me da error la ejecucion que realiza el rpmbuil cuando llega a esta linea:
«+ /usr/lib/rpm/find-debuginfo.sh /home/developer01/rpm/BUILD/test-package-1.0»
Leyendo en internet dice que hay que declarar esta linea en el archivo spec:
«%define debug_package %{nil}»
Me logra generar el archivo rpm y src.rpm pero cuando los ejecuto no tiene los archivos:
# ls -l /var/tmp/test-package/
total 8
-rw-r–r–. 1 alex alex 27 Nov 10 16:43 README.txt
-rwxr-xr-x. 1 alex alex 92 Nov 10 16:43 test-check
tienes alguna idea de por que puede fallar la instalacion.
Me sucede igual, me gustaria saber como lo solucionaste y de ser posible actualizar este post!!. Muchas gracias.
Este post no está mal como primera guía, pero tiene unos cuántos fallos, principalmente, da a entender que la sección %install es una secuencia que se ejecutará cada vez que se instale el rpm, cosa que no es así, esa secuencia sólo se ejecuta cuando se hace el rpmbuild, pero una vez generado el rpm, al instalarlo, no se ejecuta, tal y cómo dice esta documentación: https://fedoraproject.org/wiki/How_to_create_an_RPM_package
Gracias Daniel, le echaré un vistazo de nuevo.
Saludos!