Shell-komennon suorittaminen Javassa

Yleiskatsaus

Tässä opetusohjelmassa esitellään kaksi tapaa suorittaa shell-komento Java-koodista.

Ensimmäinen tapa on käyttää Runtime-luokkaa ja kutsua sen exec-metodia.

Toinen ja helpommin muokattavissa oleva keino on ProcessBuilder-instanssin luominen ja käyttö.

Operating System Dependency

Ennen kuin luomme uuden prosessin, joka suorittaa komentotulkkikomentomme, meidän on ensin määritettävä käyttöjärjestelmä, jossa JVM:mme toimii.

Se johtuu siitä, että Windowsissa komentomme täytyy suorittaa argumenttina cmd.exe-komentokuorta, ja kaikissa muissa käyttöjärjestelmissä voimme antaa vakiokomentokuorta nimeltä sh:

boolean isWindows = System.getProperty("os.name") .toLowerCase().startsWith("windows");

Syöttö ja ulostulo

Lisäksi tarvitsemme tavan kytkeytyä prosessimme syöttö- ja tulostusvirtoihin.

Vähintäänkin ulostulo on kulutettava – muuten prosessimme ei palaa onnistuneesti, vaan se roikkuu.

Toteutetaan yleisesti käytetty luokka nimeltä StreamGobbler, joka kuluttaa InputStreamin:

private static class StreamGobbler implements Runnable { private InputStream inputStream; private Consumer<String> consumer; public StreamGobbler(InputStream inputStream, Consumer<String> consumer) { this.inputStream = inputStream; this.consumer = consumer; } @Override public void run() { new BufferedReader(new InputStreamReader(inputStream)).lines() .forEach(consumer); }}

Huomautus: Tämä luokka toteuttaa Runnable-rajapinnan, mikä tarkoittaa, että se voitaisiin suorittaa millä tahansa Executor-ohjelmalla.

Runime.exec()

Metodin Runtime.exec() kutsuminen on yksinkertainen, ei vielä muokattavissa oleva tapa synnyttää uusi aliprosessi.

Seuraavassa esimerkissä pyydämme hakemistoluettelon käyttäjän kotihakemistosta ja tulostamme sen konsoliin:

String homeDirectory = System.getProperty("user.home");Process process;if (isWindows) { process = Runtime.getRuntime() .exec(String.format("cmd.exe /c dir %s", homeDirectory));} else { process = Runtime.getRuntime() .exec(String.format("sh -c ls %s", homeDirectory));}StreamGobbler streamGobbler = new StreamGobbler(process.getInputStream(), System.out::println);Executors.newSingleThreadExecutor().submit(streamGobbler);int exitCode = process.waitFor();assert exitCode == 0;

ProcessBuilder

Laskentatehtävämme toisessa toteutuksessa käytämme ProcessBuilderia. Tämä on suositeltavampi kuin Runtime-lähestymistapa, koska pystymme muokkaamaan joitakin yksityiskohtia.

Pystymme esimerkiksi:

  • muuttamaan työhakemistoa, jossa komentotulkkikomentomme suoritetaan Builderin avulla.directory()
  • asettaa mukautetun avain-arvokartan ympäristöksi käyttämällä builder.environment()
  • suuntaa input- ja output-virrat mukautettuihin korvaajiin
  • periä molemmat nykyisen JVM-prosessin virtoihin käyttämällä builder.inheritIO()
ProcessBuilder builder = new ProcessBuilder();if (isWindows) { builder.command("cmd.exe", "/c", "dir");} else { builder.command("sh", "-c", "ls");}builder.directory(new File(System.getProperty("user.home")));Process process = builder.start();StreamGobbler streamGobbler = new StreamGobbler(process.getInputStream(), System.out::println);Executors.newSingleThreadExecutor().submit(streamGobbler);int exitCode = process.waitFor();assert exitCode == 0;

Johtopäätös

Kuten olemme nähneet tässä pikaoppaassa, voimme suorittaa komentotulkkikomennon Javassa kahdella eri tavalla.

Yleisesti, jos aiot muokata käynnistettävän prosessin suoritusta, esimerkiksi vaihtaa sen työhakemistoa, sinun kannattaa harkita ProcessBuilderin käyttöä.

Vastaa

Sähköpostiosoitettasi ei julkaista.