f77fc725a8
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
71 lines
2.1 KiB
PHP
71 lines
2.1 KiB
PHP
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use App\Models\ActivityLog;
|
|
use Illuminate\Console\Command;
|
|
use Symfony\Component\Process\Process;
|
|
|
|
class BackupDatabaseCommand extends Command
|
|
{
|
|
protected $signature = 'backup:database';
|
|
protected $description = 'Backup database ke storage/app/backups/';
|
|
|
|
public function handle(): int
|
|
{
|
|
$db = config('database.connections.mysql');
|
|
$dir = storage_path('app/backups');
|
|
|
|
if (!is_dir($dir)) {
|
|
mkdir($dir, 0755, true);
|
|
}
|
|
|
|
$filename = 'backup-webgis-' . now()->format('Ymd-His') . '.sql';
|
|
$path = $dir . '/' . $filename;
|
|
|
|
$process = new Process([
|
|
'mysqldump',
|
|
'-h', $db['host'],
|
|
'-P', (string) $db['port'],
|
|
'-u', $db['username'],
|
|
'--single-transaction',
|
|
'--skip-lock-tables',
|
|
'--no-tablespaces',
|
|
'--result-file=' . $path,
|
|
$db['database'],
|
|
], null, ['MYSQL_PWD' => $db['password']]);
|
|
|
|
$process->setTimeout(120);
|
|
$process->run();
|
|
|
|
if (!$process->isSuccessful()) {
|
|
$this->error('Backup gagal: ' . $process->getErrorOutput());
|
|
ActivityLog::create([
|
|
'user_id' => null,
|
|
'user_name' => 'Sistem',
|
|
'action' => 'backup',
|
|
'description' => 'Backup terjadwal GAGAL: ' . $process->getErrorOutput(),
|
|
'ip_address' => '127.0.0.1',
|
|
]);
|
|
return self::FAILURE;
|
|
}
|
|
|
|
// Prune: hapus backup lebih dari 7 file terlama
|
|
$files = glob($dir . '/backup-webgis-*.sql');
|
|
usort($files, fn($a, $b) => filemtime($b) - filemtime($a));
|
|
foreach (array_slice($files, 7) as $old) {
|
|
unlink($old);
|
|
}
|
|
|
|
$this->info("Backup disimpan: {$filename}");
|
|
ActivityLog::create([
|
|
'user_id' => null,
|
|
'user_name' => 'Sistem',
|
|
'action' => 'backup',
|
|
'description' => "Backup terjadwal berhasil: {$filename}",
|
|
'ip_address' => '127.0.0.1',
|
|
]);
|
|
return self::SUCCESS;
|
|
}
|
|
}
|