对于Elasticsearch查询,使用Java代码中的不同引号执行Bash one liner
我试图在我的java代码中执行一个弹性搜索帖子查询。我希望使用bashshell在我的机器上执行代码 这是我的密码:对于Elasticsearch查询,使用Java代码中的不同引号执行Bash one liner,java,bash,unix,elasticsearch,Java,Bash,Unix,elasticsearch,我试图在我的java代码中执行一个弹性搜索帖子查询。我希望使用bashshell在我的机器上执行代码 这是我的密码: 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\"
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);
}
}
我试着用两种不同的方式来解释它,正如你从注释掉的代码中看到的那样
我打印我构造的查询以验证它。当我在本地机器上执行此程序并在终端中尝试打印的查询时,它可以工作,但在java代码/bash查询中不起作用。我想这与格式和单引号的使用有关,但我还不能直接从代码中运行它。仅使用
Runtime.exec来正确地分离参数和引用可能很棘手
如果需要传递json之类的复杂参数,我建议您看看更健壮的脚本。您可以尝试在单独的文件中编写脚本,然后使用
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();
最佳方法
请参阅其他答案,以获得关于更好方法的建议
如何修复此方法
这是您当前方法的正确(且棘手)报价:
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+"'");
在单引号内传递给shell的字符串中,通过结束当前单引号(”
),开始双引号(“
),添加转义单引号(”
),关闭双引号(”
)并继续单引号字符串(”
)来转义其他单引号
总之,我们把它写成“\'”
,上下文是bli'“'single-quote-inside-json'”“'bla
,变成/bin/bash-c'bli'”“'single-quote-inside-json'”“'bla'
为什么这么复杂?
必要的原因可以在bash(1)手册页面中找到:
单引号不能出现在单引号之间,即使前面有反斜杠
这就是为什么我们必须结束单引号,开始双引号(可以转义单引号),结束双引号,然后再次继续单引号。等待子进程也是个好主意。然后检查@CobraKai,很高兴我能帮忙。既然你的问题已经解决了,请将答案标记为已接受。这将使帖子看起来像得到了回答,并可能帮助其他有类似问题的人。强烈建议使用Java或其他Java HTTP库,而不是在IPC上运行CURL。通过从代码中执行三维第三方进程,您正在降低Java程序的可移植性。运行CURL时,至少您需要修改UNIX(Linux、FreeBSD、MacOS X)和Windows的代码。我编辑了您的标题,以便有类似问题的人可以更好地找到您的问题。谢谢dude。使用以前建议的方法之一修复此问题。