在PostgreSQL上运行SQL脚本并提供密码

时间:2017-05-03 17:44:58

标签: java psql

我正在尝试从我的Java应用程序中运行SQL脚本。这是我的代码:

Runtime rt = Runtime.getRuntime();
rt.exec("setx PGPASSWORD \"" + password + "\"");
String command = String.format("psql -d %s -h %s -p %s -U %s -w -f %s",
        database, host, port, user, "create_tables.sql");
System.out.println("Executing command " + command);
Process p = rt.exec(String.format(command));
p.waitFor();

打印

psql -d routes -h localhost -p 5432 -U postgres -w -f create_tables.sql

正如所料。

但是在我的数据库日志中,我看到以下内容:

  

psql:fe_sendauth:没有提供密码

如何将psql作为进程调用时提供密码?

2 个答案:

答案 0 :(得分:0)

您的环境变量应在执行psql的过程中设置。执行两个不同的进程时,代码中不会发生这种情况。

问题是,环境变量是进程上下文的本地变量。

新进程获取父级环境的副本,但每个副本都是独立的。 在您的情况下,Java进程会创建修改PGPASSWORDsetx命令的子进程 - 到目前为止一直很好。

但是,这不会影响Java进程。您的第二个子进程未在shell中运行,因此它会忽略PGPASSWORD变量,因为该进程是使用OS服务创建的。除非在启动原始(父)Java进程之前更改shell中的环境,否则这些服务会考虑PGPASSWORD进程的旧上下文,该进程不知道Java

因此,要解决您的问题,您必须设置环境变量,然后将子项作为shell命令运行(cmd /c)。 要设置环境变量,我们可以遵循@Little Santi的建议。

所以代码看起来像下面的

Runtime rt = Runtime.getRuntime();
String setCommand="PGPASSWORD=" + password;

String command = String.format("psql -d %s -h %s -p %s -U %s -w -f %s", 
        database, host, port, user, "create_tables.sql");

String finalCommand = "cmd /c \" " + command +"\"";
System.out.println("Executing command " + finalCommand);

Process p = rt.exec(finalCommand ,new String[]{setCommand});
p.waitFor();

编辑2:

答案 1 :(得分:0)

@ Plirkee的诊断是正确的:您启动psql的过程错过了所需的环境变量。但要正确设置它,最好使用Runtime.exec(String[] cmdarray, String[] envp)方法。