Как с помощью Java выполнить Shell-команду
Обзор
В этом руководстве мы рассмотрим два способа выполнения shell-команд из программы на Java . Первый способ – использовать класс Runtime и вызвать его метод exec. Второй (более гибкий способ) – создать экземпляр класса ProcessBuilder.
Зависимость операционной системы
Сначала нужно определить операционную систему, на которой работает наша JVM . В Windows необходимо запустить команду в качестве аргумента оболочки cmd.exe, а в остальных ОС мы будем использовать стандартную оболочку sh:
boolean isWindows = System.getProperty("os.name")
.toLowerCase().startsWith("windows");
Ввод и вывод
Также нужно подключиться к входным и выходным потокам нашего процесса. По крайней мере, нужно получить выходные данные, иначе процесс зависнет.
Реализуем класс 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, а это означает, что он может быть выполнен любым исполнителем.
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;
ProcessBuilder
Класс ProcessBuilder является более гибким в использовании, чем Runtime. Он позволяет настраивать целый ряд параметров.
Например, можно:
- изменить рабочий каталог, в котором работает shell-команда,
- перенаправить потоки ввода и вывода;
- наследовать их в потоках текущего процесса 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;
Заключение
Shell команды в Java можно выполнять двумя различными способами. Но если нужно настроить выполнение созданного процесса, то используйте класс ProcessBuilder.
Программные исходники примеров, приведенных в этой статье, доступны на GitHub.
Пожалуйста, опубликуйте ваши мнения по текущей теме материала. За комментарии, дизлайки, лайки, подписки, отклики огромное вам спасибо!