Выполнить однострочную версию Bash с разными кавычками из кода Java для запроса Elasticsearch - PullRequest
2 голосов
/ 13 мая 2019

Я пытаюсь выполнить поисковый запрос Elastic внутри моего кода Java.я хочу, чтобы код выполнялся на моей машине с использованием оболочки bash.

Вот мой код:

public class Elastic {
public static void main(String[] args) {

String cmd = "curl -X PUT IP:PORT/twitter/_doc/10 -H 'Content-Type: application/json' -d '{ \"user\" : \"Bob\", \"post_date\" : \"2019-12-15T14:12:10\", \"message\" : \"trying out Elasticsearch\" }' ";


   try {
Process pr = Runtime.getRuntime().exec(cmd);
  } catch (Exception e) {
    e.printStackTrace();
   }

/*
   try {
    Runtime.getRuntime().exec("/bin/bash "+"-c "+"\'"+cmd+"\'");
  } catch (Exception e) {
    e.printStackTrace();
   }   */
System.out.println("===============");
System.out.println(cmd);
 }
 }

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

Iнапечатайте запрос, который я построил, чтобы проверить это.Когда я выполняю эту программу на своем локальном компьютере и пробую печатный запрос в терминале, он работает, но не в моем запросе java code / bash.Я думаю, это как-то связано с форматированием и использованием одинарных кавычек, но я пока не смог запустить его непосредственно из своего кода.

Ответы [ 3 ]

2 голосов
/ 13 мая 2019

Вы можете попробовать написать скрипт в отдельном файле и затем использовать

String[] cmdScript = new String[]{"/bin/bash", "path/to/myScript.sh"}; 
Process procScript = Runtime.getRuntime().exec(cmdScript);

Если вы также хотите добавить параметры, вы можете использовать что-то вроде

Process procBuildScript = new ProcessBuilder("path/to/myScript.sh", "myArg1 myArg2").start();
1 голос
/ 13 мая 2019

Наилучший подход

Пожалуйста, смотрите другие ответы для предложений по совершенно лучшему подходу.

Как исправить этот подход

Это правильное (и хитрое) цитирование для вашего текущего подхода:

String cmd = "curl -X PUT IP:PORT/twitter/_doc/10 -H '"\'"'Content-Type: application/json'"\'"' -d '"\'"'{ \"user\" : \"Bob\", \"post_date\" : \"2019-12-15T14:12:10\", \"message\" : \"trying out Elasticsearch\" }'"\'"' ";

[...]

Runtime.getRuntime().exec("/bin/bash "+"-c "+"'"+cmd+"'");

Внутри строки, передаваемой в оболочку внутри одинарных кавычек, вы избегаете других одинарных кавычек, заканчивая текущую одинарную кавычку ('), начиная двойную кавычку ("), добавляя экранированную одинарную кавычку (\'), закрывая двойную кавычку (") и продолжая строку в одинарных кавычках (').

Вместе мы записываем это как '"\'"', с контекстом это bli '"\'"'single-quote-inside-json'"\'"' bla, которое становится /bin/bash -c 'bli '"\'"'single-quote-inside-json'"\'"' bla'.

Почему так сложно?

Причину, по которой это необходимо, можно найти на странице справки bash (1):

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

Вот почему мы должны заканчивать одинарную кавычку, начинать двойную кавычку (гдеможно убрать кавычку), завершить двойную кавычку и продолжить нашу одинарную кавычку.

0 голосов
/ 13 мая 2019

Разделение аргументов и правильное цитирование могут быть сложными, чтобы получить правильные значения, используя только Runtime.exec.

Я бы порекомендовал вам взглянуть на более надежный ProcessBuilder API , если вам нужно передать сложные аргументы, такие как json.

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