Página 1 de 2

criando um backup de hora em hora sem para o sistema

Enviado: 17 Nov 2009 09:07
por luizservulo
Bom dia a todos,


Gostaria de perguntar se alguem roda um backup sem interronper o funcionamento do sistema pedindo aos usuarios que abandonem o sistema por um certo período, alguém tem uma solução para isso? (que rode dentro do sistema) li num post que o amigo Rochinha ia postar algo em Dicas, Contribuições ou código-fonte, mas não achei nada.


atenciosamente.


Luiz Servulo

xhb 1.10 e 1.20.1 + wvt + dbfcdx (tentando pular para harbour, ainda sem sucesso...)

Re: criando um backup de hora em hora sem para o sistema

Enviado: 17 Nov 2009 20:23
por Hasse
Olá luizservulo

Depois de muitas tentativas frustadas tive que optar por fazer uma cópia do(s) arquivo(s) DBF, com o comando COPY FILE (cOrigem) TO (cDestino) e dela compactar com a Função HB_ZIPFILE() do xHarbour.

Para isto fiz um sistema autônomo que é "rodado" ao final do dia, ou 2 vezes ao dia, conforme o cliente, mas sem parar o sistema, que continua a todo vapor. Ele roda 24 horas por dia, 365 dias por ano.

Esta opção "copiar/zipar" foi necessária porque o Windows Server 2000 não permite zipar um arquivo DBF aberto, no entanto permite copiar este arquivo aberto. Não sei se acontece o mesmo com outras versões do Windows. Não testei em Windows 89 e nem no XP. Quem sabe algum colega possa colocar a sua experiência.

Acredito que não seria difícil fazer o aplicativo rodar em background (como um Serviço do Windows ??? - não sei este é o termo correto...), e, de hora em hora, ativado para uma função de temporização, fazer o seu trabalho.

Re: criando um backup de hora em hora sem para o sistema

Enviado: 19 Nov 2009 20:04
por luizservulo
Grande idéia...

As vezes ficamos querendo descobrir a solução de algo e é tão simples.

fico agradecido ao amigo pela clareira que tú me abristes nessa mata :-)


Por enquanto resolvido assim + OpenProcess rodando de hora em hora...


agora so falta fazer na surdina sem esperar terminar o backup

Re: criando um backup de hora em hora sem para o sistema

Enviado: 19 Nov 2009 21:12
por Hasse
É nada mais, nada menos que um grande prazer.

Fico satisfeito que a minha experiência possa ajudar um amigo.

Re: criando um backup de hora em hora sem para o sistema

Enviado: 19 Nov 2009 22:34
por TerraSoftware
Caros colegas, a questaum de zipar um arquivo aberto é muito perigosa, pois o arquivo pode ser danificado, o ideal mesmo é copiar para uma pasta temporaria e depois compactar, assim como o amigo Hasse esta fazendo. A questaum se o OS permite ou nao zipar o arquivo aberto, eu sinceramente nao sei, pois nunca tentei. Acredito que a grande maioria dos amigos façam isso mesmo, (copiar e zipar), é o mais seguro. Eu uso outro software para fazer isso, (outro que eu digo, é um diferente do que o usuario esta usando), uso o agendador de tarefas do windows para disparar este programa de tempos em tempos, de acordo com a vontade do cliente. Assim é transquilo, transparente para o usuario e nao exige muito da maquina.

Re: criando um backup de hora em hora sem para o sistema

Enviado: 20 Nov 2009 03:15
por alxsts
Olá!
Hasse escreveu:fazer uma cópia do(s) arquivo(s) DBF, com o comando COPY FILE (cOrigem) TO (cDestino) e dela compactar com a Função HB_ZIPFILE()
mas sem parar o sistema, que continua a todo vapor. Ele roda 24 horas por dia, 365 dias por ano.
Achei o assunto interessante. Algumas dúvidas.

Pelo que o amigo Hasse postou, o backup vem funcionando normalmente. Não sei se é isto mas, pelo jeito, ele tem uma rotina que abre cada arquivo de forma exclusiva e faz o COPY FILE. Depois disso é feita a compactação. Mas, se o sistema roda 24x7, como ele consegue copiar esses arquivos? Seria sem USE EXCLUSIVE? Isso poderia pegar atualizações não concluídas e se for com EXCLUSIVE, cairia no mesmo problema de zipar um arquivo aberto.... Ou será que o Windows permite zipar um DBF aberto em modo exclusivo?

Só como complemento (talvez alguém se interesse), já vi na internet fontes de rotinas de compactação, escritas em Clipper.

Re: criando um backup de hora em hora sem para o sistema

Enviado: 20 Nov 2009 10:48
por luizservulo
boa...

Por TerraSoftware "a questaum de zipar um arquivo aberto é muito perigosa..."

este era justamente o problema, o único compactador que fazia a copia com o arquivo em USO era o ARJ (DOS) e era ele que usava.

mas a idéia do amigo Hasse nem tinha me passado pela cabeça, depois que ele disse ficou tudo mais claro...como estou fazendo agora

xhb121

uso HB_OpenProcess para rodar a função backup (dentro do sistema) a cada 1 hora (posso permitir um tempo menor...) e pimba chegou no horário o sistema executa a função, único problema...até acabar a cópia...zipar...e eliminar a copia temporia aquele terminal fica pendurado :-(

eu gostaria de usar MultiThread...mais como estou usando WVT isso não foi possivel, até abri um tópico sobre isso.

só para clarear a mente o HB_OpenProcess se encarregado de colocar o processo direto no relogio do windows ...

Re: criando um backup de hora em hora sem para o sistema

Enviado: 20 Nov 2009 15:17
por Hasse
Por TerraSoftware "a questaum de zipar um arquivo aberto é muito perigosa..."
E no caso do Windows Server 2000, zipar é impossível. Ele não permite o acesso. Contudo, como falei acima, ele permite fazer uma cópia. Não sei se é furo do Server, mas o fato é ele permite fazer cópia, mesmo que o arquivo esteja aberto em modo compartilhado.
Mas, se o sistema roda 24x7, como ele consegue copiar esses arquivos? Seria sem USE EXCLUSIVE?
O comando COPY FILE do xHarbour é igual (ou muito semelhante) ao comando COPY do DOS, portanto nem há como ter cláusula de EXCLUSIVE. Simplesmente se copia o arquivo aberto em modo compartilhado. Aliás, o comando COPY do DOS também funciona.

É bem verdade que, neste momento é necessário tomar cuidado com a consistência dos dados, pois no momento da cópia é possível que haja alguma gravação de dados. Cada qual deve avaliar isto com bastante cuidado. No meu caso esta possível inconsistência é irrelevante, pois no backup seguinte isto se corrige automaticamente. E se houver necessidade de usar o backup eu terei que avaliar se há falta de consistência e fazer a correção.

Eu não sei como se comporta o Driver que lê e escreve no HD...??? Ele pode escrever e ler ao mesmo tempo ??? Eu acredito que não. Acredito que o driver deve fazer um trabalho de cada vez. Certamente temos alguns Mestres que estão acompanhando o tópico podem nos esclarcer sobre este item.

Baseado na crença que o Driver faz um trabalho de cada vez (vejam, pode estar errada) é que eu desenvolvi este raciocínio de backup.

Esta rotina está funcionando faz bem uns 2 anos e nunca me deu qualquer problema. Também nunca tive necessidade de usar o backup.

Já abri os arquivo do backup algumas vezes com o DBU e nada encontrei de estranho e nem de falta de consistência do dados.

Re: criando um backup de hora em hora sem para o sistema

Enviado: 20 Nov 2009 16:33
por alxsts
Olá!

No tópico que postei anteriormente, realmente misturei o comando COPY (que precisa ter um arquivo DBF aberto) com o comando COPY FILE, que tanto no Clipper como no [x]Harbour funcionam como no DOS.

Também não sei se é furo mas, o Windows permite que você copie o arquivo mesmo aberto por outra aplicação, desde que não esteja aberto EXCLUSIVE. Nesta última condição, o COPY FILE também não copia e nem dá mensagem. É preciso verificar se copiou ou não senão, passa despercebido e o arquivo não estará no teu backup zipado. O resultado pode ser inesperado. Uma vez fiz um teste: criei um executável que, quando executado, deletava a si próprio. E funciona... Em outro exemplo, tentei abrir o executável durante sua execução e escrever nêle. Aí, não funciona.

Quanto à leitura e gravação em disco, certamente são feitos um de cada vez. Creio que o SO use um file handlerdiferente para cada processo, mesmo se referindo ao mesmo arquivo. O problema é pegar um bloco de arquivo ainda não gravado totalmente...

Re: criando um backup de hora em hora sem para o sistema

Enviado: 20 Nov 2009 19:48
por luizservulo
Hasse só pra descontrair...backup é um negócio que você só vai precisar se não estiver fazendo...
:xau

Re: criando um backup de hora em hora sem para o sistema

Enviado: 20 Nov 2009 21:44
por Hasse
luizservulo: Você está coberto de razão, da cabeça aos pés. É a famosa Lei de Murphy que sempre dá os ares da sua graça.

alxsts: É, concordo com você, em gênero, grau e número, no caso do arquivo não estar com a cláusula EXCLUSIVE, para que o COPY possa funcionar. Eu nunca tive esta preocupação, já que nos meus aplivativos os arquivos abertos estão sempre em modo compartilhado. Neles só uso o modo EXCLUSIVE quando de uma indexação geral, e neste momento nem preciso me preocupar com backup.

No caso do file handler que você mencionou, durante a execução do DBComit() não seria de pensar que todos os blocos que estivessem nos buffer´s seriam gravados de uma só vez, e só liberando após concluído ?
O problema é pegar um bloco de arquivo ainda não gravado totalmente...
É justamente este caso ao que me refiro quando falo em consistência... Mas, ainda não detectei algum caso em isso tivesse acontecido.

Re: criando um backup de hora em hora sem para o sistema

Enviado: 20 Nov 2009 22:43
por alxsts
Olá!

Tudo acontece de forma muito veloz nestes casos de concorrência no acesso ao mesmo dado. Imagine o teu sistema rodando 24x7, executando vários COMMIT's. Aí, a rotina de backup é disparada... Pode ocorrer que um arquivo sofra um COMMIT e em seguida seja copiado ou que no meio da cópia, sofra o COMMIT... Penso que a melhor maneira de fazer backup é com todos os usuários fora. Sei que nem sempre é possível. Devem existir outros mas, o único gerenciador de banco de dados que conheço que permite o hot backup é o Oracle...

Re: criando um backup de hora em hora sem para o sistema

Enviado: 21 Nov 2009 10:14
por Hasse
Bom dia alxsts.

Realmente as coisas podem acontecer desta forma como você colocou. Nas várias vezes que eu dei uma olhada nos arquivos dos backup´s nunca encontrei qualquer problema e nem inconsistência de dados. Pode ter sido sorte e que ela vai abandonar no momento mais crucial. Não sei. Só o tempo para confirmar.

Como eu também já falei, no meu caso em particular, estas inconsistências são irrelevantes.

Por este motivo, cada qual deve analisar o seu problema com muito cuidado. É evidente que se a consistência de dados tem relevância no backup, então não há outra solução: Parar tudo para fazer o backup.

Re: criando um backup de hora em hora sem para o sistema

Enviado: 21 Nov 2009 22:36
por janio
luizservulo,

Vc pode postar aqui sua rotina??? De como vc está fazendo???

Re: criando um backup de hora em hora sem para o sistema

Enviado: 22 Nov 2009 00:47
por Vander
Olá;
Tenho um sisteminha "meia boca" (mas funciona) que fica no Tray e de tempos em tempos ele é ativado e realiza o Backup dos arquivos para o drive indicado, se servir para alguém ai está

Código: Selecionar todos

#include "fivewin.ch"
#include "struct.ch"
#define NIM_ADD     0 //
#define NIM_DELETE  2 //
#define NIM_MODIFY  1 //   Para TaskAddIcon
#define NIF_ICON    2 //
#define NIF_MESSAGE 1 //
#define NIF_TIP     4 //
STATIC oWndTray, oTray, oTrayIcon, lQuitTray := .F., lTaskWork := .F.
//--------------------
FUNCTION Main()
PUBLIC hBorland := LoadLibrary( "bwcc32.dll" )
PUBLIC hWorkRes := LoadLibrary( "workres.dll" )
PUBLIC hFivewin := LoadLibrary( "fwctrls.dll" )
   IF FindWindow( 0, "BackUp automático" ) > 0
      RETURN NIL
   ENDIF
   DEFINE ICON oTrayIcon RESOURCE "aaaahairty"
   DEFINE WINDOW oWndTray TITLE "BackUp automático" ICON oTrayIcon FROM 600, 600 TO 601, 601
   oWndTray:bTaskBar := { | nWParam, nLParam | TaskBar( nWParam, nLParam ) }
   oWndTray:bResized := { | nSizeType | DoTaskBar( nSizeType ) }
   ACTIVATE WINDOW oWndTray ON INIT Initialize() VALID QuitTray()
RETURN NIL
*------------------------------------------------------------------------------*
FUNCTION Initialize()
   USE ..\DADOS008\ATUALIZA ALIAS CONFIG SHARED
   // TMPBK = Campo do arquivo de configuração com o tempo em minutos para executar o BKP
   TMP:=TMPBK * 60000  // 10000
   // DVRBK = Campo do arquivo de configuração com o dive de destino do BKP
   DRV:=DVRBK+":\"
   CLOSE DATABASE
   AEVAL(DIRECTORY(DRV+"DADOSCOP\DB\*.*"),{|aFile| FErase(DRV+"DADOSCOP\DB"+aFile[1])})
   AEVAL(DIRECTORY(DRV+"DADOSCOP\NF\*.*"),{|aFile| FErase(DRV+"DADOSCOP\NF"+aFile[1])})
   SET EXCL  ON
   SET EXACT ON
   SetHandleCount( 200 )
   REQUEST DBFCDX
   RDDSETDEFAULT("DBFCDX")
   REQUEST HB_CODEPAGE_PT850
   HB_SETCODEPAGE( "PT850" )
   SET DECIMALS TO 2
   SET CENTURY ON
   SET DELETED ON
   SET DATE TO FRENCH
   SET EPOCH TO 1990
   SET 3DLOOK ON
   nResHoriz := oWndTray:nHorzRes() // retorna a resolucao horizontal
   nResVert  := oWndTray:nVertRes()  // retorna a resolucao vertical
//--------------- criar pastas
   lMkDir(DRV+"DADOSCOP")
   lMkDir(DRV+"DADOSCOP\DB")
   lMkDir(DRV+"DADOSCOP\NF")
   
   lMkDir("DADOSPRE")
   lMkDir("DADOSPRE\DB")
   lMkDir("DADOSPRE\NF")
   
   (oWndTray:Minimize(),ajt(tmp,DRV))
RETURN NIL
//------------- VERIFICAR TEMPO
FUNCTION ajt(tempo,DRV)
  DEFINE TIMER oTimer OF oWndTray                 INTERVAL tempo ACTION cpar(DRV)
  oTimer:activate()
RETURN NIL
//-------------GERAR COPIA
function cpar(DRV)
//--------------- ELIMINAR ARQUIVOS
   AEVAL(DIRECTORY("DADOSPRE\DB\*.*"),{|aFile| FErase("DADOSPRE\DB"+aFile[1])})
   AEVAL(DIRECTORY("DADOSPRE\NF\*.*"),{|aFile| FErase("DADOSPRE\NF"+aFile[1])})
//--------------- COPIAR ARQUIVOS
   COPIACAO1 := Directory("..\DADOS008\*.DBF")
   FOR nI = 1 TO Len(COPIACAO1)
       ORIG:="..\DADOS008\"+COPIACAO1[ nI, 1 ]
       DEST:="DADOSPRE\DB\"+COPIACAO1[ nI, 1 ]
       COPY FILE  "&ORIG" TO "&DEST"
   NEXT

   COPIACAO2 := Directory("..\FISCAL\NFES\*.*")
   FOR nI = 1 TO Len(COPIACAO2)
       ORIG:="..\FISCAL\NFES\"+COPIACAO2[ nI, 1 ]
       DEST:="DADOSPRE\NF\"+COPIACAO2[ nI, 1 ]
       COPY FILE  "&ORIG" TO "&DEST"
   NEXT
//---------------- COMPACTAR ARQUIVOS
   cArq := DRV+"\DADOSCOP\DB\BK" + SUBSTR(TIME(),1,2)+SUBSTR(TIME(),4,2)+SUBSTR(TIME(),7,2)   + ".ZIP"
   ARQUIVOS := {}
   AFILES := Directory("DADOSPRE\DB\*.DBF")
   FOR nI = 1 TO Len(aFiles)
       AAdd( ARQUIVOS, "DADOSPRE\DB\"+AFILES[ nI, 1 ] )
   NEXT
   
   IF HB_ZipFile(cArq,ARQUIVOS,,,,,,,{|x,t| qout(int((x/t)*100))})
      SndPlaySound("chimes.MP3")
     ELSE
      SndPlaySound("Erro.mp3")
   ENDIF

   cArq2 := DRV+"\DADOSCOP\NF\BK" + SUBSTR(TIME(),1,2)+SUBSTR(TIME(),4,2)+SUBSTR(TIME(),7,2)   + ".ZIP"
   ARQUIVOS2 := {}
   AFILES2 := Directory("DADOSPRE\NF\*.*")
   FOR nI = 1 TO Len(aFiles2)
       AAdd( ARQUIVOS2, "DADOSPRE\NF\"+AFILES2[ nI, 1 ] )
   NEXT
   IF HB_ZipFile(cArq2,ARQUIVOS2,,,,,,,{|x,t| qout(int((x/t)*100))})
      SndPlaySound("chimes.MP3")
     ELSE
      SndPlaySound("Erro.mp3")
   ENDIF
return .t.
*------------------------------------------------------------------------------*
FUNCTION TaskBar( nWParam, nLParam )
LOCAL aCoors := ARRAY(2)
   lTaskWork := .F.
   IF !lTaskWork
      lTaskWork := .T.
      DO CASE
         CASE nLParam == WM_RBUTTONUP // WM_LBUTTONUP
         CASE nLParam == WM_LBUTTONUP // WM_RBUTTONUP
              aCoors := GetCursorPos()
              aCoors := ScreenToClient( oWndTray:hWnd, aCoors )
              TaskMenu( aCoors[1], aCoors[2] )
      ENDCASE
      lTaskWork := .F.
     ELSEIF nLParam == WM_LBUTTONUP
      lTaskWork := .F.
   ENDIF
RETURN NIL
*------------------------------------------------------------------------------*
FUNCTION DoTaskBar( nWhich )
   DEFAULT nWhich := -1
   DO CASE
      CASE nWhich == 1
           IF VALTYPE( oTray ) <> "O"
              oTray := TaskAddIcon( oWndTray, oTrayIcon, "BackUp automático" ) // este
              oWndTray:Hide()
           ENDIF
      CASE nWhich == 0 .OR. nWhich == 2
           IF VALTYPE( oTray ) == "O"
              TaskDelIcon( oTray, oTrayIcon )
           ENDIF
           oTray := NIL
   ENDCASE
RETURN NIL
*------------------------------------------------------------------------------*
FUNCTION TaskMenu( nRow, nCol )
LOCAL oTrayMenu
   MENU oTrayMenu POPUP kkk
      MENUITEM "Fechar menu"                         WHEN TaskWhen("fecmen") ACTION NIL
      SEPARATOR
      MENUITEM "&Sair"                               WHEN TaskWhen("fecsis") ACTION QuitTray()
   ENDMENU
   ACTIVATE POPUP oTrayMenu AT nRow, nCol OF oWndTray
RETURN NIL
*------------------------------------------------------------------------------*
FUNCTION TaskWhen( cMenu )
   DO CASE
      CASE cMenu == "fecmen"
           RETURN( .T. )
      CASE cMenu == "fecsis"
           RETURN( .T. )
   ENDCASE
RETURN( .F. )
*------------------------------------------------------------------------------*
FUNCTION QuitTray()
LOCAL oDlg, oFont, oBmp, oRad, nRad := 2, lOk := .F.
   nRad:=2
   IF !lQuitTray
       DEFINE FONT oFont Name "Arial" SIZE 0, -12 BOLD
       DEFINE DIALOG oDlg RESOURCE "Dlg_QuitTray"  COLOR  RGB (0,0,0),RGB (0,0,255)
       REDEFINE BITMAP oBmp ID 500 RESOURCE "NDSLogo" OF oDlg  adjust
       REDEFINE SAY ID 501 PROMPT "Confirma o fechamento do sistema ?" OF oDlg FONT oFont COLOR  RGB (255,255,255),RGB (0,0,255)
       REDEFINE BUTTON ID 103 OF oDlg ACTION (  oDlg:bLostFocus := NIL, lOk := .T., oFont:End(), oDlg:End() )
       REDEFINE BUTTON ID 104 OF oDlg ACTION (  oDlg:bLostFocus := NIL, lOk := .F., oFont:End(), oDlg:End() )
       oDlg:bLostFocus := {|| oDlg:bLostFocus := NIL, lOk := .F., oFont:End(), oDlg:End() }
       ACTIVATE DIALOG oDlg CENTER
       IF lOk .AND. nRad == 2
          lQuitTray := .T.
          IF oTray != NIL
              TaskDelIcon( oTray )
          ENDIF
          oTrayIcon:End()
          oWndTray:End()
       ENDIF
   ENDIF
RETURN( .T. )
*------------------------------------------------------------------------------*
FUNCTION TaskAddIcon( oWnd, oIcon, cToolTip )
LOCAL oNotifyIconData
   STRUCT oNotifyIconData
      MEMBER nSize          AS DWORD
      MEMBER hWnd           AS LONG
      MEMBER nId            AS LONG
      MEMBER nFlags         AS LONG
      MEMBER nCallMsg       AS LONG
      MEMBER hIcon          AS LONG
      MEMBER cToolTip       AS STRING LEN LEN( cToolTip )
   ENDSTRUCT
   oNotifyIconData:nSize        = oNotifyIconData:SizeOf()
   oNotifyIconData:hWnd         = oWnd:hWnd
   oNotifyIconData:nId          = 1
   oNotifyIconData:nFlags       = nOr( NIF_ICON, NIF_MESSAGE, NIF_TIP )
   oNotifyIconData:nCallMsg     = WM_TASKBAR
   oNotifyIconData:hIcon        = oIcon:hIcon
   oNotifyIconData:cToolTip     = cToolTip
   Shell_NotifyIcon( NIM_ADD, oNotifyIconData:cBuffer )
RETURN oNotifyIconData
//------------------------------------------------------------------------//
FUNCTION TaskDelIcon( oNotifyIconData )
   Shell_NotifyIcon( NIM_DELETE, oNotifyIconData:cBuffer )
RETURN NIL
//------------------------------------------------------------------------//
FUNCTION TaskChangeIcon( oNotifyIconData ,oIcon)
   oNotifyIconData:nFlags    = NIF_ICON
   oNotifyIconData:hIcon     = oIcon:hIcon
   Shell_NotifyIcon( NIM_MODIFY, oNotifyIconData:cBuffer )
RETURN oNotifyIconData
//------------------------------------------------------------------------//
DLL32 FUNCTION Shell_NotifyIcon( nMsg AS LONG, pNID AS LPSTR ) AS BOOL PASCAL ;
                                 FROM "Shell_NotifyIconA" LIB "shell32.dll"
//------------------------------------------------------------------------//
DLL32 FUNCTION ShellExecute( hWnd AS LONG, cOperation AS LPSTR,;
                             cFile AS LPSTR, cParams AS LPSTR,;
                             cDir AS LPSTR, nShow AS LONG ) AS LONG PASCAL ;
                             FROM "ShellExecuteA" LIB "shell32.dll"
//------------------------------------------------------------------------//

Alterações e melhorias, postem aqui.

Vander