Cum se execută o comandă shell în Java

Vizualizare generală

Cu acest tutorial vom ilustra cele două moduri de a executa o comandă shell din interiorul codului Java.

Primul este de a folosi clasa Runtime și de a apela metoda sa exec.

Cel de-al doilea mod, mai personalizabil, va fi de a crea și folosi o instanță ProcessBuilder.

Dependența de sistemul de operare

Înainte de a crea un nou Process care să execute comanda noastră shell, trebuie să determinăm mai întâi sistemul de operare pe care rulează JVM-ul nostru.

Aceasta pentru că, pe Windows, trebuie să executăm comanda noastră ca argument la cmd.exe shell, iar pe toate celelalte sisteme de operare putem emite un shell standard, numit sh:

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

Intrare și ieșire

În plus, avem nevoie de o modalitate de a ne conecta la fluxurile de intrare și ieșire ale procesului nostru.

Cel puțin ieșirea trebuie să fie consumată – altfel procesul nostru nu se întoarce cu succes, în schimb se va bloca.

Să implementăm o clasă folosită în mod obișnuit, numită StreamGobbler, care consumă un InputStream:

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); }}

NOTA: Această clasă implementează interfața Runnable, ceea ce înseamnă că poate fi executată de orice Executor.

Runtime.exec()

Un apel la metoda Runtime.exec() este o modalitate simplă, încă nepersonalizabilă, de a genera un nou subproces.

În exemplul următor vom solicita o listă de directoare a directorului de acasă al unui utilizator și imprimarea acesteia în consolă:

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

Pentru a doua implementare a problemei noastre de calcul, vom folosi un ProcessBuilder. Aceasta este preferată față de abordarea Runtime deoarece putem personaliza unele detalii.

De exemplu, putem:

  • modifica directorul de lucru în care se execută comanda noastră shell folosind constructorul.directory()
  • configurarea unei hărți cheie-valoare personalizate ca mediu folosind builder.environment()
  • redirecționarea fluxurilor de intrare și de ieșire către înlocuitori personalizați
  • moștenirea ambelor fluxuri către fluxurile procesului JVM curent folosind 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;

Concluzie

După cum am văzut în acest tutorial rapid, putem executa o comandă shell în Java în două moduri distincte.

În general, dacă intenționați să personalizați execuția procesului generat, de exemplu, pentru a-i schimba directorul de lucru, ar trebui să luați în considerare utilizarea unui ProcessBuilder.

.

Lasă un răspuns

Adresa ta de email nu va fi publicată.