Realizando backup automático do banco em servidor de hospedagem linux com PHP

Publicado em 15/05/2018 | (0) comentários


Servidores de hospedagem Linux possuem, geralmente, um painel de controle CPANEL para administração da hospedagem. Apesar da rotina de backup automático do servidor, que é executada automaticamente e semanalmente pelo serviço contratado, a mesma não garante a recuperação e segurança dos dados, assim como não garante a restauração caso alguma invasão ou problema tenha ocorrido no servidor.

É muito aconselhado que você realize periodicamente o backup do seu banco de dados e mantenha o seu código fonte seguro com controle de versão. Neste tutorial você aprenderá a garantir a segurança de seu banco de dados MySQL em um servidor Linux utilizando um simples código PHP e uma tarefa CRON.

Código PHP para realizar o backup

O código abaixo realiza uma cópia completa de seu banco de dados, gera um arquivo SQL em um diretório no servidor e em seguida compacta ele para economizar espaço. 

<?php

//define os parâmetros de conexão do banco
$dbname = ""; //nome do banco
$dbhost = ""; //geralmente localhost
$dbuser = ""; //usuário do banco
$dbpass = ""; //senha do banco

//define o nome do arquivo e onde será salvo o backup
$filename = date('Ymdhms').$dbname;
$path = "../bkp/";

//cria a pasta onde os backups serão salvos caso ela não exista
if(!is_dir($path)){
	mkdir($path, 0751); //cria a pasta
}

// conectando ao banco
$con = mysqli_connect($dbhost,$dbuser,$dbpass,$dbname) or die(mysql_error());

// gerando um arquivo sql. Como?
// a função fopen, abre um arquivo, que no meu caso, será chamado como: nomedobanco.sql
// note que eu estou concatenando dinamicamente o nome do banco com a extensão .sql.
$back = fopen($path.$filename.".sql","w");

// aqui, listo todas as tabelas daquele banco selecionado acima
$query = mysqli_query($con,"SHOW TABLES");
while($dados = mysqli_fetch_row($query))
{
    $res[] = $dados[0];
}

//Em seguida, vamos, verificar quais são as tabelas daquela base, lista-las, e em um laço for, vamos mostrar cada uma delas, e resgatar as funções descriação da tabela, para serem gravadas no arquivo sql mais adiante.
// resgato cada uma das tabelas, num loop
foreach ($res as $key => $value) {

	$table = $value;
	// usando a função SHOW CREATE TABLE do mysql, exibo as funções de criação da tabela,
	// exportando também isso, para nosso arquivo de backup
	$res2 = mysqli_query($con, "SHOW CREATE TABLE $table");
	// digo que o comando acima deve ser feito em cada uma das tabelas
		while ( $lin = mysqli_fetch_row($res2)){

		// instruções que serão gravadas no arquivo de backup
		fwrite($back,"\n#\n# Criacao da Tabela : $table\n#\n\n");
		fwrite($back,"$lin[1] ;\n\n#\n# Dados a serem incluidos na tabela\n#\n\n");

		//Teremos então de pegar os dados que estão dentro de cada campo de cada tabela, e abri-los também para serem gravados no nosso arquivo de backup.
		// seleciono todos os dados de cada tabela pega no while acima
		// e depois gravo no arquivo .sql, usando comandos de insert
		$res3 = mysqli_query($con, "SELECT * FROM $table");
		while($r=mysqli_fetch_row($res3)){
			$sql="INSERT INTO $table VALUES (";
			//Agora vamos pegar cada dado do campo de cada tabela, e executar tarefas como, quebra de linha, substituição de aspas, espaços em branco, etc. Deixando o arquivo confiável para ser importado em outro banco de dados.
			// este laço irá executar os comandos acima, gerando o arquivo ao final,
			// na função fwrite (gravar um arquivo)
			// este laço também irá substituir as aspas duplas, simples e campos vazios
			// por aspas simples, colocando espaços e quebras de linha ao final de cada registro, etc
			// deixando o arquivo pronto para ser importado em outro banco

			for($j=0; $j<mysqli_num_fields($res3);$j++)
			{
				if(!isset($r[$j]))
				$sql .= " \"\",";
				elseif($r[$j] != "")
				$sql .= " \"".addslashes($r[$j])."\",";
				else
				$sql .= " \"\",";
			}
			$sql = preg_replace("~,$~", "", $sql);
			$sql .= ");\n";
			fwrite($back,$sql);
		}
	}

}

//E finalmente, vamos fechar (internamente, no servidor) o arquivo que geramos, dando um nome para o mesmo, e gerando o arquivo que será então disponibilizado para download.

// fechar o arquivo que foi gravado
fclose($back);

// gerando o arquivo para download, com o nome do banco e extensão sql.
$arquivo = $path.$filename.".sql";

ob_start();

//zipa o arquivo
$zip = new ZipArchive(); 
if( $zip->open( $path.$filename.".zip" , ZipArchive::CREATE )  === true){
    $zip->addFile( $path.$arquivo ) ;
    $zip->close();
}

//deleta o arquivo .sql e mantém somente o zipado
unlink($arquivo);

?>

Criando uma tarefa para executar o backup automático

A tarefa CRON do linux é semelhante ao Tarefas agendadas do Windows Microsoft. Você poderá agendar um dia, horário e periodicidade que um comando é executado automaticamente. Acesse o CPANEL e procure por TRABALHOS CRON (ou "cron", ou "Tarefas cron").


Será mostrada uma janela onde deverá ser agendada a execução de um comando. 

No meu caso deixei programado para que o backup seja realizado todos os dias as 4 horas da manhã, pois considero um bom horário de maneira que este processo não sobrecarregue o servidor enquanto ele está sendo utilizado pelos usuários.

Portanto o agendamento ficou assim:

Minuto: 0 | Hora: 4 | Dia: * | Mês: * | Dia da semana: *

O comando é o caminho onde ficou hospedado o arquivo PHP que realiza o backup com o inicializador php e o parâmetro -f do shell. O caminho deve ser baseado na raiz do servidor:

Exemplo: 

php -f public_html/seu_site/cron/backup.php