0

我需要创建一个接收(databaseIp、databaseName、port、user、password、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 向终端发送相关命令?

4

1 回答 1

1

呃,你为什么要这样做?

使用PgJDBC从 Java 与 PostgreSQL 通信。

如果你真的必须调用psql,假设你正在采购一个使用\命令的 SQL 文件,构建一个命令ProcessBuilderpsql并在批处理模式下以非交互方式调用。您可以提示用户输入密码,然后将其传递给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 并将其与提示一起显示给用户。

于 2013-08-12T12:21:10.403 回答