我需要创建一个接收方法(databaseIp,databaseName,端口,用户,密码,filePath)。这个想法是在终端这样的数据库中导入一个sql文件:

psql -h databaseIp -p port -U user -d databaseName
Password for user postgres: password
databaseName=# \\i filePath
databaseName=# \\q


我使用以下方法将命令发送到终端

public static String execute(String command) {
    StringBuilder sb = new StringBuilder();
    String[] commands = new String[]{"/bin/sh", "-c", command};
    try {
        Process proc = new ProcessBuilder(commands).start();
        BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));

        BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));

        String s = null;
        while ((s = stdInput.readLine()) != null) {
            sb.append(s);
            sb.append("\n");
        }

        while ((s = stdError.readLine()) != null) {
            sb.append(s);
            sb.append("\n");
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return sb.toString();
}


但是它看到它一次只发送一个命令,并且当psql要求输入密码时,给出的结果不正确。如何使用Java将相关命令发送到终端?

最佳答案

gh,你为什么要这么做?

使用PgJDBC从Java与PostgreSQL通信。

如果确实必须调用psql,请说是否要采购使用\命令的SQL文件,build a command with ProcessBuilder并以批处理方式非交互地调用psql。您可以提示用户输入密码,然后将其传递给psql环境变量中的PGPASSWORD,因此您无需与进程进行交互,只需启动它并等待其终止即可。

像(未经测试的)之类的东西:

 cmd = new List<String>();
 cmd.add(path_to_psql);
 cmd.add("-q"); // Quiet mode
 cmd.add("-w"); // no password prompt
 cmd.add("-X"); // ignore any user psqlrc
 cmd.add("-1"); // Run in a single transaction
 cmd.add("-v"); // Set a variable as follows:
 cmd.add("ON_ERROR_STOP=1"); // If anything goes wrong, abort the whole job
 cmd.add("-f"); // input file is:
 cmd.add(input_file_path);
 if (username_arg != null) {
    cmd.add("-U");
    cmd.add(username_arg);
 }
 // and so on for database name, etc, then:

 ProcessBuilder pb = new ProcessBuilder(cmd);
 Map<String, String> env = pb.environment();
 if (psql_password != null) {
     // User supplied a password
     env.put("PGPASSWORD", psql_password);
 }
 // ... blah blah, the usual execute it, wait for it to finish,
 // check return value, etc.


如果psql首次连接失败,错误代码为2,则可以提示用户输入密码并重试。不幸的是,错误代码2不是很具体。它还将返回与无效主机名等相关的错误,因此,您可能希望捕获psql的stderr并将其与提示一起显示给用户。

10-08 07:33
查看更多