Java Runtime.exec 无法执行 psql 命令

问题描述 投票:0回答:1

我想做的是将数据库表数据的子集从 X 环境复制到本地文件存储。 我尝试使用 Java 运行时执行 psql 命令,但失败了

this.psqlExportDataFile = "psql postgresql://dburl -o /Users/Shared/CopyDB/project.csv -c \"COPY (SELECT * FROM gls.project where id in (112371,148904,1652068)) TO STDOUT(FORMAT csv, DELIMITER ',', NULL 'null')'\"";

Process process = runtime.exec(psqlExportDataFile);
System.out.println(new String(toByteArray(process.getErrorStream())));

但是当我在 shell 中运行它时它通常可以工作。

错误输出为:

ERROR:  unterminated quoted identifier at or near ""COPY"
LINE 1: "COPY
        ^

可能是什么问题?

java shell psql
1个回答
0
投票

您错误地认为“在命令行上键入”(

cmd.exe
,或
/bin/bash
,或任何您的终端)与“启动进程”相同。不是这样的。

你的 shell 可以做很多事情。它采用您输入的字符串并以多种方式处理它。当然,它会导致运行一个命令(在这里,启动

psql.exe
/bin/psql
或诸如此类的东西,并将某些参数传递给该进程)。但这是
bash
/
cmd.exe
例如应用引号、空间分割以及所有爵士乐。

Java 的进程构建器不是

cmd.exe
,也不是
/bin/bash
。除了空间分割之外,它几乎没有任何作用。你想控制它,所以停止使用
Runtime.exec()
并使用
ProcessBuilder
来代替,整个“围绕参数的引用”并不是 ProcessBuilder 的工作方式。 bash/cmd 决定:要传递超过 1 个参数,请在它们之间放置空格,然后解决“如果我想传递一个本身包含空格的单个参数怎么办”的困境:“啊,好吧,那么,嗯,用引号引起来吗?”。

Java 的 processbuilder 选择了一个不同的、更简单的解决方案:将每个参数传递为.. 1 个参数:

new ProcessBuilder(
  "/bin/psql",
  "postgresql://dburl",
  "-o",
  "/Users/Shared/CopyDB/project.csv",
  "-c",
  "COPY (SELECT * FROM gls.project where id in (112371,148904,1652068)) TO STDOUT(FORMAT csv, DELIMITER ',', NULL 'null');");

然后运行/

© www.soinside.com 2019 - 2024. All rights reserved.