1. Este site usa cookies. Ao continuar a usar este site está a concordar com o nosso uso de cookies. Saber Mais.

[duvida] - Backups programados de um site

Discussão em 'Web Development' iniciada por JPCarvalhinho, 7 de Agosto de 2008. (Respostas: 35; Visualizações: 2571)

  1. JPCarvalhinho

    JPCarvalhinho Colaborador
    Staff Member

    Estou a participar num projecto grandinho e estou com algum receio que alguém faça asneira e como tal pretendo fazer backups diários dos htmls e do mysql do site...

    Sei que posso ir diariamente ao cpanel e clicar na área de backup e fazer a coisa manualmente...

    Mas e se eu quizer fazer um backup automático às tantas horas da noite para não interferir com algum visitante?

    Encontrei duas opções:

    1- Usar os comandos CRON programando alguns trabalhos de compressão e de transmissão por ftp para outro site...-> vou ter que pesquisar os comandos na net...

    2- Uma aplicação externa tipo http://www.site-vault.com/ que faz o que quero para um disco local... mas que não tenho qualquer feedback.... mas facilmente passo para o cliente para ele manter.


    O que vocês aconselham?

    Cumps
    JPC
     
  2. Kayvlim

    Kayvlim Undefined Moderator
    Staff Member

    Assim por alto, ocorre-me uma coisa:
    Porque não fazeres um script, talvez em PHP, que fizesse o dump da bd para uma pasta fora do /www, e depois fazias um gzip do /www mais o .sql para outro ficheiro nessa pasta, e com o fsockopen ligavas-te por FTP ao outro servidor e enviavas o .gz?
    Assim, o cronjob podia ser configurado para ser executado perto das 5 da manhã, e só tinha de executar um PHP.

    Foi a primeira coisa que me ocorreu, mas pode ser que haja alguma forma melhor :x
     
  3. anjo2

    anjo2 Power Member

    O projecto não é alojado por uma empresa? Geralmente as empresas de alojamento fazem vários backups, mas pelo menos diários
     
  4. _freelancer_

    _freelancer_ Power Member

    ...e depois contratam um gnomo para todos os dias aceder ao script que faz o trabalho. :P

    É o único problema da tua solução: garantir periodicidade. Claro que este script pode ser feito em php e depois simplesmente fazer um cronjob que faz: php backup_script.php todos os dias :)
     
  5. Kayvlim

    Kayvlim Undefined Moderator
    Staff Member

    Mas foi isso que propus - o script em php, e o cronjob era configurado para executar o PHP.
    O que é que me está a escapar?
     
  6. _freelancer_

    _freelancer_ Power Member

    Escapou-me a mim, por algum motivo não li a parte do teu post que falava de correr o script :nie2:
     
  7. slack_guy

    slack_guy Power Member

    Aqui fica um sugestão em Perl.

    Código:
    #!/usr/bin/perl -T
    #==========================================================================
    #
    #         FILE:  backup.pl
    #
    #        USAGE:  ./backup.pl -T (depois de tornar o script executável: 'chmod +x backup.pl')
    #
    #  DESCRIPTION:  Backup de ficheiros (recursivo) para tar.gz
    #                Dump de base de dados mysql (sql -> tar.gz)
    #                Envia ficheiros para servidor FTP
    #                Envia mail com tempo de execução do backup
    #
    #      OPTIONS:  ---
    # REQUIREMENTS:  Net::FTP
    #                Mail::Sendmail
    #         BUGS:  ---
    #        NOTES:  O backup é composto por dois ficheiros: <DATA>_files.tar.gz e <DATA>_mysql.tar.gz.
    #                Desta forma facilita-se o acesso a um ou a outro consoante a necessidade.
    #       AUTHOR:  slack_guy @ TZ
    #      VERSION:  0.1
    #      CREATED:  09-08-2008 12:15:27 WEST
    #==========================================================================
    #  This program comes with NO WARRANTY, to the extent permitted by law.
    #==========================================================================
    #  This program is free software; you can redistribute it and/or modify
    #  it under the terms of the GNU General Public License as published by
    #  the Free Software Foundation; either version 2 of the License, or
    #  (at your option) any later version.
    #==========================================================================
    #
    
    use strict;
    use warnings;
    
    $ENV{'PATH'} = '/usr/local/bin:/usr/bin';
    
    use Time::HiRes qw/gettimeofday tv_interval/;
    
    my $time_start = [gettimeofday];
    
    my $data = data();
    
    #==========================================================================
    # Definições: modifica os parâmetros de acordo com o teu sistema
    my $defs = {
        ftp_server     => 'ftp.example.com',
        ftp_user       => 'ftp_username',
        ftp_pass       => 'ftp_password',
        ftp_remote_dir => 'backups',
    
        mysql_user => 'mysql_username',
        mysql_pass => 'mysql_password',
        mysql_db   => 'mysql_database',
    
        # pastas a copiar
        dirs2backup => [
            '/home/me/www/xpto',
            '/home/you/www/xyz',
        ],
    
        # ficheiro de backup
        backup2file => "/home/me/tmp/${data}_files.tar.gz",
    
        # log temporario de ficheiros a copiar; é eliminado quando deixa de ser necessario
        temp_log_file => "/home/me/tmp/backup_$data.log",
    
        # ficheiro temporario com o dump da BD; é eliminado quando deixa de ser necessario
        temp_dump     => "/home/me/tmp/dump_$data.sql",
    
        # ficheiro com o dump da BD que vai ser transferido para o servidor remoto
        mysql_tar     => "/home/me/tmp/${data}_mysql.tar.gz",
    
        # qualquer expressao diferente de 'sim' equivale a 'nao'
        apagar_backups_locais => 'sim',
    
        mail_to      => [email protected]',
        mail_from    => [email protected]',
        mail_subject => "Backup de $data",
        mail_smtp    => 'mail.example.com', # ou 'localhost'
    };
    
    # A partir daqui não deverá ser necessário alterar mais nada.
    #==========================================================================
    
    my $cmds = {
        find       => '/usr/bin/find',
        tar        => '/bin/tar',
        mysql_dump => '/usr/bin/mysqldump',
    };
    
    dump_db();
    backup();
    send_ftp();
    
    my $time_end = tv_interval( $time_start, [gettimeofday] );
    
    send_mail();
    finish();
    
    exit 0;
    
    sub finish {
    
        if (   $defs->{apagar_backups_locais}
            && $defs->{apagar_backups_locais} eq 'sim' )
        {
            unlink $defs->{backup2file};
            unlink $defs->{mysql_tar};
        }
    
        return;
    }
    
    sub send_ftp {
    
        use Net::FTP;
    
        my $ftp = Net::FTP->new( $defs->{ftp_server}, Debug => 0 )
          or die "Impossivel ligar ao servidor $defs->{ftp_server} : $@";
    
        $ftp->login( $defs->{ftp_user}, $defs->{ftp_pass} )
          or die "Impossivel entrar ", $ftp->message;
    
        $ftp->cwd( $defs->{ftp_remote_dir} )
          or die "Impossivel ir para a pasta $defs->{ftp_remote_dir} ",
          $ftp->message;
    
        $ftp->put( $defs->{backup2file} )
          or die "Impossivel copiar o ficheiro ", $ftp->message;
    
        $ftp->put( $defs->{mysql_tar} )
          or die "Impossivel copiar o ficheiro ", $ftp->message;
    
        $ftp->quit;
    
        return;
    }
    
    sub backup {
    
        my $pastas = $defs->{dirs2backup};
    
        # criamos um log com todas as pastas e ficheiros que vamos compactar
        foreach my $pasta (@$pastas) {
            my $cmd = qx|$cmds->{find} $pasta >> $defs->{temp_log_file}|;
        }
    
        # criamos o tar.gz com os ficheiros
        my $tgz = qx|$cmds->{tar} czpf $defs->{backup2file} -T $defs->{temp_log_file} 2>/dev/null|;
    
        # apagamos o log
        unlink $defs->{temp_log_file};
    
        return;
    }
    
    sub dump_db {
    
        # Dump da base de dados
        my $dump_cmd = qq|$cmds->{mysql_dump} --opt --user=$defs->{mysql_user} |;
        $dump_cmd .= qq|--password=$defs->{mysql_pass} $defs->{mysql_db} |;
        $dump_cmd .= qq| > $defs->{temp_dump}|;
    
        my $dump_mysql = qx|$dump_cmd|;
    
        # Compactar o dump da BD
        my $tgz =
          qx|$cmds->{tar} czfp $defs->{mysql_tar} $defs->{temp_dump} 2>/dev/null|;
    
        # Eliminar o dump temporario (ficheiro .sql)
        unlink $defs->{temp_dump};
    
        return;
    }
    
    sub data {
    
        use POSIX qw/strftime/;
        my $data = POSIX::strftime( "%F %T", localtime );
        $data =~ s/[\s\-:]/_/gmx;
        return $data;
    
    }
    
    sub send_mail {
    
        my $duracao = sprintf( "%.2f", $time_end );
    
        my %mail = (
            To      => $defs->{mail_to},
            From    => $defs->{mail_from},
            Subject => $defs->{mail_subject},
            Message => "Backup concluído em $duracao segundos\n",
            Smtp    => $defs->{mail_smtp},
        );
    
        use Mail::Sendmail;
        sendmail(%mail) or die $!;
        return;
    
    }
    
    Depois de testares (e testares e testares novamente!) e confirmares que está OK, podes pôr na crontab qualquer coisa como:
    Código:
    30 2 * * * /path/to/script/backup.pl -T 1>/dev/null
    
    para executar o backup todos os dias às 2:30.

    Dúvidas? Sugestões?

    WARNING:
    Nunca é demais avisar que as transferências por FTP não são seguras.
     
    Última edição: 9 de Agosto de 2008
  8. Santo38

    Santo38 Power Member

    Nem todas.. Existem muitas que quando hà problemas os backups tem o condão de ter desaparecido. Acho que os clientes tem de começar a incluir nas suas perguntas iniciais se a empresa a quem contratam os seus planos tem algum plano de backup/disaster recovery.

    O cliente fazer o seu próprio backup acaba por ser mais um layer de protecção para os seus dados.

    Para não ficar totalmente offtopic fica aqui um script para backups automatizados do cPanel que já é usado por muitos clientes:

    Criar um ficheiro fullbackup.php e colocar o seguinte conteudo:

    Código:
    <?php
    
    // PHP script que permite backups automaticos e periodicos oara um servidor/conta remota.
    // Este script contém passwords importantes.  MANTENHA ESTE FICHEIRO SEGURO! (coloque-o no directorio raiz e não no /www/)
    
    // ********* OS SEGUINTES ITEMS NECESSITAM DE SER CONFIGURADOS *********
    
    // Informação necessária para o acesso ao cPanel
    $cpuser = "username"; // Username de login do CPanel
    $cppass = "password"; // Password de login no CPanel
    $domain = "examplo.com"; // nome do dominio onde corre o cpanel
    $skin = "x3"; // Skin que é usada no cPanel
    
    // Informação necessário para o FTP de destino
    $ftpuser = "ftpusername"; // Username da conta FTP destino
    $ftppass = "ftppassword"; // Password da conta FTP destino
    $ftphost = "ftp.examplo.com"; // Nome completo do servidor ou Endereço IP do FTP de destino
    $ftpmode = "ftp"; // Modo FTP ("ftp" para activo, "passiveftp" para passivo)
    
    // Email para notificações
    $notifyemail = "[email protected]"; // Endereço Email para envio dos resultados
    
    // Modo seguro ou inseguro?
    $secure = 0; // Colocar a 1 para SSL (requer suporte de SSL), de outro modo usa o HTTP
    
    // Colocar a 1 para colocar os resultados da página web no log do cron
    $debug = 0;
    
    // *********** NENHUM DOS ITEMS A SEGUIR NECESSITA DE CONFIGURAÇÃO *********
    
    if ($secure) {
       $url = "ssl://".$domain;
       $port = 2083;
    } else {
       $url = $domain;
       $port = 2082;
    }
    
    $socket = fsockopen($url,$port);
    if (!$socket) { echo "Falha a abrir o socket da ligação… Tchau!\n"; exit; }
    
    // codificar a string de autenticação
    $authstr = $cpuser.":".$cppass;
    $pass = base64_encode($authstr);
    
    $params = "dest=$ftpmode&email=$notifyemail&server=$ftphost&user=$ftpuser&pass=$ftppass&submit=Generate Backup";
    
    // Fazer post ao cpanel
    fputs($socket,"POST /frontend/".$skin."/backup/dofullbackup.html?".$params." HTTP/1.0\r\n");
    fputs($socket,"Host: $domain\r\n");
    fputs($socket,"Authorization: Basic $pass\r\n");
    fputs($socket,"Connection: Close\r\n");
    fputs($socket,"\r\n");
    
    // Apanhar a resposta mesmo que nao seja necessario fazer nada com ela.
    while (!feof($socket)) {
      $response = fgets($socket,4096);
      if ($debug) echo $response;
    }
    
    fclose($socket);
    
    ?>
    
    Para programar o script de forma a este correr regularmente, salvar o código em cima num ficheiro backuptotal.php no seu directorio raiz (não o /public_html, que seria muito pouco sensato e seguro), e coloque no CronJobs/Trabalhos Cron uma linha como a que expomos a seguir:

    Código:
    15 2 * * * /usr/local/bin/php /home/youraccount/backuptotal.php
    (Corre todas as noites às 2:15 da manhã)

    ou

    Código:
    15 2 * * 1 /usr/local/bin/php /home/youraccount/fullbackup.php
    (corre todos os domingos 2:15 da manhã)

    O melhor horário para correr estes backups é entre as 2 e as 8 da manhã, de forma a que não cause carga no servidor e porque a essa hora o servidor está menos activo.

    Espero que tenha ajudado e caso tenham alguma questão é só perguntar.

    PS: Este script não é de nossa/minha autoria, mas desconheço quem seja o autor. No entanto todos os créditos para ele.

    Saudações
     
  9. Kayvlim

    Kayvlim Undefined Moderator
    Staff Member

    Santo38, por uma questão de curiosidade, o que quer dizer cada "campo" nisso do cronjob? i.e.,
    Código:
    15 2 * * 1 /usr/local/bin/php /home/youraccount/fullbackup.php
    minuto hora ? ? ? caminho_do_executável parâmetros?

    Em relação ao próprio script, tens ali um echo (if(!$socket)) que talvez fosse melhor transformar num fopen("errors.log", "a+"). Assim, em vez de um echo que ninguém ia ler, existiria um registo de erros, que, passando para um nível seguinte, podia transformar-se num mail() para o responsável pelo site.
     
  10. _freelancer_

    _freelancer_ Power Member

    Kayvlim, sorry pelo off-topic mas como metes esses links todos "pipis" nos nomes das pessoas? :)
     
  11. Kayvlim

    Kayvlim Undefined Moderator
    Staff Member

    Ups, não procurei mesmo por preguiça :x obrigado :x

    Quanto aos nicks, apenas faço copy/paste e uso o editor WYSIWYG, que o Firefox (3, neste caso, mas o 2 também serve) trata do resto :P

    /offtopic
     
  12. _freelancer_

    _freelancer_ Power Member

    Eich, excelente :D obrigado Kayvlim. Nem sabia que o fórum tinha editor WYSIWYG :P
     
  13. Santo38

    Santo38 Power Member

    A ideia é só fazer log se o debug estiver activo. No entanto a tua sugestão é boa. Usar a função numa condição de erro e enviar o resultado por mail ao cliente..

    Tudo o que melhore este script, que diga-se de passagem funciona muito bem, é sempre util.

    Saudações
     
  14. Kayvlim

    Kayvlim Undefined Moderator
    Staff Member

    Já agora, mais uma questão de pormenor:
    De acordo com o que o _freelancer_ colocou, «day of week (0 - 7) (Sunday=0 or 7)»; no entanto, na linha do cronjob que o Santo38 colocou, usou o valor 1 para indicar Domingo. Assim sendo, afinal, qual dos dois está correcto?

    edit - ah, calma, será que o Santo38 queria dizer com "domingo" a madrugada de Domingo para Segunda, sendo que por essa altura já interessa ser o valor para Segunda? :x
     
    Última edição: 9 de Agosto de 2008
  15. anjo2

    anjo2 Power Member

    Ao estar definido um email para o cronjob é enviado esse echo.
     
  16. slack_guy

    slack_guy Power Member

    epa... só agora é que reparei que já existia um tópico sobre este assunto.

    Anyway... fica a minha sugestão mais acima, se não quiseres usar (ou se não tiveres) o cPanel.
     
  17. rpnetwork

    rpnetwork Power Member

    lol... já fiz isso de uma maneira mais fácil, gravei a input do teclado e do rato e depois foi só "reproduzir" e ele fazia automaticamente. é o método mais "fácil" (e pregiçoso :P) de fazer isso
     
  18. Kayvlim

    Kayvlim Undefined Moderator
    Staff Member

    Mas tinhas de fazer isso tu mesmo manualmente, certo?
     
  19. Silver Wolf

    Silver Wolf The Big Bad Wolf
    Staff Member

    Já agora por curiosidade...

    É possivel (para páginas pequenas, claro) que o script envie o backup por e-mail para uma conta pré-definida?
     
  20. Kayvlim

    Kayvlim Undefined Moderator
    Staff Member

    Sim, dado que o backup é gravado no servidor, acho que se pode fazer com que o script no fim envie um e-mail com o gzip anexado :)
     

Partilhar esta Página