- Выполнение команд оболочки с помощью Java
- Вступление
- Время выполнения.exec()
- Выполнение команды из строки
- Укажите рабочий каталог
- Использование Переменных Среды
- Запуск файлов .bat и .sh
- Git Essentials
- Конструктор процессов
- ProcessBuilder: Выполнение команды из строк
- ProcessBuilder: Укажите рабочий каталог
- ProcessBuilder: Переменные среды
- ProcessBuilder: Запуск файлов .bat и .sh
- Вывод
- Как с помощью Java выполнить Shell-команду
- Обзор
- Зависимость операционной системы
- Ввод и вывод
- Runtime.exec()
- ProcessBuilder
- Заключение
- Выполнение консольной команды в java se
- Русские Блоги
- Java-программа выполняет команды Linux
Выполнение команд оболочки с помощью Java
В этом уроке мы рассмотрим, как выполнять команды оболочки, файлы bat и sh на Java. Мы рассмотрим примеры для всех подходов exec() и ProcessBuilder.
Автор: David Landup
Дата записи
Вступление
В этой статье мы рассмотрим, как мы можем использовать классы Runtime и ProcessBuilder для выполнения команд и сценариев оболочки с помощью Java.
Мы используем компьютеры для автоматизации многих вещей в нашей повседневной работе. Системные администраторы постоянно выполняют множество команд, некоторые из которых очень повторяющиеся и требуют минимальных изменений в промежутках между запусками.
Этот процесс также созрел для автоматизации. Нет необходимости запускать все вручную. Используя Java, мы можем запускать одну или несколько команд оболочки, выполнять сценарии оболочки, запускать терминал/командную строку, устанавливать рабочие каталоги и управлять переменными среды с помощью основных классов.
Время выполнения.exec()
Класс Runtime в Java-это класс высокого уровня, присутствующий в каждом отдельном приложении Java. Через него само приложение взаимодействует с окружающей средой, в которой оно находится.
Извлекая среду выполнения, связанную с нашим приложением, с помощью метода getRuntime () , мы можем использовать метод exec() для прямого выполнения команд или запуска файлов .bat /|. sh .
Метод exec() предлагает несколько перегруженных вариантов:
- публичный процесс exec(строковая команда) – Выполняет команду, содержащуюся в command , в отдельном процессе.
- публичный процесс exec(строковая команда, Строка[] envp) – Выполняет команду | с массивом переменных среды. Они представлены в виде массива строк, следующих за форматом имя=значение . публичный процесс exec(Строковая команда, Строка[] envp, директория файла)
- — Выполняет команду с указанными переменными среды из каталога | каталога. публичный процесс exec(Строка cmdArray[]) – Выполняет команду в виде массива строк.
- публичный процесс exec(Строка cmdArray[], Строка[] envp) – Выполняет команду с указанными переменными среды.
- публичный процесс exec(Строка cmdarray[], Строка[] envp, файл dir) – Выполняет команду с указанными переменными среды из каталога
- dir .
Стоит отметить, что эти процессы запускаются извне из интерпретатора и будут зависеть от системы.
Что также стоит отметить, так это разницу между Строковой командой и Строковой командой cmdArray[] . Они достигают одного и того же. Команда | в любом случае разбивается на массив, поэтому использование любого из этих двух должно привести к одинаковым результатам.
Вам решать, хотите ли вы использовать exec(«директория/папка») или exec(новая строка[] <"директория", "/папка">.
Давайте приведем несколько примеров, чтобы увидеть, чем эти перегруженные методы отличаются друг от друга.
Выполнение команды из строки
Давайте начнем с самого простого подхода из этих трех:
Запуск этого кода приведет к выполнению команды, которую мы предоставили в строковом формате. Однако мы ничего не видим, когда запускаем это.
Чтобы проверить, правильно ли это выполнено, мы захотим получить доступ к объекту process . Давайте воспользуемся BufferedReader , чтобы взглянуть на то, что происходит:
Теперь, когда мы запускаем этот метод после метода exec () , он должен дать что-то вроде:
Имейте в виду, что нам придется извлекать информацию о процессе из экземпляров Process , когда мы будем рассматривать другие примеры.
Укажите рабочий каталог
Если вы хотите запустить команду, скажем, из определенной папки, мы бы сделали что-то вроде:
Здесь мы предоставили методу exec() команду , null для новых переменных среды и новый файл () , который установлен в качестве вашего рабочего каталога.
Стоит отметить добавление cmd/c перед такой командой, как dir .
Поскольку я работаю в Windows, это открывает cmd и /c выполняет последующую команду. В данном случае это реж. .
Причина, по которой это не было обязательным для примера ping , но является обязательным для этого примера, хорошо ответил пользователь SO.
Запуск предыдущего фрагмента кода приведет к:
Давайте посмотрим, как мы могли бы предоставить предыдущую команду в нескольких отдельных частях, а не в одной строке:
Запуск этого фрагмента кода также приведет к:
В конечном счете, независимо от подхода – с использованием одной строки или массива строк, вводимая вами команда всегда будет разбита на массив перед обработкой базовой логикой.
Какой из них вы хотели бы использовать, сводится только к тому, какой из них вы считаете более читабельным.
Использование Переменных Среды
Давайте посмотрим, как мы можем использовать переменные среды:
Мы можем предоставить столько переменных среды, сколько захотим, в строковом массиве. Здесь мы только что напечатали значение var1 , используя echo .
Выполнение этого кода вернет:
Запуск файлов .bat и .sh
Иногда просто гораздо проще выгрузить все в файл и запустить этот файл вместо того, чтобы добавлять все программно.
В зависимости от вашей операционной системы вы будете использовать файлы .bat или|/. sh|/. Давайте создадим его с содержимым:
Git Essentials
Ознакомьтесь с этим практическим руководством по изучению Git, содержащим лучшие практики и принятые в отрасли стандарты. Прекратите гуглить команды Git и на самом деле изучите это!
Тогда давайте воспользуемся тем же подходом, что и раньше:
Это откроет командную строку и запустит файл .bat в заданном нами рабочем каталоге.
Запуск этого кода, несомненно, приведет к:
Теперь, когда все перегруженные exec() подписи устранены, давайте рассмотрим класс ProcessBuilder и то, как мы можем выполнять команды с его помощью.
Конструктор процессов
ProcessBuilder является базовым механизмом, который выполняет команды при использовании метода Runtime.getRuntime().exec() :
JavaDocs для Время выполнения класс
Взглянув на то, как ProcessBuilder принимает наши входные данные из метода exec() и запускает команду, мы также получаем хорошее представление о том, как ее использовать.
Он принимает строку [] cmdarray , и этого достаточно, чтобы запустить его. В качестве альтернативы мы можем предоставить ему дополнительные аргументы, такие как String[] envp и File dir .
Давайте рассмотрим эти варианты.
ProcessBuilder: Выполнение команды из строк
Вместо того, чтобы предоставлять одну строку , такую как cmd/c dir , в этом случае нам придется разбить ее. Например, если бы мы хотели перечислить файлы в C:/Users каталог, как и раньше, мы бы сделали:
Чтобы фактически выполнить Процесс , мы запускаем команду start() и присваиваем возвращаемое значение экземпляру Процесса .
Запуск этого кода приведет к:
Однако этот подход ничем не лучше предыдущего. Что полезно в классе ProcessBuilder , так это то, что он настраивается. Мы можем устанавливать вещи программно, а не только с помощью команд.
ProcessBuilder: Укажите рабочий каталог
Вместо того, чтобы указывать рабочий каталог с помощью команды, давайте установим его программно:
Здесь мы установили рабочий каталог таким же, как и раньше, но мы удалили это определение из самой команды. Выполнение этого кода даст тот же результат, что и в предыдущем примере.
ProcessBuilder: Переменные среды
Используя методы ProcessBuilder , легко получить список переменных среды в виде Карты . Также легко установить переменные среды, чтобы ваша программа могла их использовать.
Давайте получим переменные среды, доступные в настоящее время, а затем добавим некоторые для последующего использования:
Здесь мы упаковали возвращенные переменные среды в Map и запустили forEach() на нем, чтобы распечатать значения на нашей консоли.
Выполнение этого кода приведет к получению списка переменных среды, имеющихся на вашем компьютере:
Теперь давайте добавим переменную среды в этот список и будем использовать ее:
Запуск этого кода приведет к:
Конечно, как только программа завершит работу, эта переменная не останется в списке.
ProcessBuilder: Запуск файлов .bat и .sh
Если вы хотите снова запустить файл, мы просто предоставим экземпляру ProcessBuilder необходимую информацию:
Выполнение этого кода приводит к открытию командной строки и выполнению файла .bat .:
Вывод
В этой статье мы рассмотрели примеры выполнения команд оболочки на Java. Для этого мы использовали классы Runtime и ProcessBuilder .
Используя Java, мы можем запускать одну или несколько команд оболочки, выполнять сценарии оболочки, запускать терминал/командную строку, устанавливать рабочие каталоги и управлять переменными среды с помощью основных классов.
Как с помощью Java выполнить Shell-команду
Обзор
В этом руководстве мы рассмотрим два способа выполнения shell -команд из программы на Java . Первый способ – использовать класс Runtime и вызвать его метод exec . Второй (более гибкий способ) – создать экземпляр класса ProcessBuilder .
Зависимость операционной системы
Сначала нужно определить операционную систему, на которой работает наша JVM . В Windows необходимо запустить команду в качестве аргумента оболочки cmd.exe, а в остальных ОС мы будем использовать стандартную оболочку sh:
Ввод и вывод
Также нужно подключиться к входным и выходным потокам нашего процесса. По крайней мере, нужно получить выходные данные, иначе процесс зависнет.
Реализуем класс StreamGobbler, который использует InputStream :
Примечание. Этот класс реализует интерфейс Runnable , а это означает, что он может быть выполнен любым исполнителем.
Runtime.exec()
Метод Runtime.exec() — это простой, но недостаточно гибкий способ создания нового подпроцесса .
В следующем примере мы запросим список пользователей из локальной директории и выведем его в консоли:
ProcessBuilder
Класс ProcessBuilder является более гибким в использовании, чем Runtime. Он позволяет настраивать целый ряд параметров.
- изменить рабочий каталог, в котором работает shell-команда,
- перенаправить потоки ввода и вывода;
- наследовать их в потоках текущего процесса JVM, используя builder.inheritIO().
Заключение
Shell команды в Java можно выполнять двумя различными способами. Но если нужно настроить выполнение созданного процесса, то используйте класс ProcessBuilder .
Программные исходники примеров, приведенных в этой статье, доступны на GitHub .
Вадим Дворников автор-переводчик статьи « How to Run a Shell Command in Java »
Выполнение консольной команды в java se
подскажите как с помощью java se можно выполнить консольную команду: useradd -m -g papka -p 123456 sky
Сможете показать пример. а то чет разобраться не могу.
Копайте в сторону java.lang.ProcessBuilder.
Спасибо) теперь разобрался вроде бы)
вообще, толку от такого запуска 0, вдруг там попросят пароль ввести или нафиг пошлют, а ты сидишь и ждешь waitFor
Ну это джава же. Ждать когда она пролагается — единственный сценарий ее использования.
можно запустить процесс в жавном эмуляторе терминала, парсить выхлоп и expect’ом ждать всё что нужно
Русские Блоги
Java-программа выполняет команды Linux
Выполнение команд linux в программах Java в основном зависит от двух категорий: Process и Runtime
Сначала посмотрите на класс Process:
- Методы ProcessBuilder.start () и Runtime.exec создают собственный процесс и возвращают экземпляр подкласса Process.
- Этот экземпляр можно использовать для управления процессом и получения соответствующей информации. Категория «Процесс» обеспечивает выполнение от ввода процесса, вывод выполнения до процесса, ожидание завершения процесса,
- Проверьте состояние выхода процесса и как уничтожить (убить) процесс. к
- Метод создания процесса может не работать для определенных процессов на некоторых собственных платформах, таких как процессы собственного окна, процессы демона, Microsoft Windows
- Процесс Win16 / DOS или скрипт оболочки на предыдущей странице. Созданный дочерний процесс не имеет собственного терминала или консоли. Все его стандарты io (т.е. stdin, stdout и stderr)
- Операции будут перенаправлены в родительский процесс через три потока (getOutputStream (), getInputStream () и getErrorStream ()). к
- Родительский процесс использует эти потоки для предоставления входных данных дочернему процессу и получения выходных данных дочернего процесса. Поскольку некоторые собственные платформы предоставляют ограниченный размер буфера для стандартных входных и выходных потоков,
- Если выходной поток или входной поток дочернего процесса чтения и записи завершается неудачно, это может привести к блокировке дочернего процесса или даже к возникновению взаимоблокировки. к
- Когда больше нет ссылок на объект Process, вместо удаления дочернего процесса он продолжает выполнять дочерний процесс асинхронно. к
- Для процесса Java с объектом Process нет необходимости выполнять процесс, представленный объектом Process, асинхронно или одновременно. к
Особое внимание следует уделить:
1, Созданный дочерний процесс не имеет собственной терминальной консоли Все операции по маркировке будут проходить через три потока.
(getOutputStream (), getInputStream () и getErrorStream ()) перенаправляют в родительский процесс ( Родительский процесс может судить о выполнении дочернего процесса через эти потоки. )
2. Потому что Некоторые собственные платформы предоставляют ограниченный размер буфера для стандартных потоков ввода и вывода Если выходной поток или входной поток для чтения и записи дочернего процесса завершается неудачно,
Это может привести к блокировке дочернего процесса или даже к тупику
- abstract void destroy()
- Убей дочерний процесс. .
- abstract int exitValue()
- Вернуть значение экспорта дочернего процесса. По соглашению, значение 0 означает нормальное завершение. .
- abstract InputStream getErrorStream()
- Получите поток ошибок дочернего процесса. .
- abstract InputStream getInputStream()
- Получите входной поток дочернего процесса. .
- abstract OutputStream getOutputStream()
- Получите выходной поток дочернего процесса. .
- abstract int waitFor()
- Это заставляет текущий поток ждать. При необходимости он должен ждать, пока процесс, представленный объектом Process, не завершится. к
- Если дочерний процесс был завершен, этот метод немедленно возвращается. Если дочерний процесс не завершен, вызывающий поток будет заблокирован до завершения дочернего процесса. к
Особое внимание следует уделить: если во входном потоке, выходном потоке или потоке ошибок в дочернем процессе больше содержимого, лучше использовать кэш (Обратите внимание на ситуацию 2 выше)
Давайте снова посмотрим на класс Runtime:
- Каждое Java-приложение имеет экземпляр класса Runtime, который позволяет приложению подключаться к среде, в которой оно выполняется. Текущую среду выполнения можно получить с помощью метода getRuntime. .
- Приложение не может создать свой собственный экземпляр класса Runtime. .
Введите несколько основных методов:
- Process exec(String command)
- Выполнить указанную строковую команду в отдельном процессе. к
- Process exec(String command, String[] envp)
- Выполните указанную строковую команду в отдельном процессе в указанной среде. к
- Process exec(String command, String[] envp, File dir)
- Выполните указанную строковую команду в независимом процессе с указанной средой и рабочим каталогом. к
- Process exec(String[] cmdarray)
- Выполните назначенные команды и переменные в отдельном процессе. .
- Process exec(String[] cmdarray, String[] envp)
- Выполнять назначенные команды и переменные в независимом процессе в назначенной среде. .
- Process exec(String[] cmdarray, String[] envp, File dir)
- Выполните указанные команды и переменные в независимом процессе указанной среды и рабочего каталога. .
команда: указанная системная команда.
envp: Строковый массив переменных среды, где форматом установки каждой переменной среды является имя = значение; если дочерний процесс должен наследовать среду текущего процесса, этот параметр имеет значение null.
dir: рабочий каталог дочернего процесса, если дочерний процесс должен наследовать рабочий каталог текущего процесса, этот параметр имеет значение null.
cmdarray: массив, содержащий вызываемые команды и их параметры.
Ниже приведен пример (его нужно пометить как исполняемый пакет jar и выбросить под linux для выполнения):
- public class test <
- public static void main(String[] args) <
- InputStream in = null ;
- try <
- Process pro = Runtime.getRuntime().exec( new String[] < "sh" ,
- «/home/test/test.sh» , «select admin from M_ADMIN» ,
- «/home/test/result.txt» >);
- pro.waitFor();
- in = pro.getInputStream();
- BufferedReader read = new BufferedReader( new InputStreamReader(in));
- String result = read.readLine();
- System.out.println( «INFO:» +result);
- > catch (Exception e) <
- e.printStackTrace();
- >
- >
- >
Здесь используется метод Process exec (String [] cmdarray)
Сценарий /home/test/test.sh выглядит следующим образом:
- #!/bin/sh
- #Query sql
- SQL=$1
- # Запрос сохранить файл сохранения
- RESULT_FILE=$2
- # Подключение к базе данных
- DB_NAME=scott
- DB_PWD=tiger
- DB_SERVER=DB_TEST
- RESULT=`sqlplus -S $
/$ @$ - set heading off
- set echo off
- set pages 0
- set feed off
- set linesize 3000
- $
- /
- commit
- /
- !`
- echo «$
» >> $ - echo 0;
Особое внимание следует обратить на тот факт, что когда выполняемая команда linux имеет символ канала (например, ps -ef | grep java), описанный выше метод не будет работать. Решение состоит в том, чтобы передать команду, которая будет выполнена, в качестве параметра оболочке
- public class Test <
- public static void main(String[] args) throws Exception <
- String[] cmds = < "/bin/sh" , "-c" , "ps -ef|grep java" >;
- Process pro = Runtime.getRuntime().exec(cmds);
- pro.waitFor();
- InputStream in = pro.getInputStream();
- BufferedReader read = new BufferedReader( new InputStreamReader(in));
- String line = null ;
- while ((line = read.readLine())!= null ) <
- System.out.println(line);
- >
- >
- >
Runtime.getRuntime (). Exec () очень ресурсоемкий в виртуальной машине Java. Даже если команда может быть выполнена быстро, создание процесса потребляет очень объективно во время частых вызовов.
Процесс выполнения этой команды в виртуальной машине Java, прежде всего, клон Процесс, имеющий те же переменные среды, что и текущая виртуальная машина, затем использует этот новый процесс для выполнения внешних команд и, наконец, завершает процесс. Частое создание потребляет много ресурсов процессора и памяти