Как запустить команду оболочки в Java

Как выполнить команду оболочки в Java

1. обзор

В этом руководстве мы проиллюстрируем два способаexecuting a shell command from within Java code.

Первый - использовать классRuntime и вызвать его методexec.

Второй и более настраиваемый способ - создать и использовать экземплярProcessBuilder.

2. Зависимость от операционной системы

Прежде чем мы собираемся создать новыйProcess, выполняющий нашу команду оболочки, нам нужно сначала определить операционную систему, в которой работает нашJVM.

Это потому, что вWindows нам нужно запустить нашу команду в качестве аргумента оболочкиcmd.exe, а во всех других операционных системах мы можем запустить стандартную оболочку, называемуюsh:

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

3. Вход и выход

Кроме того ** нам нужен способ подключиться к входным и выходным потокам нашего процесса.

По крайней мере,the output must be consumed - иначе наш процесс не вернется успешно, а просто зависнет.

Давайте реализуем часто используемый классStreamGobbler, который потребляетInputStream:

private static class StreamGobbler implements Runnable {
    private InputStream inputStream;
    private Consumer consumer;

    public StreamGobbler(InputStream inputStream, Consumer consumer) {
        this.inputStream = inputStream;
        this.consumer = consumer;
    }

    @Override
    public void run() {
        new BufferedReader(new InputStreamReader(inputStream)).lines()
          .forEach(consumer);
    }
}

NOTE: Этот класс реализует интерфейсRunnable, что означает, что он может быть выполнен любымExecutor.

4. Runtime.exec()с

Вызов методаRuntime.exec() - это простой, еще не настраиваемый способ порождения нового подпроцесса.

В следующем примере мы запросим каталог-каталог домашнего каталога пользователей и распечатаем его в консоли:

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;

5. ProcessBuilderс

Для второй реализации нашей вычислительной задачи мы будем использоватьProcessBuilder. Это предпочтительнее, чем подходRuntime, потому что мы можем настроить некоторые детали.

Например, мы можем:

  • изменить рабочий каталог, в котором работает наша команда оболочки, используяbuilder.directory()

  • настроить пользовательскую карту "ключ-значение" как среду, используяbuilder.environment()

  • перенаправить потоки ввода и вывода на пользовательские замены

  • наследовать оба из них потокам текущего процессаJVM, используя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;

6. Заключение

Как мы видели в этом кратком руководстве, мы можем выполнить команду оболочки вJava двумя разными способами.

Как правило, если вы планируете настроить выполнение порожденного процесса, например, чтобы изменить его рабочий каталог, вам следует рассмотреть возможность использованияProcessBuilder.

Как всегда, вы найдете источникиon GitHub.