Что такое конечный датчик?

Почему некоторые команды терпят неудачу?

Это происходит потому, что команда, переданная в Runtime.exec(String), не выполняется в оболочке. Оболочка выполняет множество общих служб поддержки для программ, и когда оболочка не собирается их выполнять, команда будет терпеть неудачу.

Когда команды не работают?

Команда будет если это зависит от свойств оболочки. Оболочка имеет много общих и полезных вещей, о которых мы обычно не думаем:

  1. Оболочка правильно раскладывается на кавычки и пробелы. Это удостоверяет, что имя файла в "My File.txt" остается единственным аргументом. Runtime.exec(String) наивно разбивается на пробелы и передает это как два отдельных имени файла. Это явно не получается.
  2. Оболочка расширяет globs / wildcards. Когда вы запускаете ls *.doc, оболочка перезаписывает ее в ls letter.doc notes.doc. Runtime.exec(String) нет, он просто передает их в качестве аргументов. ls не знает, что *, поэтому команда не работает.
  3. Среда управляет трубами и перенаправлением. Когда вы запускаете ls mydir > output.txt, оболочка открывает «output.txt» для вывода команды и удаляет ее из командной строки, предоставляя ls mydir. Runtime.exec(String) нет. Он просто передает их в качестве аргументов. ls не знает, что означает >, поэтому команда не работает.
  4. Оболочка расширяет переменные и команды. Когда вы запускаете ls "$HOME" или ls "$(pwd)", оболочка перезаписывает его на ls /home/myuser. Runtime.exec(String) нет, он просто передает их в качестве аргументов. ls не знает, что означает $, поэтому команда не работает.

Что вы можете сделать вместо этого?

Существует два способа выполнения произвольно сложных команд :

Простая и неаккуратная: делегировать оболочку.

Вы можете просто использовать Runtime.exec(String[]) (обратите внимание на параметр массива) и передать команду непосредственно оболочке, которая может выполнять весь тяжелый подъем:

// Simple, sloppy fix. May have security and robustness implications
String myFile = "some filename.txt";
String myCommand = "cp -R '" + myFile + "' $HOME 2> errorlog";
Runtime.getRuntime().exec(new String[] { "bash", "-c", myCommand });

Безопасный и надежный: возьмите на себя ответственность оболочки.

Это не исправление, которое можно механически применить, но требует понимания модели исполнения Unix, каких оболочек и как вы можете сделать то же самое. Тем не менее, вы можете получить надежное, надежное и надежное решение, сняв оболочку с рисунка. Этому способствует ProcessBuilder.

Команда из предыдущего примера, которая требует, чтобы кто-то обрабатывал 1. кавычки, 2. переменные и 3. перенаправления, может быть записан как:

String myFile = "some filename.txt";
ProcessBuilder builder = new ProcessBuilder(
    "cp", "-R", myFile,        // We handle word splitting
       System.getenv("HOME")); // We handle variables
builder.redirectError(         // We set up redirections
    ProcessBuilder.Redirect.to(new File("errorlog")));
builder.start();
30
задан Whymarrh 28 October 2016 в 12:40
поделиться