Ola Pessoal
Já procurei aqui no fórum em vários tópicos e ninguém tem a solução ideal.
Estou tentando escrever um método Java que faça o Dump de um banco de dados em PostgreSQL no Windows, da seguinte forma:
private boolean efetuarBackupPostgres() {
String arquivoDump = "C:\\Program Files (x86)\\pgAdmin III\\1.12\\pg_dump.exe";
String arquivoBkp = new File("dados/database" + Util.dateDataToString(new Date(), "-yyyy-MM-dd-HH-mm-ss") + ".backup").getAbsolutePath();
String comando = "\"" + arquivoDump + "\" -h " + PersistenciaServices.host + " -p " + PersistenciaServices.porta + " -U " + PersistenciaServices.usuario + " -F plain -v -f \"" + arquivoBkp + "\" banco";
try {
Runtime.getRuntime().exec(comando); // ele passa por arqui, mas não termina o processo
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
O método funciona, ele não gera erro nem exceções.
Se eu entrar na pasta DADOS onde estou gravando o arquivo de “.backup” está lá criado o arquivo com 0 kbytes, porém quando eu fecho minha aplicação JAVA ele “destrava” o processo de DUMP e preenchedo o arquivo de “.backup” com as informações.
Resumindo, ele só faz o comando que passei no método “.exec()” depois que fecho a minha aplicação.
Alguém sabe como posso solucionar?
att
Douglas Junior
Vc está matando o processo depois amigo?
Tive um erro parecido com minha aplicação, só que não usava esse código que vc está usando, tenho outro que fiz aqui para backup e envio por e-mail para os administradores do sistema.
Abraços
[quote=andre_bento]Vc está matando o processo depois amigo?
Tive um erro parecido com minha aplicação, só que não usava esse código que vc está usando, tenho outro que fiz aqui para backup e envio por e-mail para os administradores do sistema.
Abraços[/quote]
Não estou matando o processo não, o código de Bakcup que fiz é exatamente este acima, como seria forma que você fez?
att
Douglas Junior
Dica para todo mundo que quer usar Runtime.exec: evite, dentro da medida do possível, usar a versão do exec que recebe apenas uma string. É que quando você faz isso, você deixa a cargo do sistema operacional separar o comando em parâmetros.
O problema é que ele nem sempre separa do jeito que você quer.
No seu caso, ele separou nos seguintes parâmetros, por causa dos espaços no nome do arquivo executável:
C:\Program
Files
(x86)\pgAdmin
III\1.12\pg_dump.exe
“nome do arquivo de dump”
-h
host
e assim por diante. Ou seja, ele bagunçou o nome do executável por causa do espaço, e pode ter feito mais besteiras depois - não analisei o resto para ver se está faltando algum par de aspas, ou coisa parecida.
Como você já viu que ele fez besteira na hora de achar o nome do executável, você tem uma de duas opções:
- Ou põe um monte de aspas nos lugares certos, o que é um porre e nem sempre dá certo,
- Ou você separa manualmente os parâmetros, o que funciona bem melhor. No seu caso, algo parecido com:
... = Runtime.getRuntime().exec(new String[]{
"C:\\Program Files (x86)\\pgAdmin III\\1.12\\pg_dump.exe",
"nome do arquivo de dump",
"-h",
"host",
...
});
[quote=entanglement]Dica para todo mundo que quer usar Runtime.exec: evite, dentro da medida do possível, usar a versão do exec que recebe apenas uma string. É que quando você faz isso, você deixa a cargo do sistema operacional separar o comando em parâmetros.
O problema é que ele nem sempre separa do jeito que você quer.
No seu caso, ele separou nos seguintes parâmetros, por causa dos espaços no nome do arquivo executável:
C:\Program
Files
(x86)\pgAdmin
III\1.12\pg_dump.exe
“nome do arquivo de dump”
-h
host
e assim por diante. Ou seja, ele bagunçou o nome do executável por causa do espaço, e pode ter feito mais besteiras depois - não analisei o resto para ver se está faltando algum par de aspas, ou coisa parecida.
Como você já viu que ele fez besteira na hora de achar o nome do executável, você tem uma de duas opções:
- Ou põe um monte de aspas nos lugares certos, o que é um porre e nem sempre dá certo,
- Ou você separa manualmente os parâmetros, o que funciona bem melhor. No seu caso, algo parecido com:
... = Runtime.getRuntime().exec(new String[]{
"C:\\Program Files (x86)\\pgAdmin III\\1.12\\pg_dump.exe",
"nome do arquivo de dump",
"-h",
"host",
...
});
[/quote]
Não é este o problema, veja na linha onde declaro a variável "String comando = ", eu envolvo o diretório do executável com aspas por existir espaços ao longo do diretório.
Conforme ei citei acima, o comando funciona “normalmente”, porém ele só é executado totalmente quando finalizo a aplicação, ou seja, quando rodo o “.exec()” ele executa parcialmente e só conclui o processo quando eu fecho o sistema.
att
Douglas
Olá amigo.
Vou postar o código para vc amanhã pois agora não estou no meu pc… o código funciona perfeitamente… vou passar ele inteiro pra vc ae vc adápta de acordo com a sua necessidade.
Abraços
[quote=andre_bento]Olá amigo.
Vou postar o código para vc amanhã pois agora não estou no meu pc… o código funciona perfeitamente… vou passar ele inteiro pra vc ae vc adápta de acordo com a sua necessidade.
Abraços[/quote]
Opa, muito obrigado, fico no aguardo.
Abraço
Douglas Junior
Olá amigo.
Peço desculpas pela demora na resposta.
Mas ae vai o código, é só adaptar para a sua necessidade.
Abraços e espero que te ajude.
[code]
/*
- To change this template, choose Tools | Templates
- and open the template in the editor.
*/
package Util;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import javax.swing.JOptionPane;
/**
*
-
@author Andre
*/
public class BDBackup {
private static String directoryName = new String();
private static File dirDestino = new File(“C:\IBV System\backups”);
private static String caminhoNovaPasta;
public static void backingUp() throws IOException, InterruptedException{
if(dateCalculation()){
final List<String> comandos = new ArrayList<String>();
comandos.add("C:\\Program Files\\PostgresPlus\\8.4SS\\bin\\pg_dump.exe");
comandos.add("-i");
comandos.add("-h");
comandos.add("localhost");
comandos.add("-p");
comandos.add("5432");
comandos.add("-U");
comandos.add("postgres");
comandos.add("-F");
comandos.add("c");
comandos.add("-b");
comandos.add("-v");
comandos.add("-f");
makeDirectory();
settingBackupDate();
dateCalculation();
String way = dirDestino+"\\"+directoryName;
comandos.add(way+"\\"+"church-bkp");
comandos.add("church");
ProcessBuilder pb = new ProcessBuilder(comandos);
pb.environment().put("PGPASSWORD", "post");
try {
final Process process = pb.start();
final BufferedReader r = new BufferedReader(
new InputStreamReader(process.getErrorStream()));
String line = r.readLine();
while (line != null) {
System.err.println(line);
line = r.readLine();
}
r.close();
process.waitFor();
System.out.println("backup realizado com sucesso.");
process.destroy();
} catch (IOException e) {
JOptionPane.showMessageDialog(null,"ERRO durante o backup:"+e);e.printStackTrace();
} catch (InterruptedException ie) {
JOptionPane.showMessageDialog(null,"ERRO durante o backup:"+ie); ie.printStackTrace();
}
}
}
public static void backingUpWithoutDateCalculation() throws IOException, InterruptedException{
final List<String> comandos = new ArrayList<String>();
comandos.add("C:\\Program Files\\PostgresPlus\\8.4SS\\bin\\pg_dump.exe");
comandos.add("-i");
comandos.add("-h");
comandos.add("localhost");
comandos.add("-p");
comandos.add("5432");
comandos.add("-U");
comandos.add("postgres");
comandos.add("-F");
comandos.add("c");
comandos.add("-b");
comandos.add("-v");
comandos.add("-f");
makeDirectory();
settingBackupDate();
dateCalculation();
String way = dirDestino+"\\"+directoryName;
caminhoNovaPasta = way;
comandos.add(way+"\\"+"church-bkp");
comandos.add("church");
ProcessBuilder pb = new ProcessBuilder(comandos);
pb.environment().put("PGPASSWORD", "post");
try {
final Process process = pb.start();
final BufferedReader r = new BufferedReader(
new InputStreamReader(process.getErrorStream()));
String line = r.readLine();
while (line != null) {
System.err.println(line);
line = r.readLine();
}
r.close();
process.waitFor();
System.out.println("backup realizado com sucesso.");
process.destroy();
} catch (IOException e) {
JOptionPane.showMessageDialog(null,"ERRO durante o backup:"+e);e.printStackTrace();
} catch (InterruptedException ie) {
JOptionPane.showMessageDialog(null,"ERRO durante o backup:"+ie); ie.printStackTrace();
}
}
public static void makeDirectory(){
if(!dirDestino.exists()){
dirDestino.mkdirs();
Date data = new Date();
String simpleDate = new SimpleDateFormat("dd/MM/yyyy").format(data);
String [] temp = simpleDate.split("/");
/**Abaixo, estou verificando se é a última parte da data(no caso o ano)
* que ele está pegando, se for, eu mando ele não adicionar o traço no
* final para ficar visivelmente melhor
*/
for(int i=0;i<temp.length;i++){
if(temp.length-i==1){
directoryName += temp[i];
}else{
directoryName += temp[i]+"-";}
}
File newDir = new File(dirDestino,directoryName);
newDir.mkdirs();
}
else
{
Date data = new Date();
String simpleDate = new SimpleDateFormat("dd/MM/yyyy").format(data);
String [] temp = simpleDate.split("/");
//String directoryName = new String();
/**Abaixo, estou verificando se é a última parte da data(no caso o ano)
* que ele está pegando, se for, eu mando ele não adicionar o traço no
* final para ficar visivelmente melhor
*/
for(int i=0;i<temp.length;i++){
if(temp.length-i==1){
directoryName += temp[i];
}else{
directoryName += temp[i]+"-";}
}
String [] allDirectoryNames = dirDestino.list();
String [] listDirectoryNames = new String[allDirectoryNames.length];
for (int i=0;i<allDirectoryNames.length;i++){
String nameTemp = allDirectoryNames[i];
String [] nameTemp2 = nameTemp.split("-");
/**O for roda apenas uma vez para poder pegar o conteúdo até o ano
* no caso 20-12-2011... ele varre até a terceira posição
* e joga o conteúdo no listDirectoryNames
*/
for(int p=0;p<1;p++){
listDirectoryNames[i] = nameTemp2[p]+"-";
listDirectoryNames[i] += nameTemp2[p+1]+"-";
listDirectoryNames[i] += nameTemp2[p+2];
}
}
int repeatNamesCont=0;
String nameTemp = "" ;
//preciso passar como parâmetro também ao invés de allDirecotryNames
//o valor antes do - número de repetições...
for(int i=0;i<allDirectoryNames.length;i++){
if(directoryName.equals(listDirectoryNames[i])){
repeatNamesCont += 1;
nameTemp =directoryName+"-"+repeatNamesCont;
// directoryName += "-"+repeatNamesCont;
}
}
/**
*/
if(!"".equals(nameTemp)){
directoryName =nameTemp;
}
File newDir = new File(dirDestino,directoryName);
newDir.mkdirs();
}
}
public static void settingBackupDate() throws IOException{
File dirDestinoBackup = new File("C:\\IBV System");
String way = dirDestinoBackup.getAbsolutePath();
File backupDirectory = new File(way+"\\Backup Date");
Date data = new Date();
String simpleDate = new SimpleDateFormat("dd/MM/yyyy").format(data);
if(!backupDirectory.exists()){
backupDirectory.mkdirs();
FileWriter backupFile = new FileWriter(backupDirectory+"\\"+"LastBackup.txt");
PrintWriter pw = new PrintWriter(backupFile,true);
pw.println("This is the last time that the IBV System did a backup of the database");
pw.println("Complete date: "+data);
pw.println("");
pw.println(simpleDate);
pw.close();
backupFile.close();
}
else
{
FileWriter backupFile = new FileWriter(backupDirectory+"\\"+"LastBackup.txt");
PrintWriter pw = new PrintWriter(backupFile,true);
pw.println("This is the last time that the IBV System did a backup of the database");
pw.println("Complete date: "+data);
pw.println("");
pw.println(simpleDate);
pw.close();
backupFile.close();
}
}
public static boolean dateCalculation() throws FileNotFoundException, IOException{
File dirDestinoBackup = new File("C:\\IBV System");
String way = dirDestinoBackup.getAbsolutePath();
File backupDirectory = new File(way+"\\Backup Date");
if(!backupDirectory.exists()){
settingBackupDate();
}
boolean validDate = false;
BufferedReader reader = new BufferedReader(new FileReader("C:\\IBV System\\Backup Date\\LastBackup.txt"));
String text = new String();
int numLinha = 0;
while(reader.ready()){
text += reader.readLine()+";";
numLinha ++;
}
String [] temp = text.split(";");
String date = temp[3];
String [] dateSplit = date.split("/");
Calendar data = new GregorianCalendar();
int systemDay = data.get(Calendar.DAY_OF_MONTH);
int day;
if(dateSplit[0].equals("")){
day = 1;
}
else{
day = Integer.parseInt(dateSplit[0]);
}
if(systemDay - day == 7){
validDate = true;
}
return validDate;
}
public static boolean isDirectoryExist(){
boolean temp = false;
if (dirDestino.exists()){
String [] list = dirDestino.list();
if (list==null){
}else
temp = true;
}
return temp;
}
public static String getCaminhoNovaPasta(){
return caminhoNovaPasta;
}
}
[/code]
Só explicando… esse código eu faço o backup automático do banco a cada 15 dias ou quando o usuário quiser fazer.
Ele cria a pasta em um local específicado lá em cima e caso a pasta já exista, ele não fica naquela mensagem do windows se deseja substituir ou algo assim, ele calcula a quantidade de pastas que já existem com o mesmo nome e faz o padrão de cópia do windows (nome(1), nome(2),nome(3))…
Qualquer dúvida é só ppostar ae amigo.
[quote=andre_bento]
Só explicando… esse código eu faço o backup automático do banco a cada 15 dias ou quando o usuário quiser fazer.
Ele cria a pasta em um local específicado lá em cima e caso a pasta já exista, ele não fica naquela mensagem do windows se deseja substituir ou algo assim, ele calcula a quantidade de pastas que já existem com o mesmo nome e faz o padrão de cópia do windows (nome(1), nome(2),nome(3))…
Qualquer dúvida é só ppostar ae amigo.[/quote]
Pelo oque eu li no codigo, da linha 104 até a 157 vai resolver meu problema, não tinha conhecimento destas ferramentas em Java, muito bom mesmo.
Muito obrigado pelo código, vou testar na terça-feira (20/03) e posto o resultado aqui.
Abraços
Douglas Junior
[quote=andre_bento]
Só explicando… esse código eu faço o backup automático do banco a cada 15 dias ou quando o usuário quiser fazer.
Ele cria a pasta em um local específicado lá em cima e caso a pasta já exista, ele não fica naquela mensagem do windows se deseja substituir ou algo assim, ele calcula a quantidade de pastas que já existem com o mesmo nome e faz o padrão de cópia do windows (nome(1), nome(2),nome(3))…
Qualquer dúvida é só ppostar ae amigo.[/quote]
Cara, eu usei parte do seu método, mas ainda fico no mesmo problema.
Ele executa o código e trava a aplicação, quando eu finalizo a aplicação ele cria o arquivo de Backup certinho no lugar onde mandei.
Se eu rodar dentro de uma “Thread” ele não trava a aplicação, mas ele só cria o arquivo de backup quando a aplicação é finalizada também.
Veja o código como ficou:
[code] private boolean efetuarBackupPostgres() {
String arquivoDump = “C:\Program Files (x86)\pgAdmin III\1.12\pg_dump.exe”;
String arquivoBkp = new File(“dados/database” + Util.dateDataToString(new Date(), “-yyyy-MM-dd-HH-mm-ss”) + “.backup”).getAbsolutePath();
try {
List<String> comandos = new ArrayList<String>();
comandos.add(arquivoDump);
comandos.add("-i");
comandos.add("-h");
comandos.add(PersistenciaServices.host);
comandos.add("-p");
comandos.add(PersistenciaServices.porta);
comandos.add("-U");
comandos.add(PersistenciaServices.usuario);
comandos.add("-F");
comandos.add("c");
comandos.add("-v");
comandos.add("-f");
comandos.add(arquivoBkp);
comandos.add(PersistenciaServices.banco);
for (String string : comandos) {
System.out.print(string + " ");
}
ProcessBuilder pb = new ProcessBuilder(comandos);
pb.environment().put("PGPASSWORD", PersistenciaServices.senha);
Process process = pb.start();
BufferedReader brOut = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String lineOut = brOut.readLine();
while (lineOut != null) {
System.out.println(lineOut);
lineOut = brOut.readLine();
}
BufferedReader brError = new BufferedReader(
new InputStreamReader(process.getErrorStream()));
String lineError = brError.readLine();
while (lineError != null) {
System.err.println(lineError);
lineError = brError.readLine();
}
brError.close();
process.waitFor();
System.out.println("backup realizado com sucesso.");
process.destroy();
return true;
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "ERRO durante o backup:" + e);
e.printStackTrace();
}
return false;
}[/code]
Abraços
Douglas Junior
Resolvi o problema paliativamente.
Para resolver estou gravando o comando em um arquivo .bat e depois executando o arquivo “.bat”
Ainda não gostei da solução, pois eu tenho que me preocupar em apagar o arquivo “.bat” toda vez, caso contrário as informações do banco ficam expostas.
Código:
[code] private boolean efetuarBackupPostgres() {
String arquivoDump = “C:\Program Files (x86)\pgAdmin III\1.12\pg_dump.exe”;
String arquivoBkp = new File(“dados/database” + Util.dateDataToString(new Date(), “-yyyy-MM-dd-HH-mm-ss”) + “.backup”).getAbsolutePath();
File fileBat = new File(“runbakcup.bat”);
try {
// escrever arquivo .bat
PrintWriter pw = new PrintWriter(fileBat);
pw.println(“echo off”);
String comandos = “”" + arquivoDump + “” -i "
+ " -h " + PersistenciaServices.host
+ " -p " + PersistenciaServices.porta
+ " -U " + PersistenciaServices.usuario
+ " -F c -v "
+ " -f “” + arquivoBkp + “” "
+ PersistenciaServices.banco + “”;
System.out.println(comandos);
pw.println(comandos);
pw.println(“exit”);
pw.close();
// executar arquivo .bat
List<String> comandoBat = new ArrayList<String>();
comandoBat.add("cmd.exe");
comandoBat.add("/c");
comandoBat.add(fileBat.getAbsolutePath());
ProcessBuilder pb = new ProcessBuilder(comandoBat);
Process process = pb.start();
// escreve saida
BufferedReader r = new BufferedReader(
new InputStreamReader(process.getErrorStream()));
String line = r.readLine();
while (line != null) {
System.err.println(line);
line = r.readLine();
}
r.close();
process.waitFor();
System.out.println("backup realizado com sucesso.");
process.destroy();
return true;
} catch (Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(null, "ERRO durante o backup:" + e);
}
fileBat.delete();
return false;
}[/code]
Se conseguir algo diferente posto o resultado aqui.
Abraços
Douglas Junior