Agregar comando Artisan de Laravel para backups de la base de datos

El objetivo del siguiente contenido es explicar como extender la funcionalidad de artisan agregando un nuevo comando que permita generar periódicamente un respaldo de la base de datos, para esto ultimo haremos uso de las tareas programadas con crontab.

linux+laravel+crontab

linux+laravel+crontab

Consideraciones

Vamos a considerar un par de cosas:

  1. Nuestro sistema se encuentra en un servidor Linux
  2. La base de datos es MySQL
  3. Usaremos Laravel 5 o superior

Artisan

Artisan es la herramienta de lineas de comandos de Laravel la cual nos permite hacer distintas tareas por ejemplo mapear la base de datos, crear modelos, vistas, migrates, limpiar cache, etc..

Para saber mas podemos listar las opciones disponibles, esto lo podemos hacer con la siguiente instrucción:

php artisan list

Agregando Nuevo comando

Lo siguiente seria agregar el nuevo comando db:dump para esto vamos a escribir la siguiente instrucción:

php artisan make:command DbDump

Esto nos va a generar la plantilla de un comando, en el archivo app/Console/Commands/DbDump.php al cual solo le faltaría agregar nuestro código, vamos a empezar re-definir las propiedades:

protected $signature = 'db:dump';

Esta propiedad($signature) define la forma como se debe invocar el comando para ser ejecutado, en este caso estamos diciendo que se mande a llamar como php artisan db:dump.

La siguiente propiedad a modificar es la descripción($description), la cual la definiremos como:

protected $description = 'Respalda la base de datos, comprimiendo los datos en un archivo .gz';

Finalmente vamos a poner un mensaje en la función handle la cual se ejecuta cuando se llama el comando para la cual quedaría como:

public function handle() {
   $this->line('<fg=red;bg=yellow>Soy el nuevo comando db:dump</>');
}

Declarar el comando

Lo siguiente seria declarar el comando nuevo para que este disponible y la próxima vez listemos los comandos de Artisan aparezca, para esto abrimos el archivo app/Console/Kernel.php y modificamos el valor del atributo $commands quedando de la siguiente manera:

protected $commands = [
   \App\Console\Commands\DbDump::class
 ];

Ahora podemos probar que el comando este disponible ejecutando: php artisan list y donde nos debería de aparecer el nuevo comando, el cual para ejecutarlo tendríamos que escribir:

php artisan db:dump

Codificando la función handle

Finalmente vamos a codificar la función handle, la cual dejó aquí:

public function handle() {
	$ds = DIRECTORY_SEPARATOR;
	$host = env('DB_HOST');
	$username = env('DB_USERNAME');
	$password = env('DB_PASSWORD');
	$database = env('DB_DATABASE');
	$path = database_path('backups' . $ds);
	$file = 'bd' . date('_Y-m-d') . '.sql';
	if (!is_dir($path)) {
			mkdir($path, 0755, true);
	}
	$this->line('<fg=cyan>Backup: </><fg=yellow;bg=black>'. $path . $file . '</>');
	# Generamos el comando con mysqldump para exportar los datos
	$command = sprintf(
		'mysqldump --skip-comments --skip-compact --no-create-info'
		. ' --skip-triggers --complete-insert --skip-add-locks'
		. ' --disable-keys --lock-tables --host="%s" --user="%s" '
		, $host, $username
		);
	if (!empty($password)) {
		$command .= sprintf('--password="%s" ', $password);
	}
	$command .= sprintf('%s > "%s"', $database, $path . $file);
	$this->line('<fg=green>CMD: </><fg=yellow;bg=black>'. $command . '</>');
	exec($command, $output, $return);
	if ($return) {
		$this->line('<fg=red;bg=yellow>Error al intentar generar el Backup</>');
		if (file_exists($path . $ds . $file)) {
			unlink($path . $ds . $file);
		}
		return; // error
	}
	// Comprimiendo el archivo:
	// mayor info: https://www.php.net/manual/es/function.gzopen.php
	// Open the gz file (w9 is the highest compression)
	$fileCompress = gzopen ($path . $ds . $file . '.gz', 'w9');
	// Compress the file
	gzwrite ($fileCompress, file_get_contents($path . $ds . $file));
	// Close the gz file and we are done
	gzclose($fileCompress);
	// Generando el esquema
	$path = database_path('backups' . $ds . 'schemas'. $ds);
	$file = 'schema.sql';
	if (!is_dir($path)) {
		mkdir($path, 0755, true);
	}
	# Generamos el comando con mysqldump para exportar la estructura
	$command = sprintf(
		'mysqldump --skip-comments --skip-compact '
		. ' --no-data --host="%s" --user="%s" '
		, $host, $username
		);
	if (!empty($password)) {
		$command .= sprintf('--password="%s" ', $password);
	}
	$command .= sprintf(
		'%s | sed "s/ AUTO_INCREMENT=[0-9]*//g"  > "%s"',
		$database, $path . $file
	);
	$this->line('<fg=magenta>Generando Schema</>');
	exec($command, $output, $return);
	if ($return) {
		$this->line('<fg=red;bg=yellow>Error al intentar generar el Schema</>');
		if (file_exists($path . $ds . $file)) {
			unlink($path . $ds . $file);
		}
		return; // error
	}
}

Declarar la tarea en el crontab

Crontab es un servicio que nos permite agregar tareas que serán ejecutadas periódicamente, lo siguiente que nos faltaría seria declarar una tarea, para acceder al modo edición de reglas tenemos que ejecutar crontab -e la sintaxis de como declarar una regla se describe a continuación:

.--------------- minuto (0-59) 
|  .------------ hora (0-23)
|  |  .--------- día del mes (1-31)
|  |  |  .------ mes (1-12) o jan,feb,mar,apr,may,jun,jul... (meses en inglés)
|  |  |  |  .--- día de la semana (0-6) (domingo=0 ó 7) o
|  |  |  |  |     sun,mon,tue,wed,thu,fri,sat (días en inglés) 
|  |  |  |  |
*  *  *  *  *  comando a ejecutar

En este caso lo pondré a que se ejecute todos los días a las 2am, esto seria con la siguiente declaración de regla:

#.-------------- minuto cero (0-60)
#| .------------ hora dos (0-23)
#| |  .--------- todos los días (1-31)
#| |  |  .------ todos los meses (1-12)
#| |  |  |  .--- Cualquier dia de la semana (0-6)
#| |  |  |  |
#| |  |  |  |
0  2  *  *  *  php ruta_completa_larvel/artisan db:dump

Ejemplo completo

Dejo aquí el código completo del archivo, el cual lo puse en mi github:

https://gist.github.com/fitorec/d7f8003ff1b5501177068f00087cb51a

Enlaces recomendados

Por último les dejó un par de enlaces en donde puedan abundar un poquito mas al respecto:

Tema para phpmyadmin.

Hace un tiempo hice una plantilla para el phpmyadmin ya que no me gusta el que viene por defecto, hoy la comparto:

phpmyadmin theme dark orange

phpmyadmin theme dark orange

¿Como instalar?

Descargue el proyecto descomprima la carpeta y adentro ejecute como superusuario:

 ./install.sh 

Para mayores informes visitar el micrositio oficial del proyecto:

http://fitorec.github.com/phpmyadmin_theme_dark_orange/

DiaSQL generando esquema SQL apartir de un diagrama DIA

DiaSQL Dump es un plugin para el DIA que desarrolle en python bajo licencia GPLv3, que te permite crear un archivos en sintaxis SQL a partir de tu diagramas de base de datos.

Actualmente se encuentra en versión Beta pero ya es completamente funcional,  puedes obtener una copia y el código desde:

DiaSQL Dump nos ayuda a generar archivos con código SQL a partir de tus diagramas de base de datos desarrollados con la herramienta DIA, generando con esto una congruencia entre el modelado de tu base de datos con su definición en SQL, de esta forma si deseas generar algún cambio en el esquema de la base de datos basta con editar el diagrama.

Ejemplo

Previamente debes tener instalado el programa DIA, esto en ubuntu o debian linux lo puedes hacer con la siguiente instrucción.

sudo apt-get install -y dia

La siguiente figura muestra el diseño de un diagrama de base de datos en DIA.

ejemplo diagrama DIA definición de una tabla.

ejemplo diagrama DIA definición de una tabla.

De la figura se puede apreciar que la tabla Personas tiene las siguientes campos:

  • id: int(11), clave primaria, no puede ser nulo.
  • rfc: varchar(20), clave única, no puede ser nulo.
  • nombre: varchar(50), NO es clave, puede ser nulo.

Una ves que realizamos el diagrama nos vamos a archivo y del damos exportar seleccionamos al opción SQL Dump(*.sql) como se muestra en la siguiente imagen:

exportando volcado SQL del diagrama DIA

exportando volcado SQL del diagrama DIA

O bien desde linea de comando con la siguiente sentencia.

#h4x0r mode
dia  -e  ejemplo1.sql   ejemplo1.dia

Donde ejemplo1.dia es nuestro diagrama dia y ejemplos.sql es el archivo que queremos exportar(-e).

El cogido SQL generado por DiaSQL Dump para este ejemplo es:

-- Created by DiaSql-Dump Version 0.01(Beta)
-- Filename: ejemplo1.sql
-- Created: 2010-08-13

-- Personas --
CREATE TABLE IF NOT EXISTS `Personas` (
	`id` int(11) PRIMARY KEY NOT NULL UNIQUE AUTO_INCREMENT,
	`rfc` varchar(20) NOT NULL UNIQUE,
	`nombre` varchar(50)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
-- End SQL-Dump

Nota: esto es solo parte de la documentación que espero levantar próximamente.