[英]How can I execute multiple commands and psql queries in one command for Windows in Java?
我正在用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對抗是一個更好的解決方案(它的代碼少得多,問題少得多,而且控制起來也更容易)。
您想要的是不可能的; 顯然,您想要“一個命令”的原因是您希望此操作是瞬時的; 在強制殺死所有打開的PSQL連接和運行dropdb之間沒有時間。 那不是它的工作原理,shell只是一個接一個地執行這些命令。
所以..做同樣的事情:首先運行一個命令(使正在運行的進程構建器並運行該命令;然后既不需要cmd.exe / c,也可以運行),然后等待該命令完成,然后制作另一個processbuilder並運行dropdb命令。
另外,對於第一個命令,您實際上根本不需要processbuilder。 您也可以使用JDBC發送該查詢。 您還可以使用JDBC發送DROP DATABASE查詢,這是dropdb命令在后台執行的操作。 然后,就不再需要processbuilder。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.