Initial commit
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
if (PHP_SAPI !== 'cli') {
|
||||
http_response_code(404);
|
||||
exit;
|
||||
}
|
||||
|
||||
$config = require dirname(__DIR__) . '/config.php';
|
||||
if (empty($config['installed']) || ($config['db']['driver'] ?? '') !== 'mysql') {
|
||||
fwrite(STDERR, "系统尚未安装或未使用 MySQL。\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$targetDirectory = $argv[1] ?? '/var/backups/tanwan';
|
||||
if (!str_starts_with($targetDirectory, '/') || in_array(rtrim($targetDirectory, '/'), ['', '/', dirname(__DIR__)], true)) {
|
||||
fwrite(STDERR, "备份目录必须是 Web 根目录之外的绝对路径。\n");
|
||||
exit(1);
|
||||
}
|
||||
$webRoot = realpath(dirname(__DIR__));
|
||||
$resolvedParent = realpath(dirname($targetDirectory));
|
||||
if ($webRoot !== false && $resolvedParent !== false && str_starts_with($resolvedParent . '/', $webRoot . '/')) {
|
||||
fwrite(STDERR, "禁止将备份写入 Web 根目录。\n");
|
||||
exit(1);
|
||||
}
|
||||
if (!is_dir($targetDirectory) && !mkdir($targetDirectory, 0700, true) && !is_dir($targetDirectory)) {
|
||||
fwrite(STDERR, "无法创建备份目录。\n");
|
||||
exit(1);
|
||||
}
|
||||
chmod($targetDirectory, 0700);
|
||||
|
||||
$db = $config['db'];
|
||||
$filename = rtrim($targetDirectory, '/') . '/tanwan-' . date('Ymd-His') . '.sql';
|
||||
$command = ['/usr/bin/mariadb-dump', '--single-transaction', '--quick', '--skip-lock-tables', '--default-character-set=utf8mb4'];
|
||||
if (in_array((string) $db['host'], ['localhost', 'localhost.localdomain'], true)) {
|
||||
$command[] = '--protocol=socket';
|
||||
} else {
|
||||
$command[] = '--host=' . $db['host'];
|
||||
$command[] = '--port=' . $db['port'];
|
||||
}
|
||||
$command[] = '--user=' . $db['username'];
|
||||
$command[] = (string) $db['database'];
|
||||
$descriptors = [0 => ['file', '/dev/null', 'rb'], 1 => ['file', $filename, 'wb'], 2 => ['pipe', 'w']];
|
||||
$environment = array_merge(getenv(), ['MYSQL_PWD' => (string) $db['password']]);
|
||||
$process = proc_open($command, $descriptors, $pipes, null, $environment, ['bypass_shell' => true]);
|
||||
if (!is_resource($process)) {
|
||||
fwrite(STDERR, "无法启动数据库备份。\n");
|
||||
exit(1);
|
||||
}
|
||||
$errors = stream_get_contents($pipes[2]);
|
||||
fclose($pipes[2]);
|
||||
$exitCode = proc_close($process);
|
||||
if ($exitCode !== 0) {
|
||||
@unlink($filename);
|
||||
fwrite(STDERR, "备份失败:" . trim($errors) . "\n");
|
||||
exit(1);
|
||||
}
|
||||
chmod($filename, 0600);
|
||||
|
||||
$cutoff = time() - 14 * 86400;
|
||||
foreach (glob(rtrim($targetDirectory, '/') . '/tanwan-*.sql') ?: [] as $oldBackup) {
|
||||
if (is_file($oldBackup) && filemtime($oldBackup) < $cutoff) unlink($oldBackup);
|
||||
}
|
||||
fwrite(STDOUT, $filename . "\n");
|
||||
Reference in New Issue
Block a user