Skip to content

Archives

  • Janeiro 2022
  • Dezembro 2021
  • Novembro 2021
  • Outubro 2021
  • Setembro 2021

Categories

  • Sem categorias
Trend RepositoryArticles and guides
Articles

Executando Comandos Shell em Java

On Outubro 23, 2021 by admin
  • Introdução
  • Runtime.exec()
  • Executar um comando a partir de String
  • Especifique o diretório de trabalho
  • Utilizando variáveis de ambiente
  • Executar ficheiros .bat e .sh
  • ProcessBuilder
  • ProcessBuilder: Executando comando a partir de Strings
  • ProcessBuilder: Especifique o diretório de trabalho
  • ProcessBuilder: Variáveis de Ambiente
  • ProcessBuilder: Executando arquivos .bat e .sh
  • Conclusão

Introdução

Neste artigo, vamos dar uma olhada em como podemos aproveitar as classes Runtime e ProcessBuilder para executar comandos e scripts shell com Java.

Usamos computadores para automatizar muitas coisas em nossos trabalhos diários. Os administradores de sistema executam muitos comandos o tempo todo, alguns dos quais são muito repetitivos e requerem mudanças mínimas entre execuções.

Este processo também é maduro para automação. Não há necessidade de executar tudo manualmente. Usando Java, podemos executar comandos shell únicos ou múltiplos, executar scripts shell, executar o prompt de terminal/comando, definir diretórios de trabalho e manipular variáveis de ambiente através das classes centrais.

Runtime.exec()

A classe Runtime em Java é uma classe de alto nível, presente em cada aplicação Java. Através dela, a própria aplicação se comunica com o ambiente em que está em.

Extraindo o tempo de execução associado à nossa aplicação através do método getRuntime(), podemos usar o método exec() para executar comandos diretamente ou executar arquivos .bat/.sh.

O método exec() oferece algumas variações sobrecarregadas:

  • public Process exec(String command) – Executa o comando contido em command em um processo separado.
  • public Process exec(String command, String envp) – Executa o command, com um array de variáveis de ambiente. Eles são fornecidos como um array de Strings, seguindo o formato name=value.
  • public Process exec(String command, String envp, File dir) – Executa o comando command, com as variáveis de ambiente especificadas, de dentro do diretório dir.
  • public Process exec(String cmdArray) – Executa um comando na forma de um array de Strings.
  • public Process exec(String cmdArray, String envp) – Executa um comando com as variáveis de ambiente especificadas.
  • public Process exec(String cmdarray, String envp, File dir) – Executa um comando, com as variáveis de ambiente especificadas, de dentro do diretório dir.

Vale notar que estes processos são executados externamente a partir do interpretador e serão dependentes do sistema.

O que também vale a pena notar é a diferença entre String command e String cmdArray. Eles conseguem a mesma coisa. Um command é quebrado em um array de qualquer maneira, então usar qualquer um destes dois deve render os mesmos resultados.

Cabe a você decidir se exec("dir /folder") ou exec(new String{"dir", "/folder"} é o que você gostaria de usar.

Vamos escrever alguns exemplos para ver como estes métodos sobrecarregados diferem um do outro.

Executar um comando a partir de String

Vamos começar com a abordagem mais simples destes três:

Process process = Runtime.getRuntime().exec("ping www.stackabuse.com");

Executar este código irá executar o comando que fornecemos em formato String. No entanto, não vemos nada quando executamos isto.

Para validar se isto rodou corretamente, vamos querer pegar o objeto process. Vamos usar um BufferedReader para dar uma olhada no que está acontecendo:

public static void printResults(Process process) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); String line = ""; while ((line = reader.readLine()) != null) { System.out.println(line); }}

Agora, quando rodarmos este método após o método exec(), ele deve render algo na linha de:

Pinging www.stackabuse.com with 32 bytes of data:Reply from 104.18.57.23: bytes=32 time=21ms TTL=56Reply from 104.18.57.23: bytes=32 time=21ms TTL=56Reply from 104.18.57.23: bytes=32 time=21ms TTL=56Reply from 104.18.57.23: bytes=32 time=21ms TTL=56Ping statistics for 104.18.57.23: Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),Approximate round trip times in milli-seconds: Minimum = 21ms, Maximum = 21ms, Average = 21ms

Cuidado que teremos que extrair a informação do processo das instâncias Process enquanto passamos por outros exemplos.

Especifique o diretório de trabalho

Se você quiser executar um comando de, digamos, uma determinada pasta, nós faremos algo na linha de:

Process process = Runtime.getRuntime() .exec("cmd /c dir", null, new File("C:\Users\")); //.exec("sh -c ls", null, new File("Pathname")); for non-Windows usersprintResults(process);

Aqui, nós fornecemos o método exec() com um command, um null para novas variáveis de ambiente e um new File() que é definido como nosso diretório de trabalho.

A adição de cmd /c antes de um comando como dir é digno de nota.

Desde que estou a trabalhar no Windows, isto abre os cmd e /c executa o comando subsequente. Neste caso, é dir.

A razão pela qual isto não era obrigatório para o exemplo ping, mas é obrigatório para este exemplo é agradavelmente respondido por um utilizador SO.

Executar o código anterior resultará em:

Volume in drive C has no label. Volume Serial Number is XXXX-XXXX Directory of C:\Users08/29/2019 05:01 PM <DIR> .08/29/2019 05:01 PM <DIR> ..08/18/2016 09:11 PM <DIR> Default.migrated08/29/2019 05:01 PM <DIR> Public05/15/2020 11:08 AM <DIR> User 0 File(s) 0 bytes 5 Dir(s) 212,555,214,848 bytes free

Vejamos como podemos fornecer o comando anterior em várias partes individuais, em vez de uma única String:

Process process = Runtime.getRuntime().exec( new String{"cmd", "/c", "dir"}, null, new File("C:\Users\")); printResults(process);

Executar este código também resultará:

Volume in drive C has no label. Volume Serial Number is XXXX-XXXX Directory of C:\Users08/29/2019 05:01 PM <DIR> .08/29/2019 05:01 PM <DIR> ..08/18/2016 09:11 PM <DIR> Default.migrated08/29/2019 05:01 PM <DIR> Public05/15/2020 11:08 AM <DIR> User 0 File(s) 0 bytes 5 Dir(s) 212,542,808,064 bytes free

Ultimamente, independentemente da abordagem – usando uma única String ou um array String, o comando que você inserir será sempre decomposto em um array antes de ser processado pela lógica subjacente.

Qual você gostaria de usar resume-se a qual você acha mais legível.

Utilizando variáveis de ambiente

Vamos dar uma olhada em como podemos usar variáveis de ambiente:

Process process = Runtime.getRuntime().exec( "cmd /c echo %var1%", new String{"var1=value1"}); printResults(process);

Podemos fornecer tantas variáveis de ambiente quantas quisermos dentro do array String. Aqui, acabamos de imprimir o valor de var1 usando echo.

Executar este código retornará:

value1

Executar ficheiros .bat e .sh

Às vezes, é muito mais fácil descarregar tudo num ficheiro e executar esse ficheiro em vez de adicionar tudo programmaticamente.

Dependente do seu sistema operativo, você usaria ficheiros .bat ou .sh. Vamos criar um com o conteúdo:

echo Hello World

Então, vamos usar a mesma abordagem de antes:

Process process = Runtime.getRuntime().exec( "cmd /c start file.bat", null, new File("C:\Users\User\Desktop\"));

Isto vai abrir o prompt de comando e executar o arquivo .bat no diretório de trabalho que nós definimos.

Executar este código certamente resulta em:

Com todas as assinaturas sobrecarregadas exec() tratadas, vamos dar uma olhada na classe ProcessBuilder e como podemos executar comandos usando-a.

ProcessBuilder

ProcessBuilder é o mecanismo subjacente que executa os comandos quando usamos o método Runtime.getRuntime().exec():

/** * Executes the specified command and arguments in a separate process with * the specified environment and working directory. *...*/public Process exec(String cmdarray, String envp, File dir) throws IOException { return new ProcessBuilder(cmdarray) .environment(envp) .directory(dir) .start();}

JavaDocs para a classe Runtime>

Dando uma olhada em como o ProcessBuilder pega nossa entrada do método exec() e executa o comando, nos dá uma boa idéia de como usá-lo também.

Aceita um String cmdarray, e isso é o suficiente para o pôr a correr. Alternativamente, podemos fornecê-lo com argumentos opcionais como o String envp e File dir.

Vamos explorar estas opções.

ProcessBuilder: Executando comando a partir de Strings

Em vez de poder fornecer uma única String, como cmd /c dir, teremos que quebrá-la neste caso. Por exemplo, se quiséssemos listar os arquivos no diretório C:/Users como antes, faríamos:

ProcessBuilder processBuilder = new ProcessBuilder();processBuilder.command("cmd", "/c", "dir C:\Users");Process process = processBuilder.start();printResults(process);

Para realmente executar um Process, executamos o comando start() e atribuímos o valor retornado a uma instância Process

Executar este código renderá:

 Volume in drive C has no label. Volume Serial Number is XXXX-XXXX Directory of C:\Users08/29/2019 05:01 PM <DIR> .08/29/2019 05:01 PM <DIR> ..08/18/2016 09:11 PM <DIR> Default.migrated08/29/2019 05:01 PM <DIR> Public05/15/2020 11:08 AM <DIR> User 0 File(s) 0 bytes 5 Dir(s) 212,517,294,080 bytes free

No entanto, esta abordagem não é melhor do que a anterior. O que é útil com a classe ProcessBuilder é que ela é personalizável. Podemos definir as coisas programmaticamente, não apenas através de comandos.

ProcessBuilder: Especifique o diretório de trabalho

Em vez de fornecer o diretório de trabalho através do comando, vamos configurá-lo programmaticamente:

processBuilder.command("cmd", "/c", "dir").directory(new File("C:\Users\"));

Aqui, definimos o diretório de trabalho como sendo o mesmo de antes, mas movemos essa definição para fora do próprio comando. Executando este código irá fornecer o mesmo resultado que o último exemplo.

ProcessBuilder: Variáveis de Ambiente

Usando métodos ProcessBuilders, é fácil recuperar uma lista de variáveis de ambiente na forma de um Map. Também é fácil definir variáveis de ambiente para que seu programa possa usá-las.

Vamos obter as variáveis de ambiente atualmente disponíveis e então adicionar algumas para uso posterior:

ProcessBuilder processBuilder = new ProcessBuilder();Map<String, String> environmentVariables = processBuilder.environment();environmentVariables.forEach((key, value) -> System.out.println(key + value));

Aqui, empacotamos as variáveis de ambiente retornadas em um Map e rodamos um forEach() nele para imprimir os valores para nosso console.

Executar este código renderá uma lista das variáveis de ambiente que você tem na sua máquina:

DriverDataC:\Windows\System32\Drivers\DriverDataHerokuPathE:\HerokuProgramDataC:\ProgramData...

Agora, vamos adicionar uma variável de ambiente a essa lista e usá-la:

environmentVariables.put("var1", "value1");processBuilder.command("cmd", "/c", "echo", "%var1%");Process process = processBuilder.start();printResults(process);

Executar este código renderá:

value1

A partir do momento em que o programa terminar de rodar, esta variável não ficará na lista.

ProcessBuilder: Executando arquivos .bat e .sh

Se você gostaria de executar um arquivo, novamente, nós apenas forneceríamos a instância ProcessBuilder com as informações necessárias:

processBuilder .command("cmd", "/c", "start", "file.bat") .directory(new File("C:\Users\User\Desktop"));Process process = processBuilder.start();

Executar este código resulta na abertura do prompt de comando e execução do arquivo .bat>

Conclusão

Neste artigo, nós exploramos exemplos de comandos shell em execução em Java. Usamos as classes Runtime e ProcessBuilder para fazer isto.

Usando Java, podemos executar comandos shell simples ou múltiplos, executar scripts shell, rodar o prompt do terminal/comando, definir diretórios de trabalho e manipular variáveis de ambiente através das classes centrais.

Deixe uma resposta Cancelar resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *

Arquivo

  • Janeiro 2022
  • Dezembro 2021
  • Novembro 2021
  • Outubro 2021
  • Setembro 2021

Meta

  • Iniciar sessão
  • Feed de entradas
  • Feed de comentários
  • WordPress.org
  • DeutschDeutsch
  • NederlandsNederlands
  • SvenskaSvenska
  • DanskDansk
  • EspañolEspañol
  • FrançaisFrançais
  • PortuguêsPortuguês
  • ItalianoItaliano
  • RomânăRomână
  • PolskiPolski
  • ČeštinaČeština
  • MagyarMagyar
  • SuomiSuomi
  • 日本語日本語

Copyright Trend Repository 2022 | Theme by ThemeinProgress | Proudly powered by WordPress