Comment exécuter une commande shell en Java

Vue d’ensemble

Avec ce tutoriel, nous allons illustrer les deux façons d’exécuter une commande shell à partir du code Java.

La première consiste à utiliser la classe Runtime et à appeler sa méthode exec.

La deuxième façon, plus personnalisable, sera de créer et d’utiliser une instance ProcessBuilder.

Dépendance du système d’exploitation

Avant de créer un nouveau processus exécutant notre commande shell, nous devons d’abord déterminer le système d’exploitation sur lequel notre JVM fonctionne.

C’est parce que, sur Windows, nous devons exécuter notre commande comme argument du shell cmd.exe et sur tous les autres systèmes d’exploitation, nous pouvons émettre un shell standard, appelé sh:

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

Entrée et sortie

De plus, nous avons besoin d’un moyen de nous accrocher aux flux d’entrée et de sortie de notre processus.

Au moins la sortie doit être consommée – sinon notre processus ne retourne pas avec succès, au lieu de cela il se bloque.

Mettons en œuvre une classe couramment utilisée appelée StreamGobbler qui consomme 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); }}

NOTE : Cette classe implémente l’interface Runnable, ce qui signifie qu’elle pourrait être exécutée par n’importe quel Executor.

Runtime.exec()

Un appel de méthode à Runtime.exec() est un moyen simple, pas encore personnalisable, de frayer un nouveau sous-processus.

Dans l’exemple suivant, nous allons demander une liste de répertoires du répertoire personnel d’un utilisateur et l’imprimer sur la console:

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

Pour la deuxième implémentation de notre problème de calcul, nous allons utiliser un ProcessBuilder. Cette approche est préférée à celle du Runtime car nous sommes en mesure de personnaliser certains détails.

Par exemple, nous sommes en mesure de :

  • changer le répertoire de travail dans lequel s’exécute notre commande shell en utilisant builder.directory()
  • établir une carte clé-valeur personnalisée comme environnement en utilisant builder.environment()
  • rediriger les flux d’entrée et de sortie vers des remplacements personnalisés
  • hériter les deux vers les flux du processus JVM actuel en utilisant 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;

Conclusion

Comme nous l’avons vu dans ce rapide tutoriel, nous pouvons exécuter une commande shell en Java de deux manières distinctes.

Généralement, si vous prévoyez de personnaliser l’exécution du processus spawné, par exemple, pour changer son répertoire de travail, vous devriez envisager d’utiliser un ProcessBuilder.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.