Не удается отладить ProcessBuilder - PullRequest
0 голосов
/ 23 сентября 2019

Мне нужно передать различные команды sh с помощью «sudo» и «su» из моего java-приложения в linux с помощью java.lang.ProcessBuilder.

Эти команды очень похожи, но некоторые работают, некоторые не работают,Когда я копирую и вставляю команду из журналов, ALL команда работает.

После этого:

processBuilder = new ProcessBuilder("sudo", "su", "- USER66 -c", "'ssh remote.mycomp.org < " + workingDir + "/script_cluster.sh'");

У меня есть:

su : option invalide -- ' '
Usage: (...)

Но вот этот:

processBuilder = new ProcessBuilder("sudo", "su",  "- USER66 -c", "'scp remote.mycomp.org:" + clusterWorkingDir + "/" + filename + " " + workingDir + "/resultat/" + dir + "/'");

отлично работает.

И, как я уже говорил ранее, если я скопирую первую команду из моих журналов, она работает без предупреждения.

код регистрации:

  logCommand(processBuilder);

  private void logCommand(ProcessBuilder processBuilder) {
    if (logger.isDebugEnabled()) {
      logger.debug("Commande : {}", commandAsString(processBuilder.command()));
    }
  }

  private String commandAsString(List<String> command) {
    StringBuilder result = new StringBuilder();
    for (String cmdElement : command) {
      result.append(cmdElement).append(" ");
    }
    return result.toString();
  }

Что мне здесь не хватает?Что еще я могу сделать, чтобы понять, что происходит?

Ответы [ 2 ]

0 голосов
/ 24 сентября 2019

Хорошо, я нашел удивительный способ решения этой проблемы:

Хитрость заключалась не в том, чтобы разделить аргументы, а вместо этого перегруппировать их, используя "bash -c":

processBuilder = new ProcessBuilder("bash", "-c", "sudo su - USER66 -c 'ssh remote.mycomp.org < " + workingDir + "/script_cluster.sh'");

обратите внимание, насколько это не интуитивно понятно, потому что никто не напишет это так в оболочке, и это может быть довольно сложно перевести в команду оболочки с надлежащим вложенным экранированием.Кроме того, если вы объединяете 3 части команды с пробелами, она не образует допустимую команду.

0 голосов
/ 23 сентября 2019

Конструктор ProcessBuilder требует отдельной строки для каждого аргумента.В вашем коде несколько аргументов объединены в одну строку.Попробуйте это:

new ProcessBuilder( "sudo", "su", "-", "USER66", "-c", "'ssh remote.mycomp.org < /script_cluster.sh'");

(Правильно рассматривать значение флага -c как один аргумент.)

Объяснение

Большинство собственных системных методов для создания нового процесса требуют, чтобы каждый аргумент был отдельным элементом массива (например, посмотрите документацию execve ).

Во время выполнения Java будетзакодируйте аргументы в один байтовый массив, прежде чем передавать его в собственный метод JVM, который вызовет собственный системный метод.Например, "su", "-", "USER66", "-c", "'...'" будет декодироваться как su-USER66-c'...'.Отдельные аргументы разделяются байтом 0 (который мы не видим в строке).Собственный метод JVM декодирует строку продолжения, разделяя строку разделителем байтов 0.Если мы "su - USER66" будем использовать в качестве одного аргумента, он будет неправильно закодирован как один аргумент для системного метода.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...