person t-kobayashi

Laravelコマンドでデイリーバックアップを作成

calendar_today 2021年06月30日 update 2021年06月30日
Facebook Twitter LINE はてなブックマーク Pocket

今日は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$descriptionphp 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

関連記事

Laravelの記事一覧を見る

Laravelの質問

dosanko が3年前に投稿

質問日時 2021年05月26日

search