Executando comandos em uma máquina remota de Java com JSCH

Executando comandos em uma máquina remota de Java com JSCH

SSH é uma ferramenta diária de qualquer trabalho de administração do sistema Linux. É uma maneira fácil e segura de acessar máquinas remotas na rede, transferir dados e executar comandos remotos. Além do modo interativo, existem muitas ferramentas que permitem a automação de tarefas remotas que também dependem do ssh Arquitetura de servidor/cliente. Para uma dessas ferramentas, você pode ler sobre Ansible no Ubuntu, por exemplo. Você também pode encontrar muitas implementações do cliente SSH, mas que tal acessar as habilidades que o SSH fornece do código?

JSCH é um projeto que implementa o protocolo SSH em Java. Com sua ajuda, você pode criar aplicativos capazes de se conectar e interagir com um servidor SSH remoto ou local. Dessa forma, seu aplicativo é capaz de gerenciar qualquer aspecto da máquina de destino que você possa concluir com seu cliente SSH nativo, o que fornece mais uma adição poderosa ao já vasto conjunto de ferramentas Java.

Neste artigo, importaremos o JSCH para o nosso projeto Java e desenvolveremos as peças mínimas de código necessárias para criar um aplicativo que possa fazer login no servidor SSH de uma máquina remota, executar alguns comandos no shell interativo remoto, fechar a sessão e depois apresenta o saída. Este aplicativo será mínimo, no entanto, pode dar uma dica do poder que fornece.

Neste tutorial, você aprenderá:

  • Como importar o JSCH para o seu projeto Java
  • Como configurar o ambiente de teste
  • Como implementar a interface UserInfo em uma classe personalizada
  • Como escrever um aplicativo que inicia sessão interativa SSH
Exemplo de JSCH Execução.

Requisitos de software e convenções usadas

Requisitos de software e convenções de linha de comando Linux
Categoria Requisitos, convenções ou versão de software usada
Sistema Fedora 30
Programas OpenJdk 1.8, JSCH 0.1.55, netbeans 8.2
Outro Acesso privilegiado ao seu sistema Linux como raiz ou através do sudo comando.
Convenções # - requer que os comandos Linux sejam executados com privilégios root diretamente como usuário root ou por uso de sudo comando
$ - Requer que os comandos do Linux sejam executados como um usuário não privilegiado regular

Introdução

Com a ajuda do JSCH, desenvolveremos um aplicativo que tentará fazer login LocalHost através da ssh, usando o nome de usuário teste e senha teste. Vamos assumir a porta padrão 22 O servidor SSH ouve e aceitará a impressão digital do servidor sem verificar sua validade. No login bem -sucedido, executaremos alguns comandos que poderíamos emitir em um shell remoto, logot e depois imprimir toda a saída recebida.

AVISO
O seguinte código -fonte é apenas para fins de demonstração; Nunca use esse código na produção! Só para citar duas armadilhas, Não confie em nenhuma impressão digital do servidor por padrão, e lidar com exceções corretamente.

Nossas ferramentas consistirão em um desktop do Fedora (como cliente e servidor), um IDE recente do NetBeans e o (no momento da redação) mais recente JSCH estável. Observe, no entanto, que essas são apenas as ferramentas de escolha. Java é independente da plataforma e o servidor de destino pode estar do outro lado do planeta e pode ser qualquer sistema operacional que execute um adequado servidor ssh.

Configurando o ambiente de teste

Precisaremos das credenciais acima para trabalhar LocalHost. Em nosso exemplo, isso significa que precisamos de um usuário chamado "teste", com a senha "teste". Também precisaremos de um servidor SSH em execução.

Adicionando o usuário do teste

Vamos executar UserAdd como raiz:

# teste de userAdd

E defina a senha do novo usuário:

# Teste Passwd

Aqui precisamos fornecer a senha acima duas vezes. Isso é adequado em um ambiente de teste que é temporário e também inacessível do mundo exterior, mas não use senhas facilmente adivinhadas quando pode haver menor chance de acesso descontrolado.

Verificando o servidor SSH

Podemos verificar o status do servidor ssh com Systemd:

# status systemctl sshd

E comece se não estiver em execução:

# SystemCtl Start SSHD

Esta etapa pode ser necessária nas instalações da área de trabalho, pois algumas dessas configurações não executam o servidor SSH por padrão.

Testando a conectividade com o cliente nativo

Se nosso usuário estiver definido e o serviço estiver em execução, devemos fazer login usando as informações acima:

$ ssh teste@localhost

Precisamos aceitar a impressão digital do host e fornecer a senha. Se chegarmos ao shell, nosso ambiente de teste será concluído.

Obtenção e importação de JSCH para o nosso projeto

Baixando o arquivo

Precisamos baixar o código de byte do projeto JSCH para usar sua funcionalidade. Você pode encontrar o link apropriado na página inicial do JSCH. Vamos precisar do .jarra Arquivo Java.

Criando o projeto em Netbeans

No começo, criamos um novo projeto vazio chamado sshremoteexample em netbeans. Podemos simplesmente escolher "novo projeto" no menu de arquivos.



Criando um novo projeto.

Escolheremos a categoria "Java" e o projeto "Java Application".

Escolhendo a categoria para o projeto.

Precisamos fornecer um nome para o projeto, neste caso "sshremoteexample".

Nomeando o projeto.

No layout padrão, podemos encontrar a janela "Projetos" à esquerda. Lá, clicaremos com o botão direito do mouse no nó "bibliotecas" em nosso projeto recém-criado e selecione "Adicionar jar/pasta". Uma janela de um selecionador de arquivos será aberta, onde precisamos navegar para o .jarra Arquivo que baixamos no site do desenvolvedor.

Adicionando uma jarra como uma biblioteca.

Após a seleção, o arquivo deve aparecer nas bibliotecas incluídas, se abrirmos o nó "bibliotecas".

JSCH importou com sucesso.

Precisamos implementar o Informação de usuário interface para usá -lo em nosso aplicativo. Para fazer isso, precisamos adicionar um novo Classe Java ao nosso projeto clicando com o botão direito do mouse em nosso sshremoteexample Pacote na janela do projeto, escolha "Novo", depois "Java Class ...".

Adicionando nova aula de java ao pacote.

Forneceremos o nome "sshremoteexampleuserinfo" como nome de classe.

Nomeando a nova aula de Java.

Adicionando o código -fonte

sshremoteexampleUserinfo.Java

Para nossa implementação de interface, considere a seguinte fonte. É aqui que aceitamos a impressão digital do alvo cegamente. Não faça isso em um cenário do mundo real. Você pode editar o código -fonte clicando na classe na janela do projeto ou, se já estiver aberto, mude para ele com as guias na parte superior da janela do código -fonte.

pacote sshremoteexample; importar com.jcraft.JSCH.*; classe pública sshremoteexampleUserinfo implementa o userInfo private final string pwd; public sshremoteexampleUserinfo (nome de usuário da String, string senha) pwd = senha;  @Override public String getPassPhrase () THROW NOVA UNSUPPORTEDOPERATIONEXCECTIMENTO ("GetPassphrase ainda não suportado."); @Override public String getPassword () return pwd; @Override public boolean PromptPassword (string string)  /*mod* / return true; @Override public boolean PromptpassPhrase (string string) throw unsupportEdOperationException (" Promptpassphrase ainda não suportado."); @Override public boolean Promptyesno (string string)  /*mod* / return true; @Override public void showMessage (string string)  
cópia de

Sshremoteexample.Java

Nossa classe principal será a sshremoteexample classe com a seguinte fonte:

pacote sshremoteexample; importar com.jcraft.JSCH.*; importar java.io.ByteArrayInputStream; importar java.io.Ioexception; importar java.io.InputStream; importar java.NIO.CHARST.StandardCharSets; classe pública sshremoteexample public static void main (string [] args) string host = "localhost"; String user = "teste"; String senha = "teste"; String command = "hostname \ ndf -h \ nexit \ n"; tente jsch jsch = new jsch (); Sessão de sessão = JSCH.getSession (usuário, host, 22); sessão.setUserInfo (novo sshremoteexampleUserinfo (usuário, senha)); sessão.conectar(); Canal canal = sessão.OpenChannel ("Shell"); canal.setInputStream (novo ByteArrayInputStream (comando.GetBytes (StandardCharSets.Utf_8))); canal.setOutputStream (System.fora); InputStream em = canal.getInputStream (); Stringbuilder outbuff = new StringBuilder (); int exitstatus = -1; canal.conectar(); while (true) for (int c; ((c = em.leitura ())> = 0);) outbuff.anexar ((char) c);  se (canal.isClosed ()) if (em.disponível ()> 0) Continue; exitstatus = canal.getExitStatus (); quebrar;  canal.desconectar(); sessão.desconectar(); // Imprima o sistema de conteúdo do buffer.fora.Imprima (OtBuff.para sequenciar()); // Sistema de status de saída imprima.fora.print ("Status de saída da execução:" + exitstatus); if (exitstatus == 0) sistema.fora.print ("(ok) \ n");  else sistema.fora.print ("(Nok) \ n");  catch (ioexception | jschException ioex) sistema.errar.println (ioex.para sequenciar());  
cópia de

Observe que, neste exemplo, codificamos todos os detalhes necessários para a conexão: nome do host de destino, nome de usuário/senha e a string de comando a ser executada na sessão remota. Este não é um exemplo da vida real, mas serve ao seu propósito de demonstração.

Poderíamos mudar o alvo e as credenciais para executar o comando em um host remoto. Observe também que a sessão remota terá os privilégios do usuário que efetuará login. Eu não recomendo usar um usuário com altos privilégios - como raiz - para teste, se a máquina de destino contiver dados ou serviços valiosos.

Executando o aplicativo

Podemos executar nosso aplicativo diretamente do IDE clicando no "Run Project (sshremoteexample)" no menu "Run", que fornecerá a saída na janela de saída abaixo do código -fonte. Também podemos escolher “Projeto Limpo e Construção (Sshremoteexample)” no mesmo menu, nesse caso o IDE produzirá o .jarra Java Archive o pode ser executado sem o IDE.

A saída fornecida mostrará o caminho para o arquivo, semelhante ao seguinte (o caminho exato pode variar dependendo das configurações do IDE):

Para executar este aplicativo da linha de comando sem formiga, tente: java -jar "/var/Projects/sshremoteexample/dist/sshremoteexample.jarra " 

Como pode ser adivinhado, podemos executar nosso aplicativo construído a partir da linha de comando e, se tudo correr bem, ele fornecerá uma saída semelhante ao seguinte.

$ java -jar "/var/Projects/sshshellexemple/dist/sshellexpleple ampler.jar "Último login: seg 29 14:27:08 2019 de 127.0.0.1 HostName DF -H Exit [Test@test1 ~] $ hostName test1.LinuxConfig.org [teste@test1 ~] $ df -h tamanho do sistema de arquivos usado use% use% montado em 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% /execução 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 , 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% /lar /dev/sda1 200m 18m 182m 9%/bota/efi tmpfs 789m 9,7m 779m 2%/run/user/1000 tmpfs 789m 0 789m 0%/run/user/1001 [test@test1] da execução: 0 (ok)

Observe que sua saída provavelmente será diferente, se nada mais, no nome do host, nomes de volume e tamanhos - mas, em geral, você deve ver um completo df -h saída que você obteria em uma sessão SSH.

Pensamentos finais

Este exemplo simples destinado a mostrar o poder do projeto JSCH, se de uma maneira um pouco simplificada. Com acesso à máquina de teste e um cliente adequado, o comando simples seguinte forneceria as mesmas informações:

$ ssh teste@localhost "hostName; df -h"

E também não criaria uma sessão interativa. A mesma funcionalidade é fornecida pelo JSCH se você abrir o canal no modo de comando:

Canal canal = sessão.OpenChannel ("comando");

Dessa forma, você não precisa lidar com o fechamento da sessão com o saída comando shell.

O verdadeiro poder deste projeto reside na capacidade de se conectar e interagir com os comandos da Shell Native Machine Trough, processar a saída e decidir a próxima ação programaticamente. Imagine um aplicativo multithread que gerencia possivelmente centenas de servidores por si só, e você terá a foto.

Tutoriais do Linux relacionados:

  • Uma introdução à automação, ferramentas e técnicas do Linux
  • Coisas para instalar no Ubuntu 20.04
  • Ansible Tutorial para iniciantes no Linux
  • Oracle Java Instalação no Ubuntu 20.04 fossa focal linux
  • Como instalar Java no Manjaro Linux
  • Linux: Instale Java
  • Como executar operações de administração com Ansible…
  • Coisas para fazer depois de instalar o Ubuntu 20.04 fossa focal linux
  • Mastering Bash Script Loops
  • Ansible Vault Tutorial