Как запустить shell-команду средствами java?

Мне нужно запустить shell-команду, к примеру: “flick video -a start -p ios” или, по крайней мере, запустить shell-скрипт (.sh).
Как это можно сделать автоматически средствами java?

Для быстроты нахождения ответа, пытайтесь иногда вбивать такие вопросы в поисковик.

Runtime.getRuntime().exec(“ваша команда”);

2 лайка

извиняюсь, не совсем правильно сформулировал вопрос.
Мне нужно запустить стороннюю команду в терминале,
Eclipse жалуется:
“java.io.IOException: Cannot run program “flick”: error=2, No such file or directory”

Если запускать руками в терминале, то все ок.
Судя по всему, Eclipse не знает “не родных” path для shell команд.

Пробовал с помощью Runtime и ProcessBuilder, неудачно.
Any ideas?

Уточните что за терминал, по какому протоколу он работает.
Для справки: Ой!

На текущий момент, насколько мне известно, самым крутым process executor’ом является zt-exec, который впитал в себя все лучшее от ProcessBuilder, Runtime.exec и Apache Commons Exec. Его интуитивно понятный DSL и богатый набор фич оставляет далеко позади все существующие аналоги.

По вашей задаче:

List<String> commands = Arrays.asList("/bin/sh", "flick", "video", "-a", "start", "-p", "ios");
// or Arrays.asList("/bin/sh", "yourScript.sh");

String output = new ProcessExecutor()
                       .command(commands)
                       .readOutput(true)
                       .execute()
                       .outputUTF8();

Судя по предложенному варианту, данный код должен создавать файл .mp4 после завершения, но ничего не происходит (хотя код отрабатывает без ошибок):

	List<String> commands = Arrays.asList("/bin/sh", 
					      "flick", 
					      "video", 
					      "-a", 
					      "start", 
					      "-p", 
					      "ios");
	String output = new ProcessExecutor()
	                       .command(commands)
	                       .readOutput(true)
	                       .execute()
	                       .outputUTF8();

	List<String> commands2 = Arrays.asList("/bin/sh", 
					       "flick", 
					       "video", 
					       "-a", 
					       "stop", 
					       "-p", 
					       "ios", 
					       "-o", 
					       "/Users/aap/Documents/lime-mobile-automation/target/video-rec", 
					       "-n", 
					       "bug");
	String output2 = new ProcessExecutor()
	                       .command(commands2)
	                       .readOutput(true)
	                       .execute()
	                       .outputUTF8();

не уверен, что корректно отвечу на вопрос:

  • платформа Mac
  • terminal Версия 2.6.1 (361.1) (.sh)
  • протокол ssh
  • сторонние ssh библиотеки для java не ставил

В оутпуте поищите свой файл.

также как и для Runtime отдается ошибка:
/bin/sh: flick: No such file or directory (это после вывода output на консоль)

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

П.С. Какой, к слову, output выводится на экран?

А flick - это что вообще? Вы случайно ее не на iPhone пытаетесь запустить? Она физически где находится - на маке или телефоне (только заметил тег appium)? Если на маке, то присутствует ли она в global path, или вы ее запускаете из каталога с самой программой?

GitHub - isonic1/flick: A CLI with helpful QA tools for Android (Devices & Emulators) and iOS (Devices). использую для рекорда видео тестов.

Запускаю на маке, видео снимается с iPad (не эмулятор).

На маке - /Library/Ruby/Gems/2.0.0/gems/flick-0.1.0

запускаю не из каталога, в global path не добавлял. Стоит добавить
/Library/Ruby/Gems/2.0.0/gems/flick-0.1.0/bin,
или - /Library/Ruby/Gems/2.0.0/gems/flick-0.1.0?

Добавил:
echo $PATH
/Library/Ruby/Gems/2.0.0/gems/flick-0.1.0/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/WebDriver

А вы можете описать сам процесс. Вот вы вызываете первую команду из терминала - что происходит? Есть ли какой-то output? Процесс вешает терминал до отравки stop сигнала из другого терминала, или отпускает терминал? Каким образом процесс понимает, что надо идти на iPad, а не писать видео на маке?

  1. Вызываем команду “flick video -a start -p ios”
    (flick video - запуск рекордера видео), (start - начать), (-p ios - указываем платформу)

  2. После запуска команды, на экране консоли появляется текст:
    Starting Recoder!!!
    Process will stop after 500 screenshots.

  3. Далее, снимается видео с экрана девайса

  4. Далее вводим в консоли (консоль можно закрыть, и открыть другое окно):
    flick video -a stop -p ios -o /Users/aap/Documents/lime-mobile-automation/target/video-rec -n bug
    (flick video - запуск рекордера видео), (stop - закончить), (-p ios - указываем платформу), (-o /Users/aap/Documents/lime-mobile-automation/target/video-rec - путь где сохранится файл), (bug - имя файла в формате .mp4)

  5. После ввода в консоль вышесказанной команды, в указанной папке появляется файл, а на консоли выводится следующая инфа:
    stopping Recorder!!!
    Saving to /Users/aap/Documents/lime-mobile-automation/target/video-rec/bug.mp4

Вы пробовали запускать flick из .sh скрипта? Результат такой же?
И вот еще что… /bin/sh может быть прилинкован совсем не с тем shell’ом. Проверьте, по какому пути запускается ваш sh терминал. Я вставлял команду из Linux, там все довольно прозрачно. Но на маке у вас может использоваться совсем другой shell: zsh, ksh, tcsh, bash, sh. Причем, вести они могут себя так же по-разному.

да, в терминале ./myScript.sh (скрипт flick) запускается и результат корректный.

путь до терминала:
/Applications/Utilities/Terminal.app
http://screencast.com/t/LdUhd0OzHc

ps: все тоже самое с /bin/bash аналогично не работает

Я имел ввиду программно.

Там же можно указать путь к любому другому bash.

Вооот, что и требовалось доказать. Вам вместо /bin/sh нужно указать валидный sh терминал. Никакой executor сам за вас этого не сделает. Попробуйте еще засетить /bin/bash в качестве основного shell, интереса ради. Заработает ли? Возможно, если терминал не выбран основным, система не подтягивает path к основным ресурсам, включая gems.

  • но если я в терминале ввожу /bin/sh, запускается sh-3.2
  • если ввожу /bin/bash, запускается bash-3.2
    значит они оба валидные?

поменять галочку как на приложенном скрине? сейчас попробую

Они все валидные. Просто у тех или иных shells могут быть различные возможности (иногда даже урезанные). Но проблема сейчас состоит в том, что неактивные терминалы не видят ruby, а следовательно не могут стартануть соответствующий gem.

Да, установите путь к другому shell и попробуйте выполнить нужную вам команду в терминале. Если не поможет, значит программно надо указывать путь к вашему основному shell.

не помогло.

Правда я все равно не понимаю, если я руками запускаю flick и в sh и в bash, то все ок. А из Eclipse никак.

Подскажите, правильно ли я добавил global path?

А как это сделать? И как найти путь к основному Shell?