今日はLaravelコマンドとcronを使ってデイリーでデータベースのバックアップを取るように設定する手順をまとめます。
artisanコマンドの作成
以下のコマンドで、/app/Console/Commands/DatabaseBackup.php
コマンドのクラスを作成します。
php artisan make:command DatabaseBackUp
下記のように、$signature
, $description
, handle()
を設定します。
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Carbon;
class DatabaseBackUp extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'database:backup';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Backup application database';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$filename = "backup-" . Carbon::now()->format('Y-m-d') . ".sql";
$command = "mysqldump --user=" . config('database.connections.mysql.username') . " --password=" . config('database.connections.mysql.password') . " --host=" . config('database.connections.mysql.host') . " " . config('database.connections.mysql.database') . " > " . storage_path() . "/app/backup/" . $filename;
exec($command, NULL, NULL);
$command2 = "bzip2 " . storage_path() . "/app/backup/" . $filename;
exec($command2, NULL, NULL);
}
}
$signature
と$description
はphp artisan list
コマンドで表示される内容になります。 handle()
メソッドは$signature
で定義したコマンドを実行した際に、実行されるコードです。
handle()
メソッドでは、まずバックアップの保存先となるファイル名を日付情報を元に生成します。デイリーなので、時刻はファイル名の一部にはしていません。
次に、バックアップファイルを作成するコマンドの文字列を生成します。データベースのユーザー名、パスワードは設定ファイルから引っ張ってきます。exec()
関数を使ってコマンドを実行します。
作成したバックアップファイルを圧縮します。そのコマンドが$command2
となります。database:backup
コマンドを実行することで、$command
と$command2
が実行されます。
出力先のフォルダが存在しないとエラーが発生するので、以下のコマンドで、バックアップファイルを保存するフォルダを設定します。
mkdir storage/app/backup
基本的にパーミッションはデフォルトで問題ないが、状況によって調整する必要があるかもしれません。
コマンドをスケジュールする
/app/Console/Kernel.php
の$commands
配列とschedule
関数に上記で作成したコマンドを追加します。
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
'App\Console\Commands\DatabaseBackUp'
];
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('database:backup')->daily();
}
/**
* Register the commands for the application.
*
* @return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}
cronジョブを追加する
今回作成したコマンドを実行したいサーバー上でcrontabを編集し、ジョブを追加します。crontabを編集するページを開くコマンドは以下です。
crontab -e
追加するジョブ
* * * * * cd /path/to/application && php artisan schedule:run >> /dev/null 2>&1
15 06 * * * find /path/to/application/storage/app/backup -maxdepth 1 -type f -name "backup-*.sql.bz2" -mtime +90 -exec rm -f {} \; 2>&1
1つ目のジョブは、毎分/app/Console/Kernel.php
でスケジュールされたジョブがないか確認し、該当するジョブがあればそれを実行します。
2つ目のジョブは、90日以上経過したバックアップファイルをサーバー上から削除します。
cronに毎分チェックする処理をさせる必要はないという方は、Laravelのスケジュール機能を使わずに、ピンポイントでコマンドを実行するという選択肢もあると思います。上記の1行目のジョブを以下のものと入れ替えて、例えば毎日午前3時に直接コマンドを実行するように設定してもいいと思います。
00 03 * * * cd /path/to/application && php artisan database:backup >> /dev/null 2>&1
参考リンク:
https://laravel.com/docs/8.x/artisan#generating-commands
https://medium.com/lockwoodtechnology/automatic-daily-database-backup-with-laravel-6-d329cadd2f1f