我正在尝试从我的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
作为进程调用时提供密码?
答案 0 :(得分:0)
您的环境变量应在执行psql
的过程中设置。执行两个不同的进程时,代码中不会发生这种情况。
问题是,环境变量是进程上下文的本地变量。
新进程获取父级环境的副本,但每个副本都是独立的。
在您的情况下,Java
进程会创建修改PGPASSWORD
到setx
命令的子进程 - 到目前为止一直很好。
但是,这不会影响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)方法。