Перейти к основному содержимому

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

· 3 мин. чтения

1. Обзор

В этом руководстве мы проиллюстрируем два способа выполнения команды оболочки из кода Java .

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

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

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

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

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

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

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

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

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

Давайте реализуем часто используемый класс StreamGobbler , который использует 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);
}
}

ПРИМЕЧАНИЕ. Этот класс реализует интерфейс Runnable , что означает, что его может выполнять любой Executor .

4. Время выполнения.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 . Это предпочтительнее, чем подход 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 .

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