Como executar o script shell Unix a partir do código Java?

É muito simples executar um comando Unix a partir do Java.

Runtime.getRuntime().exec(myCommand); 

Mas é possível executar um script de shell Unix a partir do código Java? Se sim, seria uma boa prática executar um script de shell a partir do código Java?

Você deve realmente olhar para o Process Builder . É realmente construído para esse tipo de coisa.

 ProcessBuilder pb = new ProcessBuilder("myshellScript.sh", "myArg1", "myArg2"); Map env = pb.environment(); env.put("VAR1", "myValue"); env.remove("OTHERVAR"); env.put("VAR2", env.get("VAR1") + "suffix"); pb.directory(new File("myDir")); Process p = pb.start(); 

Eu diria que não é no espírito do Java para executar um script de shell de Java. Java é uma plataforma cruzada e a execução de um script de shell limitaria seu uso apenas ao UNIX.

Com isso dito, é definitivamente possível executar um script de shell dentro do Java. Você usaria exatamente a mesma syntax que você listou (eu não tentei por mim mesmo, mas tente executar o script de shell diretamente, e se isso não funcionar, execute o próprio shell, passando o script como um parâmetro de linha de comando) .

Eu acho que você respondeu sua própria pergunta com

 Runtime.getRuntime().exec(myShellScript); 

Quanto a saber se é uma boa prática … o que você está tentando fazer com um script de shell que você não pode fazer com Java?

Você também pode usar a biblioteca exec do Apache Commons .

Exemplo:

 package testShellScript; import java.io.IOException; import org.apache.commons.exec.CommandLine; import org.apache.commons.exec.DefaultExecutor; import org.apache.commons.exec.ExecuteException; public class TestScript { int iExitValue; String sCommandString; public void runScript(String command){ sCommandString = command; CommandLine oCmdLine = CommandLine.parse(sCommandString); DefaultExecutor oDefaultExecutor = new DefaultExecutor(); oDefaultExecutor.setExitValue(0); try { iExitValue = oDefaultExecutor.execute(oCmdLine); } catch (ExecuteException e) { System.err.println("Execution failed."); e.printStackTrace(); } catch (IOException e) { System.err.println("permission denied."); e.printStackTrace(); } } public static void main(String args[]){ TestScript testScript = new TestScript(); testScript.runScript("sh /root/Desktop/testScript.sh"); } } 

Para referência adicional, um exemplo é fornecido no Apache Doc também.

Sim, é possível fazer isso. Isso funcionou para mim.

 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import org.omg.CORBA.portable.InputStream; public static void readBashScript() { try { Process proc = Runtime.getRuntime().exec("/home/destino/workspace/JavaProject/listing.sh /"); //Whatever you want to execute BufferedReader read = new BufferedReader(new InputStreamReader( proc.getInputStream())); try { proc.waitFor(); } catch (InterruptedException e) { System.out.println(e.getMessage()); } while (read.ready()) { System.out.println(read.readLine()); } } catch (IOException e) { System.out.println(e.getMessage()); } } 

Aqui está o meu exemplo. Espero que faça sentido.

 public static void excuteCommand(String filePath) throws IOException{ File file = new File(filePath); if(!file.isFile()){ throw new IllegalArgumentException("The file " + filePath + " does not exist"); } if(this.isLinux()){ Runtime.getRuntime().exec(new String[] {"/bin/sh", "-c", filePath}, null); }else if(this.isWindows()){ Runtime.getRuntime().exec("cmd /c start " + filePath); } } public static boolean isLinux(){ String os = System.getProperty("os.name"); return os.toLowerCase().indexOf("linux") >= 0; } public static boolean isWindows(){ String os = System.getProperty("os.name"); return os.toLowerCase().indexOf("windows") >= 0; } 

Sim, é possível e você respondeu isso! Sobre boas práticas, acho que é melhor lançar comandos de arquivos e não diretamente de seu código. Portanto, você precisa fazer com que o Java execute a lista de comandos (ou um comando) em arquivos .bat, .sh, .ksh … existentes. Aqui está um exemplo de execução de uma lista de comandos em um arquivo “MyFile.sh”:

  String[] cmd = { "sh", "MyFile.sh", "\pathOfTheFile"}; Runtime.getRuntime().exec(cmd); 

A biblioteca ZT Process Executor é uma alternativa ao Apache Commons Exec. Possui funcionalidade para executar comandos, capturar sua saída, definir tempos limite, etc.

Eu não usei ainda, mas parece razoavelmente bem documentado.

Um exemplo da documentação: Executando um comando, bombeando o stderr para um logger, retornando a saída como string UTF8.

  String output = new ProcessExecutor().command("java", "-version") .redirectError(Slf4jStream.of(getClass()).asInfo()) .readOutput(true).execute() .outputUTF8(); 

Sua documentação lista as seguintes vantagens sobre o Commons Exec:

  • Melhor manuseio de streams
    • Leitura / escrita para streams
    • Redirecionando stderr para stdout
  • Melhor manuseio de tempos limite
  • Verificação aprimorada dos códigos de saída
  • API aprimorada
    • Um forros para casos de uso bastante complexos
    • Um forros para obter saída do processo em uma String
    • Acesso ao object Process disponível
    • Suporte para processos asynchronouss ( futuro )
  • Log aprimorado com a API SLF4J
  • Suporte para múltiplos processos

Quanto a mim, todas as coisas devem ser simples. Para executar o script só precisa executar

 new ProcessBuilder("pathToYourShellScript").start(); 

Para evitar ter que codificar um caminho absoluto, você pode usar o método a seguir que localizará e executará seu script se ele estiver em seu diretório raiz.

 public static void runScript() throws IOException, InterruptedException { ProcessBuilder processBuilder = new ProcessBuilder("./nameOfScript.sh"); //Sets the source and destination for subprocess standard I/O to be the same as those of the current Java process. processBuilder.inheritIO(); Process process = processBuilder.start(); int exitValue = process.waitFor(); if (exitValue != 0) { // check for errors new BufferedInputStream(process.getErrorStream()); throw new RuntimeException("execution of script failed!"); } } 

É possível, apenas executá-lo como qualquer outro programa. Apenas certifique-se de que seu script tenha o número adequado! (she-bang) linha como a primeira linha do script e verifique se há permissions de execução no arquivo.

Por exemplo, se for um script bash, coloque #! / Bin / bas no topo do script, também chmod + x.

Também quanto a se é uma boa prática, não, não, especialmente para Java, mas se você economiza muito tempo transferindo um script grande, e não está sendo pago extra para fazê-lo;) economize seu tempo, execute o script, e colocar a portabilidade para Java em sua lista de tarefas de longo prazo.

  String scriptName = PATH+"/myScript.sh"; String commands[] = new String[]{scriptName,"myArg1", "myArg2"}; Runtime rt = Runtime.getRuntime(); Process process = null; try{ process = rt.exec(commands); process.waitFor(); }catch(Exception e){ e.printStackTrace(); } 

Esta é uma resposta tardia. No entanto, eu pensei em colocar a luta que eu tive que suportar para obter um script de shell a ser executado a partir de um aplicativo Spring-Boot para futuros desenvolvedores.

  1. Eu estava trabalhando no Spring-Boot e não consegui encontrar o arquivo a ser executado a partir do meu aplicativo Java e estava lançando FileNotFoundFoundException . Eu tive que manter o arquivo no diretório de resources e tive que definir o arquivo a ser verificado em pom.xml enquanto o aplicativo estava sendo iniciado como o seguinte.

       src/main/resources true  **/*.xml **/*.properties **/*.sh    
  2. Depois disso eu estava tendo problemas para executar o arquivo e ele estava retornando o error code = 13, Permission Denied . Então eu tive que tornar o arquivo executável executando este comando – chmod u+x myShellScript.sh

Finalmente, eu poderia executar o arquivo usando o seguinte trecho de código.

 public void runScript() { ProcessBuilder pb = new ProcessBuilder("src/main/resources/myFile.sh"); try { Process p; p = pb.start(); } catch (IOException e) { e.printStackTrace(); } } 

Espero que isso resolva o problema de alguém.

Apenas a mesma coisa que o Solaris 5.10 funciona assim ./batchstart.sh existe um truque que eu não sei se o seu SO aceitar usar \\. batchstart.sh \\. batchstart.sh vez disso. Esta barra dupla pode ajudar.

Eu acho com

 System.getProperty("os.name"); 

Verificar o sistema operacional pode gerenciar os scripts shell / bash, se forem suportados. se houver necessidade de tornar o código portátil.