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
Consideraciones
Vamos a considerar un par de cosas:
- Nuestro sistema se encuentra en un servidor Linux
- La base de datos es MySQL
- 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: