Exécution des commandes sur une machine distante de Java avec JSCH

Exécution des commandes sur une machine distante de Java avec JSCH

SSH est un outil quotidien de tout travail d'administration du système Linux. C'est un moyen facile et sécurisé d'accéder aux machines distantes sur le réseau, de transférer des données et d'exécuter des commandes distantes. En dehors du mode interactif, il existe de nombreux outils qui permettent l'automatisation des tâches distantes qui reposent également sur ssh Architecture de serveur / client. Pour un de ces outils, vous pouvez lire sur Ansible sur Ubuntu par exemple. Vous pouvez également trouver de nombreuses implémentations du client SSH, mais qu'en est-il de l'accès aux capacités que SSH fournit à partir du code?

JSCH est un projet qui met en œuvre le protocole SSH en Java. Avec son aide, vous pouvez créer des applications capables de se connecter et d'interagir avec un serveur SSH à distance ou local. De cette façon, votre application est capable de gérer tout aspect de la machine cible que vous pourriez compléter avec votre client SSH natif, ce qui donne un autre ajout puissant au ensemble d'outils Java déjà vaste.

Dans cet article, nous importerons JSCH dans notre projet Java et développerons les pièces de code minimales nécessaires pour créer une application qui peut se connecter au serveur SSH d'une machine distante, exécuter certaines commandes dans le shell interactif distant, ferme la session, puis présente le sortir. Cette application sera minime, cependant, elle peut donner un soupçon de puissance qu'il fournit.

Dans ce tutoriel, vous apprendrez:

  • Comment importer JSCH dans votre projet Java
  • Comment configurer l'environnement de test
  • Comment implémenter l'interface UserInfo dans une classe personnalisée
  • Comment rédiger une application qui initie une session SSH interactive
Exemple de JSCH Exécution.

Exigences et conventions logicielles utilisées

Exigences logicielles et conventions de ligne de commande Linux
Catégorie Exigences, conventions ou version logicielle utilisée
Système Fedora 30
Logiciel Openjdk 1.8, jsch 0.1.55, Netbeans 8.2
Autre Accès privilégié à votre système Linux en tant que racine ou via le Sudo commande.
Conventions # - Exige que les commandes Linux soient exécutées avec des privilèges racine soit directement en tant qu'utilisateur racine, soit par l'utilisation de Sudo commande
$ - Exige que les commandes Linux soient exécutées en tant qu'utilisateur non privilégié régulier

Introduction

Avec l'aide de JSCH, nous développerons une application qui tentera de se connecter à hôte local via ssh, Utilisation du nom d'utilisateur test et mot de passe test. Nous supposerons le port par défaut 22 Le serveur SSH écoute et acceptera l'empreinte digitale du serveur sans vérifier sa validité. Dans une connexion réussie, nous exécuterons quelques commandes que nous pourrions émettre dans un shell distant, nous déconnecter, puis imprimer toutes les sorties reçues.

AVERTISSEMENT
Le code source suivant est à des fins de démonstration uniquement; N'utilisez jamais un tel code en production! Juste pour nommer deux pièges, Ne faites confiance aux empreintes digitales du serveur par défaut, et gérer correctement les exceptions.

Nos outils se composeront d'un bureau Fedora (à la fois en tant que client et serveur), un récent NetBeans IDE, et le (au moment de la rédaction du moment de la rédaction) JSCH (. Notez cependant que ce ne sont que les outils de choix. Java est indépendant de la plate-forme, et le serveur cible pourrait être de l'autre côté de la planète, et pourrait être n'importe quel système d'exploitation qui exécute un bon serveur SSH.

Configuration de l'environnement de test

Nous aurons besoin des informations d'identification ci-dessus pour travailler hôte local. Dans notre exemple, cela signifie que nous avons besoin d'un utilisateur nommé «test», avec le mot de passe «Test». Nous aurons également besoin d'un serveur SSH en cours d'exécution.

Ajout de l'utilisateur de test

Nous exécuterons userAdd comme racine:

# test userAdd

Et définir le mot de passe du nouvel utilisateur:

# Test de passwd

Ici, nous devons fournir le mot de passe ci-dessus deux fois. Cela convient dans un environnement de test qui est temporaire et également inaccessible du monde extérieur, mais n'utilisez pas de mots de passe facilement devinés lorsqu'il peut y avoir de moindres chances d'accès incontrôlé.

Vérification du serveur SSH

Nous pouvons vérifier l'état du serveur SSH avec systemd:

# Statut SystemCTL SSHD

Et démarrez-le s'il ne fonctionne pas:

# systemctl start sshd

Cette étape peut être nécessaire sur les installations de bureau, car certaines de ces configurations n'exécutent pas le serveur SSH par défaut.

Tester la connectivité avec le client natif

Si notre utilisateur est défini et que le service est en cours d'exécution, nous devrions pouvoir vous connecter en utilisant les informations ci-dessus:

$ ssh test @ localhost

Nous devons accepter l'empreinte digitale de l'hôte et fournir le mot de passe. Si nous arrivons à la coquille, notre environnement de test est terminé.

Obtenir et importer JSCH dans notre projet

Télécharger les archives

Nous devons télécharger le code octet du projet JSCH afin d'utiliser sa fonctionnalité. Vous pouvez trouver le lien approprié sur la page d'accueil de JSCH. Nous aurons besoin du .pot Archives Java.

Création du projet dans Netbeans

Au début, nous créons un nouveau projet vide appelé sshremoteexample dans Netbeans. Nous pouvons simplement choisir «Nouveau projet» dans le menu Fichier.



Création d'un nouveau projet.

Nous choisirons la catégorie «Java» et le projet «Application Java».

Choisir la catégorie pour le projet.

Nous devons fournir un nom pour le projet, dans ce cas «SShreMoteExample».

Nommer le projet.

Sur la disposition par défaut, nous pouvons trouver la fenêtre «projets» à gauche. Là, nous cliquerons avec le bouton droit sur le nœud «Libraries» dans notre projet nouvellement créé et sélectionnez «Ajouter un pot / dossier». Une fenêtre de sélecteur de fichiers s'ouvrira, où nous devons parcourir .pot fichier que nous avons téléchargé à partir du site du développeur.

Ajouter un pot comme bibliothèque.

Après la sélection, l'archive doit apparaître dans les bibliothèques incluses, si nous ouvrons le nœud «bibliothèques».

JSCH importé avec succès.

Nous devons implémenter le Informations utilisateur interface afin de l'utiliser dans notre application. Pour ce faire, nous devons ajouter un nouveau classe Java à notre projet en cliquant avec le bouton droit sur notre sshremoteexample Package dans la fenêtre du projet, choisissez «Nouveau», puis «Classe Java…».

Ajouter une nouvelle classe Java au package.

Nous fournirons le nom «sshreMoteExampleUserInfo» comme nom de classe.

Nommer la nouvelle classe Java.

Ajout du code source

sshreMoteExampleUserInfo.Java

Pour notre implémentation d'interface, considérez la source suivante. C'est là que nous acceptons l'empreinte digitale de la cible à l'aveugle. Ne faites pas cela dans un scénario du monde réel. Vous pouvez modifier le code source en cliquant sur la classe dans la fenêtre du projet, ou s'il est déjà ouvert, passez-le avec les onglets en haut de la fenêtre de code source.

package sshreMoteExample; Importer com.jcraft.jsch.* La classe publique sshreMoteExampleUserInfo implémente userInfo private final String pwd; public sshreMoteExampleUserInfo (String Username, String Motword) pwd = mot de passe;  @Override public String getPassPhrase () lancez un nouveau non soutenu."); @Override public String getPassword () return pwd; @Override public boolean promptPassword (String String) / * mod * / return true; @Override public boolean promptSpassPhrase (String String) throw new UsupportedOperationException (" insidepassphrase n'est pas encore pris en charge."); @Override public boolean promptyesno (String String) / * mod * / return true; @Override public void showMessage (String String)  
Copie

Sshremoteexample.Java

Notre classe principale sera la sshremoteexample classe avec la source suivante:

package sshreMoteExample; Importer com.jcraft.jsch.* Importer Java.Io.ByteArrayInputStream; Importer Java.Io.IoException; Importer Java.Io.Flux d'entrée; Importer Java.nio.charbon.StandardCharsets; classe publique sshreMoteExample public static void main (String [] args) String host = "localhost"; String user = "test"; Chaîne mot de passe = "test"; String command = "hostname \ ndf -h \ nexit \ n"; essayez jsch jsch = new jsch (); Session Session = JSCH.getSession (utilisateur, hôte, 22); session.SetUserInfo (nouveau sshreMoteExampleUserInfo (utilisateur, mot de passe)); session.connecter(); Canal canal = session.OpenChannel ("Shell"); canaliser.setInputStream (nouveau bytearrayInputStream (commande.Getbytes (StandardCharsets.UTF_8))); canaliser.SetOutputStream (système.dehors); InputStream dans = canal.getInputStream (); StringBuilder OutBuff = new StringBuilder (); int exitStatus = -1; canaliser.connecter(); tandis que (true) pour (int c; ((c = in.lire ()))> = 0);) Outbuff.ajouter ((char) c);  if (canal.isClosed ()) if (dans.Disponible ()> 0) Continuer; exitStatus = canal.getExitStatus (); casser;   canaliser.déconnecter (); session.déconnecter (); // imprime le système de contenu du tampon.dehors.Imprimer (Outbuff.toString ()); // Imprimer le système d'état de sortie.dehors.print ("Statut de sortie de l'exécution:" + EXITSTATUS); if (exitStatus == 0) système.dehors.print ("(ok) \ n");  else système.dehors.print ("(nok) \ n");  catch (ioException | jschexception ioex) système.se tromper.println (ioex.toString ());  
Copie

Notez que dans cet exemple, nous code dur chaque détail nécessaire pour la connexion: nom d'hôte cible, nom d'utilisateur / mot de passe, et la chaîne de commande à exécuter dans la session distante. Ce n'est guère un exemple réel de la vie, mais il sert son objectif de démonstration.

Nous pourrions modifier la cible et les informations d'identification pour exécuter la commande sur un hôte distant. Notez également que la session distante aura les privilèges de l'utilisateur qui se connecte. Je ne conseillerais pas d'utiliser un utilisateur avec des privilèges élevés - comme racine - pour les tests, si la machine cible contienne des données ou des services précieux.

Exécution de l'application

Nous pouvons exécuter notre application directement à partir de l'IDE en cliquant sur «Exécuter le projet (SShreMoteExample)» dans le menu «Exécuter», qui fournira la sortie dans la fenêtre de sortie sous le code source. Nous pouvons également choisir «Clean and Build Project (sshreMoteExample)» à partir du même menu, auquel cas l'IDE produira le .pot Java Archive the peut être exécuté sans l'IDE.

La sortie fournie montrera le chemin vers l'archive, similaire à ce qui suit (le chemin exact peut varier en fonction de vos paramètres IDE):

Pour exécuter cette application à partir de la ligne de commande sans fourmi, essayez: java -jar "/ var / projets / sshremoteexample / dist / sshremoteexample.pot" 

Comme il peut être deviné, nous pouvons exécuter notre application construite à partir de la ligne de commande, et si tout se passe bien, il fournira une sortie similaire à ce qui suit.

$ java -jar "/ var / projets / sshshellexamp / dist / sshshellexample.Jar "Dernière connexion: lun 29 juillet 14:27:08 2019 de 127.0.0.1 nom d'hôte df -h exit [test @ test1 ~] $ hostname test1.linuxconfig.org [test @ test1 ~] $ df -h Taille de système de fichiers utilisé disponible Utiliser% monté sur 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% / Run TMPFS 3,9G 0 3,9G 0% / SYS / FS / CGROUP / DEV / MAPTER / FEDORA_LOCALHOST - LIVE-ROOT 49G 15G 32G 32% / TMPFS 3,9G 6,1M 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 / dev / sda1 200m 18m 182m 9% / boot / efi tmpfs 789m 9,7m 779m 2% / run / user / 1000 tmpfs 789m 0 789m 0% / run / user / 1001 [test @ test1 ~] $ quitter la connexion de sortie de sortie de sortie de sortie de l'exécution: 0 (ok)

Notez que votre sortie différera probablement, si rien d'autre, dans le nom d'hôte, les noms de volume et les tailles - mais en général, vous devriez voir un complet df -h Sortie que vous obtiendrez dans une session SSH.

Dernières pensées

Cet exemple simple destiné à montrer la puissance du projet JSCH, si de manière quelque peu simplifiée. Avec l'accès à la machine de test et à un client approprié, la commande simple suivante fournirait les mêmes informations:

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

Et ne créerait pas non plus de session interactive. La même fonctionnalité est fournie par JSCH si vous ouvrez le canal en mode commande:

Canal canal = session.OpenChannel ("Command");

De cette façon, vous n'avez pas besoin de gérer la fermeture de la session avec le sortie commande de shell.

La véritable puissance de ce projet réside dans la capacité de se connecter et d'interagir avec les commandes de coquille native de la machine distante, de traiter la sortie et de décider de la prochaine action. Imaginez une application multi-thread qui gère peut-être des centaines de serveurs en soi, et vous obtiendrez l'image.

Tutoriels Linux connexes:

  • Une introduction à l'automatisation Linux, des outils et des techniques
  • Choses à installer sur Ubuntu 20.04
  • Tutoriel anible pour les débutants sur Linux
  • Installation d'Oracle Java sur Ubuntu 20.04 Focal Fossa Linux
  • Comment installer Java sur Manjaro Linux
  • Linux: installer Java
  • Comment effectuer des opérations d'administration avec Ansible…
  • Choses à faire après l'installation d'Ubuntu 20.04 Focal Fossa Linux
  • Masterring Bash Script Loops
  • Tutoriel de coffre-fort Ansible