java - 如何在 Java 中在一个命令中为 Windows 执行多个命令和 psql 查询?
问题描述
我正在用 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 子句已经删除了您的“自己的”会话。
然后,您只需要运行psql
一次(而不是其他命令行工具)传递该脚本,方法是将上述内容写入临时文件并使用-f
参数,或者将所有内容作为单个命令传递使用-c
psql -c "alter database your_db_name allow_connections false; select ... where ...; drop database your_db_name"
然而,我认为通过 JDBC 来做这件事Statement.execute()
是一个更好的解决方案,它试图与 ProcessBuilder 抗争(它的代码少得多,问题少得多,而且更容易控制)。
推荐阅读
- spring-security - 使用 OKTA 的 WSO2 最终用户身份验证
- swiftui - 在 SwiftUI 中切换 UINavigationBar 外观
- java - 计算不同的有效对
- python - 不使用数据类调用超类的 __init__
- nginx - 如何仅使用反向代理实现 nginx geoip 模块
- javascript - Joi 验证可以包含数字 0-9 但不能仅包含数字的字符串?
- sql - Sql - 将重复行值拆分为新列
- jquery - 使用 Api 数据获取的 Jquery 自动完成
- postgresql - 我应该使用哪个版本来连接postgresql9.4.24
- python - 在这种情况下,我将如何实现 try 或 except 方法?