Ubuntu下备份PHP项目的实用方案
一 备份范围与准备
二 方案一 Shell脚本一键备份(推荐)
#!/usr/bin/env bash
set -Eeuo pipefail
# 配置
PROJECT_DIR="/var/www/your_project" # 项目根目录
BACKUP_DIR="/opt/backups/php" # 备份存放目录
DB_HOST="localhost"
DB_USER="dbuser"
DB_PASS="dbpass"
DB_NAME="dbname"
RETENTION_DAYS=30
# 创建备份目录
mkdir -p "$BACKUP_DIR"
# 时间前缀
TS=$(date +"%Y%m%d_%H%M%S")
LOG="$BACKUP_DIR/backup_$TS.log"
# 备份数据库(MySQL/MariaDB)
DB_DUMP="$BACKUP_DIR/${DB_NAME}_${TS}.sql.gz"
echo "[$(date)] Dumping database $DB_NAME to $DB_DUMP" >> "$LOG"
mysqldump -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASS" --single-transaction --routines --triggers "$DB_NAME" \
| gzip > "$DB_DUMP" || { echo "DB backup failed"; exit 1; }
# 备份项目文件
CODE_TAR="$BACKUP_DIR/${PROJECT_DIR##*/}_${TS}.tar.gz"
echo "[$(date)] Archiving project $PROJECT_DIR to $CODE_TAR" >> "$LOG"
tar -czf "$CODE_TAR" -C "$(dirname "$PROJECT_DIR")" "$(basename "$PROJECT_DIR")" >> "$LOG" 2>&1
# 清理过期备份
echo "[$(date)] Cleaning up backups older than $RETENTION_DAYS days" >> "$LOG"
find "$BACKUP_DIR" -type f -name "*.sql.gz" -mtime +"$RETENTION_DAYS" -delete
find "$BACKUP_DIR" -type f -name "*.tar.gz" -mtime +"$RETENTION_DAYS" -delete
echo "[$(date)] Backup finished. See $LOG for details."
chmod +x /opt/backups/backup_php.sh
/opt/backups/backup_php.sh
sudo crontab -e
# 添加
0 2 * * * /opt/backups/backup_php.sh
三 方案二 使用PHP脚本实现备份与定时
<?php
declare(strict_types=1);
set_time_limit(300);
$backupDir = '/opt/backups/php';
$projectDir = '/var/www/your_project';
$host = 'localhost'; $user = 'dbuser'; $pass = 'dbpass'; $name = 'dbname';
$retentionDays = 7;
$ts = date('Ymd_His');
$logFile = "$backupDir/backup_$ts.log";
file_put_contents($logFile, "Start at " . date('c') . "\n", FILE_APPEND);
function run(string $cmd, string $label, string $logFile): void {
exec($cmd . ' 2>&1', $out, $code);
file_put_contents($logFile, "[$label] exit=$code\n" . implode("\n", $out) . "\n", FILE_APPEND);
if ($code !== 0) exit(1);
}
// 数据库导出
$sqlFile = "$backupDir/{$name}_$ts.sql.gz";
run("mysqldump -h$host -u$user -p$pass --single-transaction --routines --triggers $name | gzip > '$sqlFile'", 'DB Dump', $logFile);
// 代码打包
$tarFile = "$backupDir/" . basename($projectDir) . "_$ts.tar.gz";
run("tar -czf '$tarFile' -C '" . dirname($projectDir) . "' '" . basename($projectDir) . "'", 'Code Archive', $logFile);
// 清理旧备份
run("find '$backupDir' -type f -name '*.sql.gz' -mtime +$retentionDays -delete", 'Cleanup SQL', $logFile);
run("find '$backupDir' -type f -name '*.tar.gz' -mtime +$retentionDays -delete", 'Cleanup Code', $logFile);
file_put_contents($logFile, "Finished at " . date('c') . "\n", FILE_APPEND);
echo "OK: $sqlFile, $tarFile\n";
sudo crontab -e
# 每天 02:00 用 CLI 执行
0 2 * * * /usr/bin/php /opt/backups/backup.php
四 备份Web与PHP配置及恢复步骤
php --ini | grep "Loaded Configuration File" | awk '{print $4}'sudo cp /etc/php/8.1/cli/php.ini /etc/php/8.1/cli/php.ini.bak/etc/nginx/nginx.conf、/etc/nginx/sites-available/your-site/etc/apache2/apache2.conf、/etc/apache2/sites-available/your-site.conf.env、.htaccess、自定义配置等tar -xzf your_project_YYYYMMDD_HHMMSS.tar.gz -C /var/www/gunzip < your_db_YYYYMMDD_HHMMSS.sql.gz | mysql -h localhost -u dbuser -p dbnamesudo systemctl reload nginx 或 sudo systemctl reload apache2