【问题标题】:Create backup of postgresql via ProcessBuilder通过 ProcessBuilder 创建 postgresql 的备份
【发布时间】:2016-05-11 14:05:04
【问题描述】:

我想在 java 中使用 pg_dump 创建我的数据库的备份。备份的创建工作正常,但在程序退出之前不会启动。

有什么方法可以立即开始备份?

public static void backupDb() throws IOException, InterruptedException {
  String path = "C:\\HACENE\\test.backup";
  Runtime r = Runtime.getRuntime();
  //PostgreSQL variables    
  String host = "localhost";
  String user = "postgres";
  String dbase = "gtr_bd";
  String password = "postgres";
  Process p;
  ProcessBuilder pb;

  r = Runtime.getRuntime();
  pb = new ProcessBuilder("C:\\Program Files\\PostgreSQL\\9.3\\bin\\pg_dump", "-v", "-h", host, "-f", path, "-U", user, dbase);
  pb.environment().put("PGPASSWORD", password);
  pb.redirectErrorStream(true);
  p = pb.start();
  System.out.println("end of backup");
}

【问题讨论】:

  • p.waitFor() 也许?
  • 行为取决于操作系统环境。流程执行不是由 java 本身完成的。因此,由操作系统实际执行您定义并移交执行的进程。另外 pprogramme 退出前还有多长时间(毫秒、秒、小时)?
  • 进程由操作系统处理,所以从逻辑上讲它应该在我从应用程序启动时启动,但进程在我退出程序时启动

标签: java postgresql processbuilder


【解决方案1】:

您应该检查从ProcessBuilder.start() 返回的Process 实例的状态。正如 cmets 中已经提到的,您可以使用 Process.waitFor() 方法等待该过程完成。此外,您应该考虑检查已启动进程的退出值以确定您的备份是否成功。

这是我在我的一个项目中所做的:

private void validateExitValue(final Process aProcess, final String aCommand,
    final String aResult) throws IllegalStateException {
    do {
        try {
            if (aProcess.waitFor() != 0) {
                final String errorMessage = String.format("Command '%s' terminated with exit status '%s': %s",
                    aCommand, aProcess.exitValue(), aResult);
                throw new IllegalStateException(errorMessage);
            }
            break;
        } catch (final InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    } while (true);
}

如果进程以0 以外的退出代码结束,此方法将等待进程完成并抛出IllegalStateException

当前备份进程在您的 Java 程序终止时启动的观察结果是我怀疑的巧合,因为启动备份进程很可能是您的 Java 程序执行的最后一个操作。启动外部进程需要一些时间,并且您的程序会继续并终止,也就是说,看起来该进程是在 Java 程序终止时启动的。

【讨论】:

    【解决方案2】:
    // Comment -> p = pb.start();
    // add this at the end:
    
    final Process process = pb.start();  
    InputStream is = process.getInputStream();  
    InputStreamReader isr = new InputStreamReader(is);
    BufferedReader br = new BufferedReader(isr);
    String line;
    while ((line = br.readLine()) != null) {
      System.out.println(line);
    }
    // because you put "-v" in your command. Another way is to remove "-v" from your command
    

    -v 指定详细模式。这将导致 pg_dump 将详细的对象 cmets 和开始/停止时间输出到转储文件,并将进度消息输出到标准错误。从这个LINK

    【讨论】:

      【解决方案3】:

      如果您在 cmd 中执行此命令,则可以正常工作:

      "C:\Program Files\PostgreSQL\9.3\bin\pg_dump.exe" -U postgres -h localhost -p 5432 database_name > "C:\Test\test.buckup"
      

      因此,您可以将这些行放在 .bat 文件中,如下所示:

      @echo off
      cd "C:\Program Files\PostgreSQL\9.3\bin\" 
      pg_dump.exe -U postgres -h localhost -p 5432 bd_suivi > "C:\Test\test.buckup"
      exit
      

      然后用java执行这个file.bat,像这样:

      public static void main(String[] args) {
          try {
              ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", "start script.bat");
              builder.redirectErrorStream(true);
              Process p = builder.start();
              BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
              String line;
              while (true) {
                  line = r.readLine();
                  if (line == null) {
                      break;
                  }
                  System.out.println(line);
              }
              System.out.println("I finished the creation of the buckup!");
          } catch (Exception e) {
              System.out.println("Exception = " + e);
          }
      }
      

      祝你好运。

      【讨论】:

        猜你喜欢
        • 2020-10-15
        • 1970-01-01
        • 2019-03-21
        • 1970-01-01
        • 2013-01-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-10
        相关资源
        最近更新 更多