Ejecución de comandos en una máquina remota desde Java con JSCH

Ejecución de comandos en una máquina remota desde Java con JSCH

SSH es una herramienta diaria de cualquier trabajo de administración de sistemas de Linux. Es una forma fácil y segura de acceder a máquinas remotas en la red, transferir datos y ejecutar comandos remotos. Además del modo interactivo, existen muchas herramientas que permiten la automatización de tareas remotas que también dependen de la existencia ssh Arquitectura de servidor/cliente. Para una de esas herramientas, puede leer sobre Ansible en Ubuntu, por ejemplo. También puede encontrar muchas implementaciones del cliente SSH, pero ¿qué hay de acceder a las habilidades que SSH proporciona desde el código??

JSCH es un proyecto que implementa el protocolo SSH en Java. Con su ayuda, puede crear aplicaciones que sean capaces de conectarse e interactuar con un servidor SSH remoto o local. De esta manera, su aplicación es capaz de administrar cualquier aspecto de la máquina de destino que pueda completar con su cliente SSH nativo, lo que ofrece otra poderosa adición al conjunto de herramientas de Java ya vasto.

En este artículo importaremos JSCH en nuestro proyecto Java y desarrollaremos las piezas de código mínimas necesarias para crear una aplicación que pueda iniciar sesión en el servidor SSH de una máquina remota, ejecutar algunos comandos en el shell interactivo remoto, cierra la sesión y luego presenta el producción. Esta aplicación será mínima, sin embargo, puede dar una pista de la potencia que proporciona.

En este tutorial aprenderás:

  • Cómo importar JSCH en su proyecto Java
  • Cómo configurar el entorno de prueba
  • Cómo implementar la interfaz UserInfo en una clase personalizada
  • Cómo escribir una aplicación que inicie la sesión SSH interactiva
Ejecución de ejemplo de JSCH.

Requisitos y convenciones de software utilizados

Requisitos de software y convenciones de línea de comandos de Linux
Categoría Requisitos, convenciones o versión de software utilizada
Sistema Fedora 30
Software OpenJDK 1.8, JSCH 0.1.55, NetBeans 8.2
Otro Acceso privilegiado a su sistema Linux como root o a través del sudo dominio.
Convenciones # - requiere que los comandos de Linux dados se ejecuten con privilegios raíz directamente como un usuario raíz o mediante el uso de sudo dominio
ps - Requiere que los comandos de Linux dados se ejecuten como un usuario regular no privilegiado

Introducción

Con la ayuda de JSCH, desarrollaremos una aplicación que intentará iniciar sesión hostil a través de ssh, Usando el nombre de usuario prueba y contraseña prueba. Asumiremos el puerto predeterminado 22 El servidor SSH escucha y aceptará la huella digital del servidor sin verificar su validez. En el inicio de sesión exitoso, ejecutaremos algunos comandos que podríamos emitir en un shell remoto, cierre la sesión e imprima toda la salida recibida.

ADVERTENCIA
El siguiente código fuente es solo para fines de demostración; Nunca use dicho código en producción! Solo por nombrar dos trampas, No confíe en ninguna huella digital del servidor de forma predeterminada, y manejar las excepciones correctamente.

Nuestras herramientas consistirán en un escritorio Fedora (tanto como cliente como servidor), un reciente IDE de NetBeans y el (en el momento de escribir) (al momento) el último JSCH estable. Tenga en cuenta que estas son solo las herramientas de elección. Java es independiente de la plataforma, y ​​el servidor de destino podría estar en el otro lado del planeta, y podría ser cualquier sistema operativo que ejecute un adecuado servidor ssh.

Configuración del entorno de prueba

Necesitaremos las credenciales anteriores para trabajar hostil. En nuestro ejemplo, eso significa que necesitamos un usuario llamado "prueba", con la contraseña "prueba". También necesitaremos un servidor SSH en ejecución.

Agregar el usuario de la prueba

Ejecutaremos usuarios como raíz:

# Prueba de usuarios

Y configure la contraseña del nuevo usuario:

# prueba de passwd

Aquí necesitamos proporcionar la contraseña anterior dos veces. Esto es adecuado en un entorno de prueba temporal y también inalcanzable del mundo exterior, pero no usa contraseñas fácilmente adivinadas cuando puede haber una menor posibilidad de acceso no controlado.

Verificar el servidor SSH

Podemos verificar el estado del servidor ssh con system:

# SystemCTL Status SSHD

Y comience si no se está ejecutando:

# SystemCTL Start SSHD

Este paso puede ser necesario en las instalaciones de escritorio, ya que algunas de estas configuraciones no ejecutan el servidor SSH de forma predeterminada.

Prueba de conectividad con el cliente nativo

Si nuestro usuario está configurado y el servicio se está ejecutando, deberíamos poder iniciar sesión utilizando la información anterior:

$ ssh test@localhost

Tendremos que aceptar la huella digital del host y proporcionar la contraseña. Si llegamos al shell, nuestro entorno de prueba se completa.

Obtener e importar JSCH a nuestro proyecto

Descargando el archivo

Tendremos que descargar el código de byte del proyecto JSCH para usar su funcionalidad. Puede encontrar el enlace apropiado en la página de inicio de JSCH. Necesitaremos el .frasco Archivo de Java.

Creación del proyecto en NetBeans

Al principio, creamos un nuevo proyecto vacío llamado sshremoteExample en netbeans. Simplemente podemos elegir "nuevo proyecto" en el menú de archivo.



Creando un nuevo proyecto.

Elegiremos la categoría "Java" y el proyecto "Aplicación Java".

Elegir la categoría para el proyecto.

Necesitamos proporcionar un nombre para el proyecto, en este caso "sshremoteExample".

Nombrar el proyecto.

En el diseño predeterminado, podemos encontrar la ventana "Proyectos" a la izquierda. Allí haremos clic con el botón derecho en el nodo "Bibliotecas" en nuestro proyecto recién creado, y seleccionaremos "Agregar jar/carpeta". Se abrirá una ventana de selección de archivos, donde necesitamos navegar por el .frasco Archivo que descargamos del sitio del desarrollador.

Agregar un frasco como biblioteca.

Después de la selección, el archivo debe aparecer en las bibliotecas incluidas, si abrimos el nodo "Bibliotecas".

JSCH importado con éxito.

Tendremos que implementar el Información de usuario interfaz para usarlo en nuestra aplicación. Para hacerlo, tendremos que agregar un nuevo clase Java a nuestro proyecto haciendo clic derecho en nuestro sshremoteExample Paquete en la ventana del proyecto, elija "Nuevo", luego "Java Clase ...".

Agregar nueva clase Java al paquete.

Proporcionaremos el nombre "sshremoteExampleUserInfo" como nombre de clase.

Nombrando la nueva clase de Java.

Agregar el código fuente

sshremoteExampleUserInfo.Java

Para la implementación de nuestra interfaz, considere la siguiente fuente. Aquí es donde aceptamos la huella digital del objetivo a ciegas. No hagas esto en un escenario del mundo real. Puede editar el código fuente haciendo clic en la clase en la ventana del proyecto, o si ya está abierto, cambie a él con las pestañas en la parte superior de la ventana del código fuente.

paquete sshremoteExample; importación.jarra.jsch.*; clase pública sshremoteExampleUserInfo implementa UserInfo private final String pwd; public sshremoteExampleUserInfo (String UserName, String Password) pwd = contraseña;  @Override public String getPassPhrase () Throw New UnpportedOperationException ("GetPassPhrase aún no es compatible."); @Override public String getPassword () return pwd; @Override public boolean apurpassword (string string)  /*mod* / return true; @Override public boolean apurphrase (string string) tirar nueva UNSUPTREDOperationException (" " PractPassphrase aún no es compatible."); @Override public boolean apidyesno (string string)  /*mod* / return true; @Override public void showMessage (cadena de cadena)  
Copiar

SshremoteExample.Java

Nuestra clase principal será la sshremoteExample clase con la siguiente fuente:

paquete sshremoteExample; importación.jarra.jsch.*; importar java.IO.BytearrayInputStream; importar java.IO.Ioexception; importar java.IO.Flujo de entrada; importar java.NiO.charlatán.StandardCharsets; clase pública sshremoteExample public static void main (string [] args) string host = "localhost"; String user = "test"; String Password = "Test"; String command = "hostname \ ndf -h \ nexit \ n"; intente jsch jsch = new JSch (); Sesión Sesión = JSCH.getsession (usuario, host, 22); sesión.setUserInfo (nuevo sshremoteExampleUserInfo (usuario, contraseña)); sesión.conectar(); Canal canal = sesión.OpenChannel ("Shell"); canal.setInputStream (nuevo bytearrayInputStream (comando.GetBytes (StandardCharsets.Utf_8))); canal.setOutputStream (sistema.afuera); InputStream in = canal.getInputStream (); StringBuilder outbuff = new StringBuilder (); int exitStatus = -1; canal.conectar(); while (true) for (int c; ((c = en.read ())> = 0);) Outbuff.append ((char) c);  if (canal.isClosed ()) if (en.disponible ()> 0) Continuar; ExitStatus = canal.getExitStatus (); romper;  canal.desconectar(); sesión.desconectar(); // Imprima el sistema de contenido del búfer.afuera.Imprimir (fuera de su lado.Encadenar()); // Sistema de estado de salida de impresión.afuera.imprimir ("Estado de salida de la ejecución:" + ExitStatus); if (exitstatus == 0) sistema.afuera.imprimir ("(OK) \ n");  else sistema.afuera.print ("(nok) \ n");  Catch (IOException | JSCHEXCEPTION IOEX) Sistema.errar.println (ioex.Encadenar());  
Copiar

Tenga en cuenta que en este ejemplo codificamos cada detalle necesario para la conexión: nombre de host de destino, nombre de usuario/contraseña y la cadena de comando que se ejecutará en la sesión remota. Esto no es un ejemplo de la vida real, pero sirve a su propósito de demostración.

Podríamos cambiar el objetivo y las credenciales para ejecutar el comando en un host remoto. También tenga en cuenta que la sesión remota tendrá los privilegios del usuario que inicia sesión. No aconsejaría usar un usuario con altos privilegios, como raíz - Para las pruebas, si la máquina de destino contiene datos o servicios valiosos.

Ejecutando la aplicación

Podemos ejecutar nuestra aplicación directamente desde el IDE haciendo clic en "Ejecutar el proyecto (sshremoteExample)" en el menú "Ejecutar", que proporcionará la salida en la ventana de salida debajo del código fuente. También podemos elegir "Proyecto de limpieza y construcción (sshremoteExample)" del mismo menú, en cuyo caso el IDE producirá el .frasco Java Archivo se puede ejecutar sin el ideal.

La salida proporcionada mostrará la ruta al archivo, similar a la siguiente (la ruta exacta puede variar según la configuración de su IDE):

Para ejecutar esta aplicación desde la línea de comando sin hormiga, intente: java -jar "/var/proyectos/sshremoteExample/dist/sshremoteExample.frasco" 

Como se puede adivinar, podemos ejecutar nuestra aplicación construida desde la línea de comandos, y si todo va bien, proporcionará una salida similar a la siguiente.

$ java -jar "/var/proyectos/sshshellexample/dist/sshshellexample.Jar "Last Iniciar: Mon 29 de julio 14:27:08 2019 desde 127.0.0.1 nombre de host df -h sale [test@test1 ~] $ hostname test1.LinuxConfig.org [test@test1 ~] $ DF -H Tamaño del sistema de archivos Usado Aviso de uso% Montado en devTMPFS 3,9G 0 3,9G 0% /dev tmpfs 3,9g 127m 3,8g 4% /dev /shm tmpfs 3,9g 1 , 7m 3,9g 1% /Ejecutar TMPFS 3,9G 0 3,9G 0% /SYS /FS /CGROUP /DEV /MAPPER /FEDORA_LOCALHOST-LIVE-ROOT 49G 15G 32G 32% /TMPFS 3,9G 6,1M 3 3 , 9G 1% /TMP /dev /SDB1 275G 121G 140G 47% /MNT /HDD_OPEN /DEV /SDA2 976M 198M 711M 22% /BOOT /DEV /MAPPER /FEDORA_LOCALHOST-LIVE-HOME 60G 50G 6,9G 88% /HOME HOME /dev/sda1 200m 18m 182m 9%/boot/EFI TMPFS 789m 9,7m 779m 2%/ejecutivo/usuario/1000 tmpfs 789m 0 789m 0%/run/user/1001 [Test@test1 ~] $ Salir logrout Salida Estado de salida de la ejecución: 0 (OK)

Tenga en cuenta que su salida probablemente diferirá, si nada más, en el nombre de host, nombres y tamaños de volumen, pero en general, debería ver un completo DF -H salida que obtendrá en una sesión de SSH.

Pensamientos finales

Este simple ejemplo destinado a mostrar el poder del proyecto JSCH, si de una manera un tanto sobreestrificada. Con el acceso a la máquina de prueba y a un cliente adecuado, el siguiente comando simple proporcionaría la misma información:

$ ssh test@localhost "hostname; df -h"

Y tampoco crearía una sesión interactiva. JSCH proporciona la misma funcionalidad si abre el canal en modo de comando:

Canal canal = sesión.OpenChannel ("comando");

De esta manera no necesita manejar el cierre de la sesión con el salida comando shell.

El verdadero poder de este proyecto radica en la capacidad de conectarse e interactuar con los comandos de shell nativos de la máquina remota, procesar la salida y decidir la siguiente acción programáticamente. Imagine una aplicación múltiple que administra posiblemente cientos de servidores por sí mismo, y obtendrá la imagen.

Tutoriales de Linux relacionados:

  • Una introducción a la automatización, herramientas y técnicas de Linux
  • Cosas para instalar en Ubuntu 20.04
  • Tutorial Ansible para principiantes en Linux
  • Instalación de Oracle Java en Ubuntu 20.04 fossa focal Linux
  • Cómo instalar Java en Manjaro Linux
  • Linux: instalar Java
  • Cómo realizar operaciones de administración con Ansible ..
  • Cosas que hacer después de instalar Ubuntu 20.04 fossa focal Linux
  • Mastering Bash Script Loops
  • Tutorial de bóveda ansible