Cómo ejecutar un proceso del sistema con Java

Publicado por pico.dev el , actualizado el .
blog-stack java gnu-linux planeta-codigo planeta-linux
Comentarios

Dada la popularidad de Java es difícil que no encontremos en el propio JDK o librería la funcionalidad que necesitamos y sino en algún comando del sistema de los muchos que tenemos a disposición en un sistema GNU/Linux. Esto nos da acceso a una gran cantidad de funcionalidades también desde los programas Java.

Java
GNU
Linux

Java de por sí incluye una amplia colección de clases con las funcionalidades principales que podamos necesitar, si no lo ofrece en la API es muy posible que haya una librería que lo proporcione. Pero en algún momento quizá se nos dé el caso que un comando del sistema devuelve la información o realiza la acción que necesitamos. Puede ser una un comando del sistema GNU/Linux, Windows o Mac OS X o un script en Java, Python, Ruby u otro lenguaje de programación. A través de las clase Process y ProcessBuilder nos es posible lanzar un proceso de cualquier comando del sistema y acceder a su entrada estándar, salida estándar y salida de error.

La clase Process representa el proceso que lancemos, tenemos dos formas de obtener un referencia esta clase, una con Runtime.getInstance().exec() y otra con la clase ProcessBuilder con ambas nos será posible establecer variables de entorno, el directorio de trabajo o redirigir la entrada y salida. Obtenida la referencia a una instancia de Process con el método getInputStream() leeremos la salida estándar del proceso, con getErrorInputStream() la salida de errores y con getOutputStream() podremos enviar contenido a la entrada estándar. Otros métodos de utilidad nos permitirán conocer si el proceso sigue vivo con isAlive(), obtener el código de salida con exitValue(), esperar a que termine con waitFor(). Finalmente con destroy() podemos terminar de forma abrupta el proceso.

No son de las novedades destacables de Java 8 pero desde esta versión se puede establecer una espera máxima a la terminación del proceso, las variables de entorno y el directorio de trabajo. Y más cambios pequeños pero muy útiles como estos habrá sido añadidos a otras clases de la API.

Con esto nos es posible hacer cualquier cosa que el sistema pueda hacer según los comandos que tenga instalados o puedan instalarse y esto significa que está al alcance de Java en un sistema GNU/Linux el poder de su linea de comandos. Por ejemplo, supongamos que queremos saber en un programa Java el tiempo que lleva iniciado un sistema que nos sería útil si queremos implementar algún tipo de métricas de monitorización con Spring Boot Actuator. Java no tiene en su API un método que proporcione esta información, sin embargo, en GNU/Linux podemos saber este dato usando el sistema de archivos virtual accesible en /proc, concretamente en el archivo /proc/uptime. Este archivo contiene dos números el primero es el que nos interesaría siendo el número de segundos transcurridos desde que el sistema se inició y el segundo el tiempo que ha permanecido en reposo. El segundo número en un sistema con un procesador con varios núcleos físicos o lógicos es probable que se más alto que el primero.

Este sería el programa Java para conocer el tiempo que un sistema GNU/Linux lleva arrancado. Primero se crea el proceso, se espera a que termine y se obtiene su código de salida, se obtiene la salida del proceso (entrada para el programa), se procesa el resultado y se imprimen los segudos que lleva el sistema iniciado.

Ejecutar un comando del sistema nos da acceso a un nuevo mundo de posibilidades aunque si podemos es mejor tener disponible un API para invocar la funcionalidad que queremos en vez de una integración más frágil leyendo y escribiendo en la salida, de error y entrada del proceso. En el siguiente artículo basándome es esto comentaré cómo enviar un correo electrónico en Java firmado digitalmente con GPG, aplicando esto mismo podemos obtener el país y ciudad en base a la dirección IP en una aplicación web.

El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub y probarlo en tu equipo ejecutando el comando ./gradlew run.