Ubuntu PHP 项目备份与恢复实操指南
一 备份范围与策略
二 方法一 纯 PHP 脚本备份与恢复(适合共享主机或无 CLI 场景)
<?php
declare(strict_types=1);
set_time_limit(300);
$backupRoot = '/var/backups/myproj';
$webRoot = '/var/www/myproj';
$dbHost = 'localhost';
$dbUser = 'dbuser';
$dbPass = 'dbpass';
$dbName = 'mydb';
$ts = date('Y-m-d_H-i-s');
$out = "$backupRoot/{$ts}.zip";
$sql = "$backupRoot/{$ts}.sql";
$log = "$backupRoot/backup.log";
function logMsg(string $msg): void {
global $log;
file_put_contents($log, date('c') . " $msg\n", FILE_APPEND | LOCK_EX);
}
// 1) 打包文件
$zip = new ZipArchive();
if ($zip->open($out, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE) {
logMsg("无法创建 ZIP: $out");
exit(1);
}
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($webRoot, FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($iterator as $file) {
if (!$file->isDir()) {
$zip->addFile($file->getRealPath(), substr($file->getRealPath(), strlen($webRoot) + 1));
}
}
$zip->close();
chmod($out, 0600);
logMsg("已打包: $out");
// 2) 导出数据库
$cmd = sprintf(
'mysqldump -h%s -u%s -p%s --single-transaction --routines --triggers --default-character-set=utf8mb4 %s > %s 2>&1',
escapeshellarg($dbHost), escapeshellarg($dbUser), escapeshellarg($dbPass), escapeshellarg($dbName), escapeshellarg($sql)
);
exec($cmd, $outLines, $ret);
if ($ret !== 0) {
logMsg("导出数据库失败: " . implode("\n", $outLines));
exit(1);
}
chmod($sql, 0600);
logMsg("已导出: $sql");
// 3) 可选:加密备份(密钥单独保管)
$keyFile = "$backupRoot/backup.key";
if (!file_exists($keyFile)) {
$key = random_bytes(32);
file_put_contents($keyFile, $key, LOCK_EX);
chmod($keyFile, 0600);
}
$enc = "$out.enc";
$cmd = "openssl enc -aes-256-cbc -salt -in " . escapeshellarg($out) . " -out " . escapeshellarg($enc) . " -pass file:" . escapeshellarg($keyFile) . " 2>&1";
exec($cmd, $outLines, $ret);
if ($ret === 0) {
unlink($out);
logMsg("已加密: $enc");
} else {
logMsg("加密失败: " . implode("\n", $outLines));
}
0 2 * * * /usr/bin/php /var/backups/myproj/backup.phpopenssl enc -d -aes-256-cbc -in backup-2025-12-10_02-00-00.zip.enc -out backup.zip -pass file:/var/backups/myproj/backup.keyunzip backup.zip -d /var/www/myprojmysql -u$dbUser -p$dbPass -e "DROP DATABASE IF EXISTS $dbName; CREATE DATABASE $dbName CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;",再 mysql -u$dbUser -p$dbPass $dbName < backup.sqlSET FOREIGN_KEY_CHECKS=0;,导入后 SET FOREIGN_KEY_CHECKS=1;。三 方法二 命令行与系统工具备份恢复(推荐,性能与可靠性更佳)
mysqldump -u root -p --single-transaction --routines --triggers --default-character-set=utf8mb4 mydb > /backups/mydb_$(date +%F).sqlgzip /backups/mydb_$(date +%F).sqlmysql -u root -p mydb < /backups/mydb_2025-12-10.sql;若压缩:gunzip < /backups/mydb_2025-12-10.sql.gz | mysql -u root -p mydbtar -czvf /backups/files_$(date +%F).tar.gz -C /var/www/myproj .php --ini | grep "Loaded Configuration File" | awk '{print $4}' | xargs -I {} sudo cp {} {}.bak_$(date +%F)sudo tar -czvf /backups/nginx_$(date +%F).tar.gz /etc/nginx /etc/php/$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;')/fpm/php.ini0 2 * * * /usr/bin/mysqldump -u root -p'******' mydb | gzip > /backups/mydb_$(date +\%F).sql.gzrsync -avz /backups/ user@backup.example.com:/backups/ 或 scp /backups/mydb_2025-12-10.sql.gz user@backup.example.com:/backups/sudo apt install timeshift → 图形/命令行向导选择 RSYNC/BTRFS → 设置计划任务 → 需要时选择还原点恢复。四 恢复流程与验证清单
五 安全与运维要点