我正在用 Java 编写一些代码来自动从云端恢复备份。为此,我需要在 Windows 的 (CMD) 命令行工具中用一个命令打开 psql、终止连接、退出 psql 和删除数据库,以便 Java 可以一次性执行。这些分别是单独的步骤(我认为);
psql -h localhost -p 5433 -U postgres -w OC_A -c '
SELECT
pg_terminate_backend(pid)
FROM
pg_stat_activity
WHERE
pid <> pg_backend_pid();
/q postgres-# \q ;'
dropdb -h localhost -p 5433 -U postgres -w OC_A
我已将这些步骤放入一个单独的 cmd 命令中;
// 2 - terminate db connections, delete based on config db's
String terminateSQLconnecitons= "\npsql -h "+ postgresHost + " -p " + postgresPort + " -U " + postgresUsername + " -w " + postgresDbname + " -c "+
"\'\nSELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE pid <> pg_backend_pid();\n/q postgres-# \\q ;'" ;
int terminateSQLconnecitonsResult = cmdExe(terminateSQLconnecitons);
if (terminateSQLconnecitonsResult == 0) {
System.out.println("Connections terminated");
} else {
System.out.println("CONNECTIONS NOT TERMINATED");
}
public static int cmdExe(String cmd) {
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.redirectErrorStream(true);
processBuilder.command("cmd.exe", "/c", cmd);
System.out.println(cmd);
int exitCode = -1;
try {
Process process = processBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
exitCode = process.waitFor();
System.out.println("Result :" + exitCode);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return exitCode;
}
要在 Java 的一个命令中执行这些步骤,我需要在哪里/更改什么?
编辑 1;我现在已经有了单独的步骤,但似乎没有用。我不明白为什么。
// 2 - terminate db connections, delete based on config db's
String terminateSQLconnecitons= "\npsql -h "+ postgresHost + " -p " + postgresPort + " -U " + postgresUsername + " -w " + postgresDbname + " -c "+
"\'\nSELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE pid <> pg_backend_pid();\n/q postgres-# \\q ;'" ;
int terminateSQLconnecitonsResult = cmdExe(terminateSQLconnecitons);
if (terminateSQLconnecitonsResult == 0) {
System.out.println("Connections terminated");
} else {
System.out.println("CONNECTIONS NOT TERMINATED");
}
String DeleteCMD= "\ndropdb -h "+ postgresHost + " -p " + postgresPort + " -U " + postgresUsername + " -w " + postgresDbname;
int cmdResult = cmdExe(DeleteCMD);
if (cmdResult == 0) {
System.out.println("Database " + postgresDbname + " deleted");
} else {
System.out.println("Database " + postgresDbname + " NOT deleted");
}
最佳答案
通过将所有内容放入单个 SQL 脚本中,您可以大大简化这一切。要运行脚本,请连接到一个不同的数据库,例如template1
.
-- prevent new connections between the moment you killed everything
-- and the moment where the database is dropped
alter database your_db_name allow_connections false;
select pg_terminate_backend(pid)
from pg_stat_activity
where datname = 'your_db_name'
and pid <> pg_backend_pid();
drop database your_db_name;
and pid <> ...
并不是真的需要,因为该脚本没有连接到要删除的数据库,因此目标数据库上的 where 子句已经删除了您的“自己的” session 。
然后你只需要运行psql
一次(没有其他命令行工具)传递该脚本,方法是将上述内容写入临时文件并使用 -f
参数或使用 -c
将所有内容作为单个命令传递
psql -c "alter database your_db_name allow_connections false; select ... where ...; drop database your_db_name"
但是我认为通过 JDBC 使用 Statement.execute()
来做到这一点是一个好得多的解决方案,试图对抗 ProcessBuilder(它的代码少得多,问题少得多,而且更容易控制)。
关于java - 如何在 Java 的 Windows 的一个命令中执行多个命令和 psql 查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57393569/