Correcta instalación de Java en Debian mediante paquetes DEB

Hay muchas formas de instalar diferentes versiones de Java en nuestros sistemas: en la propia web de Oracle (que como todos sabéis, es el propietario de Java desde hace varios años) podemos descargar diferentes versiones (9, 8, 7, ...), en diferentes formatos (comprimido con tar.gz, paquetes para CentOS/RedHat, ejecutables binarios, ...) y para diferentes sistemas operativos (Linux, MacOS, Windows y SPARC).

Incluso hay repositorios no-oficiales que ponen a disposición de todo el mundo los paquetes de instalación de Java en otros formatos, por lo que a simple vista cualquiera diría que existiendo tanta variedad incluso nosotros (fieles y exigentes defensores de Debian y de la mantenibilidad de los sistemas) estaríamos contentos, verdad?

Pues va a ser que no...

¿Y porqué no? Pues porque ninguna de estas opciones está pensada para instalarse correctamente en Debian, y te voy a explicar porqué:

Podríamos descomprimir los archivos .tar.gz y copiar manualmente su contenido a alguna parte de nuestro disco duro, crear los enlaces simbólicos que apunten a dichos archivos, añadir los paths a nuestras variables de entorno, etc.

Esto no es nada complicado, pero no es mantenible ya que si el dia de mañana queremos desinstalarlo (o actualizar a una nueva versión), volver sobre nuestros pasos y eliminar todo eso nos llevaría un tiempo que no siempre tendremos (aparte de que sería un coñazo, vaya). Por no mencionar que seguro que se nos olvidaría algo, y acabaríamos dejando archivos innecesarios en el disco, ensuciando cada vez más nuestro servidor.

Por lo tanto necesitamos aprovechar las ventajas de nos ofrecen los paquetes propios de cada distribución y de sus gestores, ya que ellos se encargan de instalar, actualizar y desinstalar correctamente las aplicaciones sin dejar el sistema en un estado inconsistente, manejar las dependencias que necesite la aplicación que estamos instalando, etc.

El problema es que Oracle solo proporciona paquetes para Linux en formato RPM (CentOS y RedHat) por lo que tendríamos que instalar el gestor de paquetes de RPM en nuestra distribución Debian.

Y aunque hacerlo es muy sencillo, no lo recomiendo en absoluto ya que aunque para cosas sencillas este método funciona bien, cada distribución suele tener una forma ligeramente distinta de hacer algunas cosas, rutas diferentes donde almacenar los archivos, etc. y normalmente no coinciden unas con otras. Si instalamos un paquete en una distribución para la que no ha sido pensado lo más normal es que la aplicación no se instale correctamente, y si por casualidad se instala, su funcionamiento podría no ser el adecuado.

Si hacer debug en el código que estamos escribiendo para solucionar un bug ya es complicado en algunas ocasiones, no parece buena idea añadir aún más posibles causas de error al asunto, no crees?

Queda descartado entonces el uso de paquetes RPM en sistemas Debian...

En este punto, puede que alguno de vosotros esté pensando en la herramienta alien, verdad? Para quienes no la conozcan, esta herramienta permite convertir paquetes de otras distribuciones a paquetes Debian.

Genial, ¿no? ¿ya tenemos la solución entonces? Pues me temo que no...

Convertir los paquetes mediante esta herramienta no siempre funciona. Para cosas muy sencillas quizás si, pero no siempre es capaz de interpretar todas las diferencias entre unas distribuciones y otras, por lo que la mayoría de las veces habrá una parte de la instalación que no se haga (no se establecerá un enlace simbólico, no se reiniciará un servicio o cualquier otra cosa) y de nuevo estaremos ante una instalación incompleta (o peor aún, inestable) de la aplicación.

Por lo tanto debemos instalar únicamente paquetes DEB que hayan sido generados y empaquetados pensando en que iban a ser instalados en un sistema Debian. Y Oracle no, pero como dije al principio hay muchos otros repositorios de código no-oficiales que ofrecen Java en otros formatos, incluyendo el que nosotros queremos.

El hecho de utilizar repositorios no-oficiales no tiene ningún problema per se, pero si al igual que yo sois un poco precavidos (por no decir paranoicos) seguro que no estáis cómodos instalando paquetes que no podéis comprobar si han sido manipulados con algún tipo de malware, especialmente si hablamos de entornos de producción.

Cada uno es libre de hacer lo que quiera (hasta el dia en el que yo mande, por supuesto) por lo que si decidís utilizar un repositorio no-oficial de Java para descargar e instalar los paquetes en vuestros sistemas no hay ningún problema. Yo sin embargo no me fio de nadie (por algo soy sysadmin!), por lo que no estoy a gusto usando estos repositorios.

Así que, ¿cómo lo hacemos entonces? ¿programamos en otro lenguaje que no sea Java? ¿nos olvidamos de Debian y reinstalamos CentOS en nuestros ordenadores? ¿dejamos la informática y nos dedicamos a criar ganado en la montaña? No tengo inconveniente en programar en cualquier lenguaje, y me encanta la montaña... pero jamas usaré CentOS en mis servidores, así que seguiré buscando una solución... xDDD

Por suerte, nuestra querida Debian ya pensó en esto y dió con la solución: java-package.

Tal y como se explica en la propia página de Debian, la aplicación java-package nos permite generar paquetes DEB partiendo de los archivos Java descargados de la web oficial de Oracle. Es decir, bajando el archivo .tar.gz de la versión de Java que queramos desde la web de Oracle, podemos generar un paquete DEB para instalar sin problemas en nuestra distribución Debian.

Ahora si, esto tiene mucha mejor pinta!

Lo primero que tenemos que hacer es instalar el paquete java-package:

$ sudo apt-get install java-package

Este paquete nos provee del comando make-jpkg, que es quien se encarga de generar el paquete DEB.

Ahora vamos a descargar de la web de Java el archivo con la versión que queramos instalar.

Accedemos a la página de descargas de Java y descargamos el archivo para Linux en formato .tar.gz:

A dia de hoy la última versión disponible es la 9.0.1. No obstante vamos a descargar también la version 8 (concretamente la 8u151) para que veáis cómo pueden convivir varias versiones de Java al mismo tiempo sin problemas.

Guardaremos ambos archivos en /tmp:

└─ tmp/
   ├─ jdk-8u152-linux-x64.tar.gz
   ├─ jdk-9.0.1_linux-x64_bin.tar.gz

Si os fijáis bien, los nombres de ambos archivos son ligeramente diferentes, no solo en la versión sino también en otras partes.

Es muy importante que os fijéis en esto ya que parece ser que Oracle ha cambiado la forma de nombrar dichos archivos a partir de la versión 9, y esto provoca que el comando make-jpkg no reconozca el archivo correctamente.

Quizás cuando leáis este artículo ya lo hayan corregido (realmente es un fallo muy absurdo), pero a dia de hoy es necesario renombrar el archivo al formato que tenían antes para que la generación del paquete funcione. El nombre debe ser jdk-version-linux-arquitectura.tar.gz:

$ mv /tmp/jdk-9.0.1_linux-x64_bin.tar.gz /tmp/jdk-9-linux-x64.tar.gz

Ahora ya tenemos los 2 archivos con los nombres que make-jpkg espera encontrar:

└─ tmp/
   ├─ jdk-8u152-linux-x64.tar.gz
   ├─ jdk-9-linux-x64.tar.gz

Ahora ejecutamos el comando make-jpkg dos veces, una con cada archivo:

$ cd /tmp
$ make-jpkg jdk-8u152-linux-x64.tar.gz
$ make-jpkg jdk-9-linux-x64.tar.gz

Si todo ha ido bien, una vez que hayan finalizado tendremos 2 nuevos paquetes DEB en /tmp:

└─ tmp/
   ├─ oracle-java8-jdk_8u151_amd64.deb
   ├─ oracle-java9-jdk_9_amd64.deb

Y ya podremos instalarlos sin ningún problema con nuestro maravilloso dpkg:

$ sudo dpkg -i /tmp/oracle-java8-jdk_8u151_amd64.deb
$ sudo dpkg -i /tmp/oracle-java9-jdk_9_amd64.deb

Hecho! Ya tenemos instaladas las 2 versiones de Java en nuestro sistema. Puedes comprobarlo con:

$ dpkg -l "oracle-java*"

Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                 Version      Architecture    Description
+++-====================-============-===============-=====================================================
ii  oracle-java8-jdk     8u152        amd64           Java Platform, Standard Edition 8 Development Kit
ii  oracle-java9-jdk     9            amd64           Java Platform, Standard Edition 9 Development Kit

De ahora en adelante, podemos utilizar nuestro gestor de paquetes para gestionarlas como haríamos con cualquier otro paquete instalado por medio de dpkg o incluso de apt-get. Por ejemplo, si quisiéramos desinstalar una de ellas (la versión 8, por ejemplo) bastaría con ejecutar:

$ sudo dpkg -r oracle-java8-jdk

Para seleccionar una o otra como la versión por defecto solo tenéis que apuntar los enlaces simbólicos que hay en /etc/alternatives/ al directorio correspondiente.

Con este comando podéis ver a donde apunta cada comando de java (java, javac, javadoc, etc) actualmente:

$ ls -l /etc/alternatives/java*

lrwxrwxrwx 1 root root 48 Nov 12 15:31 /etc/alternatives/java -> /usr/lib/jvm/oracle-java9-jdk-amd64/bin/java
lrwxrwxrwx 1 root root 45 Nov 12 15:45 /etc/alternatives/javac -> /usr/lib/jvm/oracle-java9-jdk-amd64/bin/javac
lrwxrwxrwx 1 root root 47 Nov 12 15:45 /etc/alternatives/javadoc -> /usr/lib/jvm/oracle-java9-jdk-amd64/bin/javadoc
lrwxrwxrwx 1 root root 45 Nov 12 15:45 /etc/alternatives/javah -> /usr/lib/jvm/oracle-java9-jdk-amd64/bin/javah
lrwxrwxrwx 1 root root 45 Nov 12 15:45 /etc/alternatives/javap -> /usr/lib/jvm/oracle-java9-jdk-amd64/bin/javap
lrwxrwxrwx 1 root root 50 Nov 12 15:31 /etc/alternatives/javaws -> /usr/lib/jvm/oracle-java9-jdk-amd64/bin/javaws

En mi caso todos los comandos apuntan a la versión 9 porque están enlazados con los comandos que hay en /usr/lib/jvm/oracle-java9-jdk-amd64/bin. Podéis verlo aquí:

$ java -version

java version "9.0.1"
Java(TM) SE Runtime Environment (build 9.0.1+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.1+11, mixed mode)

Si quisiera que la versión de Java por defecto fuera la 8, solo tendría que cambiar el destino de los enlaces simbólicos. Por ejemplo:

$ sudo ln -sf /usr/lib/jvm/oracle-java8-jdk-amd64/jre/bin/java /etc/alternatives/java

Ahora la versión de Java por defecto es la 8:

$ java version "1.8.0_152"

Java(TM) SE Runtime Environment (build 1.8.0_152-b16)
Java HotSpot(TM) 64-Bit Server VM (build 25.152-b16, mixed mode)

Y eso es todo!

Como siempre, espero que el artículo os haya resultado de utilidad! Y por supuesto, no dudéis en distribuirlo y compartirlo con todo el mundo (pero por favor, cita siempre la fuente original de éste artículo).

Alaaaaaaaaaaaaaaaaaaaaaaa!