shell实战学习——具体的shell脚本示例

目录

文件批量重命名

系统资源管理

日志分析统计

定时任务管理

数据库查询与操作

文件的备份与压缩

自动化部署脚本

简单的用户管理脚本

系统监控与报警

数据分析与报告生成


文件批量重命名

题目:编写一个Shell脚本,实现将当前目录下所有以 .jpg 结尾的文件批量重命名,要求在每个文件名前加上指定的前缀,并输出重命名成功的文件数。

提示:

  1. 使用循环遍历当前目录下的所有 .jpg 文件。
  2. 对每个文件生成新的文件名,形如 prefix_filename.jpg
  3. 使用 mv 命令进行文件重命名操作。
  4. 最后输出成功重命名的文件数。
# 示例答案一(不输出文件数)
#!/bin/bash

# 获取当前目录下所有以 .jpg 结尾的文件
for file in *.jpg; do        # for in ;do done循环,分号或换行啊;注意规范缩进,多注释
    # 生成新的文件名
    newname="prefix_$file"       # 一定要记住$使用变量
    # 重命名文件
    mv "$file" "$newname"        
    # 是mv可不是rm,想想两者分别啥意思,回忆一下选项
    # mv是移动文件文件夹,但是如果目标文件不在的话,则“改名”效果
done

echo "Files renamed successfully."
# 示例答案二(输出文件数)
#!/bin/bash

count=0

# 获取当前目录下所有以 .jpg 结尾的文件
for file in *.jpg; do
    # 生成新的文件名
    newname="prefix_$file"
    # 重命名文件
    mv "$file" "$newname"
    # $?是一个特殊变量,存储了上一个命令的退出状态码。
    # 退出状态码为0表示命令成功执行,如果不为0则表示命令执行失败。
    if [[ $? -eq 0 ]]; then
        echo "Renamed $file to $newname"
        ((count++))
    else
        echo "Failed to rename $file"
    fi
    # 以上六行也可以写为
    # mv "$file" "$newname"&&((count++))

done

echo "Files renamed successfully. Total files renamed: $count"

系统资源管理

题目:编写一个Shell脚本,监控并输出当前系统的CPU和内存使用情况

具体要求如下:

  1. 使用 top 命令获取当前系统的CPU使用情况,并输出为百分比。
  2. 使用 free 命令获取当前系统的内存使用情况,并输出为百分比。
  3. 最后输出CPU和内存使用情况的百分比值。

提示:

  • 可以使用 grepawk 命令来提取和计算所需的数据。
  • 使用 printf 格式化输出结果。
#!/bin/bash

# 获取当前系统的CPU和内存使用情况
cpu_usage=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}')
mem_usage=$(free | awk '/Mem/{printf("%.2f"), $3/$2 * 100}')

echo "CPU Usage: $cpu_usage%"
echo "Memory Usage: $mem_usage%"

top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}

top -bn1top命令实时显示系统信息(进程CPU内存...)-b批处理 n1运行一次退出
grep "Cpu(s)"

top 命令的输出中提取包含CPU使用情况的行。

grep搜索文本  Cpu(s)搜索模式

sed "s/.*, *\([0-9.]*\)%* id.*/\1/"

提取出CPU空闲百分比。

awk '{print 100 - $1}

计算并打印CPU使用百分比。

计算100减去sed中打印的值$1(表示第一列),并打印结果

 free | awk '/Mem/{printf("%.2f"), $3/$2 * 100}'

free

free命令显示系统内存的使用情况,包括总内存、已用内存、空闲内存等。

awk '/Mem/{...}'对包含 Mem 的行进行处理。
{printf("%.2f"), $3/$2 * 100}

计算已用内存占总内存的百分比,并格式化为保留两位小数。

$3:表示第三列(即已用内存)。

$2:表示第二列(即总内存)。

问题:

  1. 该脚本是如何计算CPU使用情况的?
  2. sedawk 命令在脚本中分别起到了什么作用?
  3. 该脚本是如何计算内存使用情况的?
  4. 请解释 free 命令输出的内存信息是如何被处理并计算成百分比的。

答案:

  1. 该脚本通过 top 命令获取CPU空闲百分比,然后用100减去该值来计算CPU使用百分比。
  2. sed 命令用于从 top 命令的输出中提取出CPU空闲百分比,awk 命令则用于计算使用百分比(100 - 空闲百分比)。
  3. 该脚本通过 free 命令获取总内存和已用内存,然后计算内存使用百分比(已用内存 / 总内存 * 100)。
  4. free 命令输出内存信息,awk 命令从中提取出总内存和已用内存,并计算成百分比输出。

日志分析统计

题目:编写一个Shell脚本,统计Web服务器日志文件中不同IP地址的访问次数,并按访问次数从高到低排序输出。要求脚本读取一个指定的日志文件,并输出格式化的结果。

要求:

  1. 脚本读取指定的日志文件(假设文件名为 access.log)。
  2. 提取日志文件中的IP地址。
  3. 统计每个IP地址的访问次数。
  4. 按访问次数从高到低排序。
  5. 格式化输出结果,显示IP地址及其对应的访问次数。
#!/bin/bash

# 统计日志中不同IP的访问次数
logfile="access.log"  #指定日志文件名

echo "IP Address   Requests"
echo "====================="
awk '{print $1}' "$logfile" | sort | uniq -c | sort -nr | while read count ip; do
    printf "%-15s %7d\n" "$ip" $count
done

# awk '{print $1}' "$logfile" 提取日志文件第一列;
# 加上双引号可以避免文件名中出现空格或特殊字符的影响(不加会将其解释为多个参数)

# sort:对IP地址进行排序。
# uniq -c:统计每个唯一IP地址的出现次数。
# sort -nr:按统计次数从高到低排序。-n按数值顺序排序;-r按逆序排序

# while read count ip; do ... done:读取排序后的统计结果,并格式化输出。
# count 和 ip 是在 read 命令中定义的变量。它们的作用域仅限于 while 循环体内。

# printf "%-15s %7d\n" "$ip" $count:格式化输出IP地址及其访问次数。
# "%-15s %7d\n":这是格式字符串,指定了输出格式。
    # %-15s:表示一个左对齐的字符串,占15个字符宽度。
        # %s:表示格式化输出为字符串。
        # -:表示左对齐(默认是右对齐)。
        # 15:表示字段宽度为15个字符。
    # %7d:表示一个右对齐的整数,占7个字符宽度。
        # %d:表示格式化输出为整数。
        # 7:表示字段宽度为7个字符。
  • 访问日志(Access Logs)

    • 默认位置/var/log/apache2/access.log/var/log/httpd/access_log
    • 描述:记录所有访问服务器的请求信息,包括访问者的IP地址、访问时间、请求的URL、HTTP状态码等。

定时任务管理

题目:编写一个改进版本的Shell脚本,以完成每天定时备份数据库的任务,并加入以下功能:

  1. 备份文件管理:每次备份前,检查备份目录是否存在,不存在则创建。检查当天的备份文件是否已存在,如果存在则给出警告或覆盖旧文件。

  2. 日志记录:将备份操作的结果和详细信息记录到日志文件中,包括备份成功与否、备份文件路径等。

  3. 错误处理:在发生错误时能够输出详细的错误信息,并记录到日志中。

  4. 可配置性:将备份目录、数据库连接信息等参数作为脚本的输入参数或配置项,增强脚本的灵活性和通用性。

要求和提示:

  1. 使用Shell脚本语言编写,确保脚本能够在Linux环境下运行。
  2. 脚本应能自动创建备份目录,检查并管理备份文件。
  3. 使用合适的日期格式化来生成备份文件名,避免重复备份同一天的文件。
  4. 考虑在日志文件中记录脚本运行的详细过程,包括备份成功或失败的信息。
  5. 使用条件判断结构来处理备份成功或失败的情况,并输出相应的信息。
  6. 考虑使用函数来组织和模块化代码,提高脚本的可读性和维护性。
#基础版

#!/bin/bash

# 每天定时备份数据库
backup_dir="/path/to/backup"
backup_file="$backup_dir/db_backup_$(date +%Y%m%d).sql"
# date +格式化字符串

# 使用 pg_dump 备份数据库
pg_dump -h localhost -U username dbname > "$backup_file"
# pg_dump 是 PostgreSQL 数据库自带的一个备份工具
# 用于将 PostgreSQL 数据库中的数据和对象导出到一个文件中,以便后续进行恢复或迁移。
    # -h localhost:指定数据库服务器的主机名或IP地址。
    # -U username:指定连接数据库的用户名。
    # dbname:要备份的数据库名。
    # > "$backup_file":将备份内容输出到 backup_file 文件中。

if [[ $? -eq 0 ]]; then
    echo "Database backup successfully created: $backup_file"
else
    echo "Error creating database backup."
fi
# 改进版

#!/bin/bash

# 备份目录和文件
backup_dir="/path/to/backup"
backup_file="$backup_dir/db_backup_$(date +%Y%m%d).sql"
log_file="/path/to/backup_log.txt"

# 创建备份目录
if [[ ! -d "$backup_dir" ]]; then
    mkdir -p "$backup_dir"
    echo "Created backup directory: $backup_dir" >> "$log_file"
fi
# ! 表示逻辑非,-d "$backup_dir" 表示检查 $backup_dir 是否存在并且是一个目录。


# 检查当天备份文件是否存在
if [[ -f "$backup_file" ]]; then   
    echo "Warning: Backup file already exists for today." >> "$log_file"
fi
#-f 只能用于检查文件是否存在并且是一个常规文件,-d(检查是否是目录)-e(检查是否存在)


# 使用 pg_dump 备份数据库
pg_dump -h localhost -U username dbname > "$backup_file" 2>> "$log_file"

# 检查备份是否成功
if [[ $? -eq 0 ]]; then
    echo "$(date): Database backup successfully created: $backup_file" >> "$log_file"
else
    echo "$(date): Error creating database backup." >> "$log_file"
fi

# 结束日志记录
echo "Backup process completed." >> "$log_file"

数据库查询与操作

题目:查询并显示数据库中所有状态为 'active' 的用户信息。向数据库中插入一个新用户记录。

#!/bin/bash

# 查询并显示数据库中的活跃用户
query="SELECT * FROM users WHERE status='active';"
psql -h localhost -U username dbname -c "$query"
# -h hostname:指定连接的主机名。
# -U username:指定连接的用户名。
# dbname:指定连接的数据库名。

# 向数据库插入新用户
new_user="INSERT INTO users (name, email, status) VALUES ('John Doe', 'john.doe@example.com', 'active');"
psql -h localhost -U username dbname -c "$new_user"

文件的备份与压缩

题目:编写一个Shell脚本,实现以下操作:

  1. 备份指定目录下的文件。
  2. 将备份文件压缩为 tar.gz 格式。
#!/bin/bash

# 备份指定目录下的文件,并压缩为tar.gz格式
backup_dir="/path/to/data"
backup_file="backup_$(date +%Y%m%d).tar.gz" #备份文件名,使用当前日期作为文件名的一部分

#使用 tar 命令将指定目录 $backup_dir 下的文件打包并压缩为 tar.gz 格式的文件 $backup_file
tar -czf "$backup_file" "$backup_dir"
# -c 创建压缩文件
# -z gzip模式
# -f 创建的文件

# 检查备份和压缩是否成功
if [[ $? -eq 0 ]]; then  #退出状态码是否为0
    echo "Backup successfully created: $backup_file"
else
    echo "Error creating backup."
fi

自动化部署脚本

题目:编写一个Shell脚本,实现以下操作:

  1. 将本地的Web应用程序文件(如 app.war)部署到远程服务器。
  2. 在远程服务器上解压部署文件,并重启应用服务器(假设使用 systemctl 重启 tomcat)。
#!/bin/bash

# 自动化部署Web应用程序到远程服务器
remote_host="username@hostname"   # 远程服务器的用户名和主机名。
remote_dir="/path/to/deploy"    # 远程服务器上的目标部署目录。
local_war="app.war"    # 本地的Web应用程序文件

echo "Deploying application to $remote_host:$remote_dir ..."
# 使用 scp 命令将本地的应用程序文件复制到远程服务器的指定目录。
scp "$local_war" "$remote_host:$remote_dir"

# 使用 ssh 连接到远程服务器,执行在远程服务器上解压应用程序文件并重启 tomcat 服务器的命令序列。
ssh "$remote_host" "cd $remote_dir && tar -xf $local_war && systemctl restart tomcat"

# 检查部署操作的执行状态
if [[ $? -eq 0 ]]; then
    echo "Deployment successful."
else
    echo "Deployment failed."
fi

简单的用户管理脚本

题目:编写一个Shell脚本,实现简单的用户管理功能,包括添加和删除用户操作。

要求:

  1. 功能选择:脚本首先显示功能菜单;提示用户输入选择(12
  2. 添加用户操作:如果用户选择 1,提示用户输入要添加的用户名。
  3. 删除用户操作:如果用户选择 2,提示用户输入要删除的用户名。
  4. 错误处理:对于无效的选择(不是 12),输出提示信息并结束脚本运行。
#!/bin/bash

# 简单的用户管理脚本,添加和删除用户
echo "Choose an action:"
echo "1. Add User"
echo "2. Delete User"
read choice

case $choice in
    1)
        echo "Enter username to add:"
        read username
        useradd "$username"
        if [[ $? -eq 0 ]]; then
            echo "User $username added successfully."
        else
            echo "Failed to add user."
        fi
        ;;
    2)
        echo "Enter username to delete:"
        read username
        userdel "$username"
        if [[ $? -eq 0 ]]; then
            echo "User $username deleted successfully."
        else
            echo "Failed to delete user."
        fi
        ;;
    *)
        echo "Invalid choice."
        ;;
esac
注意权限

系统监控与报警

题目:编写一个Shell脚本,实现以下操作:

  1. 监控系统资源使用命令获取当前系统的CPU使用情况。如果CPU使用率超过指定阈值(例如90%),则触发邮件报警。

  2. 发送邮件报警如果CPU使用率超过阈值,使用 mail 命令向指定的管理员邮箱发送报警邮件。邮件主题为 "High CPU Usage Alert",内容包含当前CPU使用率信息。

要求:

  1. 获取CPU使用率使用 top 命令结合 grepsedawk 等工具获取CPU使用率,并进行计算。

  2. 报警条件如果计算得到的CPU使用率超过预设的阈值(例如90%),则触发报警。

  3. 发送邮件使用 mail 命令发送邮件给管理员,包括当前CPU使用率信息。

#!/bin/bash

# 监控系统资源使用情况,并发送邮件报警
threshold=90  # 设置CPU使用率的阈值为90%。
cpu_usage=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}')
# 第二题中出现。grep、sed 和 awk 结合,从输出中提取并计算CPU空闲百分比。


# 使用 bc 计算判断CPU使用率是否超过阈值。
if [[ $(echo "$cpu_usage > $threshold" | bc -l) -eq 1 ]]; then
    echo "High CPU usage detected: $cpu_usage%"
    # 如果CPU使用率超过阈值,使用 mail 命令发送邮件给 admin@example.com。
    mail -s "High CPU Usage Alert" admin@example.com <<< "Current CPU Usage: $cpu_usage%"
else
    echo "CPU usage within normal range: $cpu_usage%"
fi

数据分析与报告生成

题目:编写一个Shell脚本,统计指定日志文件中访问量最高的页面(URL)。

要求:

  1. 日志文件:日志文件路径为 access.log
  2. 统计逻辑:从日志文件中提取页面(URL)信息,一般在日志中为第7列;使用 awk 命令提取页面信息,并结合 sortuniq -csort -nrhead -n 10 实现统计;输出按访问量降序排列的前10个页面及其访问次数。
#!/bin/bash

# 统计日志中访问量最高的页面
logfile="access.log"

echo "Top 10 Pages by Access Count:"
echo "============================="


awk '{print $7}' "$logfile" | sort | uniq -c | sort -nr | head -n 10 | while read count page; do
    printf "%-10s %s\n" "$count" "$page"    #输出格式要求
done

# awk '{print $7}' "$logfile":提取日志文件中第7列的页面信息(假设页面URL在第7列)。
# sort:排序页面信息。
# uniq -c:统计每个页面出现的次数。
# sort -nr:按访问次数逆序排序。
# head -n 10:取前10条结果。

# 变量 count 存储访问次数
# 变量 page 存储页面URL。

未完待续,2024/7/18留

Shell脚本高级编程教程,希望对你有所帮助。 Example 10-23. Using continue N in an actual task: 1 # Albert Reiner gives an example of how to use "continue N": 2 # --------------------------------------------------------- 3 4 # Suppose I have a large number of jobs that need to be run, with 5 #+ any data that is to be treated in files of a given name pattern in a 6 #+ directory. There are several machines that access this directory, and 7 #+ I want to distribute the work over these different boxen. Then I 8 #+ usually nohup something like the following on every box: 9 10 while true 11 do 12 for n in .iso.* 13 do 14 [ "$n" = ".iso.opts" ] && continue 15 beta=${n#.iso.} 16 [ -r .Iso.$beta ] && continue 17 [ -r .lock.$beta ] && sleep 10 && continue 18 lockfile -r0 .lock.$beta || continue 19 echo -n "$beta: " `date` 20 run-isotherm $beta 21 date 22 ls -alF .Iso.$beta 23 [ -r .Iso.$beta ] && rm -f .lock.$beta 24 continue 2 25 done 26 break 27 done 28 29 # The details, in particular the sleep N, are particular to my 30 #+ application, but the general pattern is: 31 32 while true 33 do 34 for job in {pattern} 35 do 36 {job already done or running} && continue 37 {mark job as running, do job, mark job as done} 38 continue 2 39 done 40 break # Or something like `sleep 600' to avoid termination. 41 done 42 43 # This way the script will stop only when there are no more jobs to do 44 #+ (including jobs that were added during runtime). Through the use 45 #+ of appropriate lockfiles it can be run on several machines 46 #+ concurrently without duplication of calculations [which run a couple 47 #+ of hours in my case, so I really want to avoid this]. Also, as search 48 #+ always starts again from the beginning, one can encode priorities in 49 #+ the file names. Of course, one could also do this without `continue 2', 50 #+ but then one would have to actually check whether or not some job 51 #+ was done (so that we should immediately look for the next job) or not 52 #+ (in which case we terminate or sleep for a long time before checking 53 #+ for a new job).
<think>我们正在处理一个MySQL增量备份系统的搭建,要求包括自动备份、过期删除(保留7天)和可恢复验证。根据引用[1][2][3][4],我们选择使用Percona XtraBackup(因为它是开源的物理备份工具,适合大数据量,支持InnoDB引擎的增量备份,并且可以保证备份期间的一致性)。注意:引用中提到的`mysqlbackup`实际上是Percona XtraBackup中的`xtrabackup`命令,在引用[2]中使用了`mysqlbackup`作为命令,但实际工具名为`xtrabackup`。因此,在下面的脚本中,我们将使用`xtrabackup`命令。 ### 步骤1: 安装Percona XtraBackup 在Linux系统上安装Percona XtraBackup(以Ubuntu为例): ```bash # 下载Percona仓库 wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb sudo dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb sudo percona-release enable-only tools release sudo apt update sudo apt install percona-xtrabackup-80 -y # 根据MySQL版本选择,这里以8.0为例 ``` ### 步骤2: 配置备份目录和权限 ```bash sudo mkdir -p /opt/mysql_backup/{full,inc,binlog} sudo chown -R mysql:mysql /opt/mysql_backup # 如果MySQL以mysql用户运行,确保权限正确 sudo chmod -R 770 /opt/mysql_backup ``` ### 步骤3: 编写自动备份脚本 创建备份脚本`/opt/mysql_backup/backup.sh`,并赋予执行权限: ```bash sudo touch /opt/mysql_backup/backup.sh sudo chmod +x /opt/mysql_backup/backup.sh ``` 脚本内容如下: ```bash #!/bin/bash # 定义变量 BACKUP_DIR="/opt/mysql_backup" FULL_BACKUP_DIR="$BACKUP_DIR/full" INC_BACKUP_DIR="$BACKUP_DIR/inc" BINLOG_DIR="$BACKUP_DIR/binlog" DATE=$(date +%Y%m%d) LOG_FILE="$BACKUP_DIR/backup.log" MYSQL_USER="root" MYSQL_PASSWORD="your_password" # 替换为实际密码,建议使用配置文件或环境变量 # 检查全量备份目录是否存在,不存在则创建 mkdir -p $FULL_BACKUP_DIR mkdir -p $INC_BACKUP_DIR mkdir -p $BINLOG_DIR # 记录开始时间 echo "Backup started at $(date)" >> $LOG_FILE # 判断是否为周日(0代表周日),执行全量备份 if [ $(date +%w) -eq 0 ]; then echo "Starting full backup..." >> $LOG_FILE xtrabackup --backup --user=$MYSQL_USER --password=$MYSQL_PASSWORD --target-dir=$FULL_BACKUP_DIR/full_$DATE # 准备全量备份(不恢复,仅应用日志) xtrabackup --prepare --apply-log-only --target-dir=$FULL_BACKUP_DIR/full_$DATE >> $LOG_FILE 2>&1 # 备份完成后,记录当前binlog位置(用于增量备份的起始点) cp $FULL_BACKUP_DIR/full_$DATE/xtrabackup_binlog_info $BACKUP_DIR/last_binlog_info echo "Full backup completed at $(date)" >> $LOG_FILE else # 增量备份 echo "Starting incremental backup..." >> $LOG_FILE # 获取上一次备份的目录(最近的全量或增量) LAST_BACKUP=$(ls -d $FULL_BACKUP_DIR/full_* $INC_BACKUP_DIR/inc_* 2>/dev/null | sort -r | head -1) if [ -z "$LAST_BACKUP" ]; then echo "Error: No base backup found for incremental backup. Exiting." >> $LOG_FILE exit 1 fi # 执行增量备份 xtrabackup --backup --user=$MYSQL_USER --password=$MYSQL_PASSWORD --target-dir=$INC_BACKUP_DIR/inc_$DATE --incremental-basedir=$LAST_BACKUP # 准备增量备份(应用日志到增量备份,但不合并到全量) xtrabackup --prepare --apply-log-only --target-dir=$LAST_BACKUP --incremental-dir=$INC_BACKUP_DIR/inc_$DATE >> $LOG_FILE 2>&1 echo "Incremental backup completed at $(date)" >> $LOG_FILE fi # 步骤4: 删除7天前的备份(过期删除) # 删除7天前的全量备份 find $FULL_BACKUP_DIR -type d -name "full_*" -mtime +7 -exec rm -rf {} \; >> $LOG_FILE 2>&1 # 删除7天前的增量备份 find $INC_BACKUP_DIR -type d -name "inc_*" -mtime +7 -exec rm -rf {} \; >> $LOG_FILE 2>&1 echo "Old backups cleanup completed at $(date)" >> $LOG_FILE # 步骤5: 备份binlog(可选,根据需求) # 注意:增量备份依赖于binlog,建议开启binlog并定期备份 ``` ### 步骤4: 配置cron定时任务 每天凌晨2点执行备份: ```bash sudo crontab -e ``` 添加一行: ``` 0 2 * * * /bin/bash /opt/mysql_backup/backup.sh ``` ### 步骤5: 恢复验证机制 编写恢复测试脚本`/opt/mysql_backup/verify.sh`,并设置每月执行一次(例如每月1号凌晨3点): ```bash #!/bin/bash BACKUP_DIR="/opt/mysql_backup" FULL_BACKUP_DIR="$BACKUP_DIR/full" RESTORE_DIR="/var/lib/mysql_restore" # 恢复目录,确保有足够空间 LOG_FILE="$BACKUP_DIR/verify.log" MYSQL_USER="root" MYSQL_PASSWORD="your_password" # 记录开始时间 echo "Restore verification started at $(date)" >> $LOG_FILE # 查找最新的全量备份 LATEST_FULL=$(ls -d $FULL_BACKUP_DIR/full_* | sort -r | head -1) if [ -z "$LATEST_FULL" ]; then echo "Error: No full backup found for restore. Exiting." >> $LOG_FILE exit 1 fi # 停止MySQL服务 sudo systemctl stop mysql # 创建恢复目录并清空(确保目录存在) sudo mkdir -p $RESTORE_DIR sudo rm -rf $RESTORE_DIR/* # 复制备份文件到恢复目录 echo "Copying backup files to $RESTORE_DIR..." >> $LOG_FILE xtrabackup --copy-back --target-dir=$LATEST_FULL --datadir=$RESTORE_DIR >> $LOG_FILE 2>&1 # 修改权限 sudo chown -R mysql:mysql $RESTORE_DIR # 修改MySQL配置指向恢复目录(临时) # 注意:这里我们使用临时配置,避免影响生产 sudo sed -i.bak "s|datadir.*|datadir=$RESTORE_DIR|" /etc/mysql/mysql.conf.d/mysqld.cnf # 启动MySQL sudo systemctl start mysql # 等待MySQL启动 sleep 30 # 检查MySQL是否正常运行 if systemctl is-active --quiet mysql; then # 验证数据:检查表数量(示例) TABLE_COUNT=$(mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema NOT IN ('information_schema','mysql','performance_schema','sys');" -s) if [ $TABLE_COUNT -gt 0 ]; then echo "Restore verification SUCCESS. Table count: $TABLE_COUNT" >> $LOG_FILE else echo "Restore verification FAILED: No tables found." >> $LOG_FILE fi else echo "MySQL failed to start. Restore verification FAILED." >> $LOG_FILE fi # 恢复原配置并停止MySQL sudo mv /etc/mysql/mysql.conf.d/mysqld.cnf.bak /etc/mysql/mysql.conf.d/mysqld.cnf sudo systemctl stop mysql # 清理恢复目录(可选,根据情况保留或删除) sudo rm -rf $RESTORE_DIR # 启动原MySQL服务 sudo systemctl start mysql echo "Restore verification completed at $(date)" >> $LOG_FILE ``` 设置cron任务: ```bash sudo crontab -e ``` 添加一行(每月1号凌晨3点执行): ``` 0 3 1 * * /bin/bash /opt/mysql_backup/verify.sh ``` ### 注意事项 1. **安全性**:脚本中密码建议存储在配置文件中(如`~/.my.cnf`)并设置权限为600,避免在脚本中明文存储。 2. **备份策略调整**:根据数据量调整备份频率(例如,数据变化大时,可每天多次增量备份)。 3. **监控**:监控备份日志和验证日志,设置告警(如日志中出现错误时发送邮件)。 4. **存储空间**:确保备份目录有足够空间,可使用`df -h`监控。 5. **恢复测试**:恢复测试在独立环境进行,避免影响生产。上述脚本临时修改了MySQL的数据目录,测试后恢复,但生产环境建议在另一台机器上测试。 ### 相关问题 1. 如何优化Percona XtraBackup的备份速度? 2. 增量备份过程中出现中断,如何恢复备份流程? 3. 如何配置MySQL的binlog以支持增量备份? 4. 备份验证失败时,如何排查问题? 5. 如何将备份文件自动上传到云存储(如AWS S3)以实现异地备份?</think>### 搭建MySQL增量备份机制(基于Percona XtraBackup) #### 一、工具选择与安装 根据引用[3]建议,**大数据量场景首选Percona XtraBackup**(物理备份工具),支持InnoDB引擎的无锁备份: ```bash # Ubuntu安装步骤 wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb sudo dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb sudo apt update sudo apt install percona-xtrabackup-80 # 匹配MySQL 8.0 ``` #### 二、全量+增量备份配置 ```bash #!/bin/bash # /opt/mysql_backup/backup.sh BACKUP_ROOT="/opt/mysql_backup" FULL_DIR="$BACKUP_ROOT/full" INC_DIR="$BACKUP_ROOT/inc" DATE=$(date +%Y%m%d) LOG="$BACKUP_ROOT/backup.log" # 全量备份(每周日执行) if [ $(date +%u) -eq 7 ]; then echo "[$(date)] 开始全量备份" >> $LOG xtrabackup --backup --user=root --password=your_password \ --target-dir=$FULL_DIR/full_$DATE # 准备备份文件(应用redo log) xtrabackup --prepare --apply-log-only --target-dir=$FULL_DIR/full_$DATE >> $LOG 2>&1 echo "[$(date)] 全量备份完成" >> $LOG # 增量备份(其他日期) else echo "[$(date)] 开始增量备份" >> $LOG # 查找最新全量/增量作为基准 BASE_DIR=$(ls -td $FULL_DIR/full_* $INC_DIR/inc_* 2>/dev/null | head -1) [ -z "$BASE_DIR" ] && { echo "错误:未找到基准备份"; exit 1; } xtrabackup --backup --user=root --password=your_password \ --target-dir=$INC_DIR/inc_$DATE \ --incremental-basedir=$BASE_DIR echo "[$(date)] 增量备份完成" >> $LOG fi ``` #### 三、自动过期删除(7天保留) 在备份脚本末尾添加: ```bash # 删除7天前备份 find $FULL_DIR -type d -name "full_*" -mtime +7 -exec rm -rf {} \; find $INC_DIR -type d -name "inc_*" -mtime +7 -exec rm -rf {} \; echo "[$(date)] 已清理过期备份" >> $LOG ``` #### 四、可恢复验证机制 ```bash #!/bin/bash # /opt/mysql_backup/verify.sh RESTORE_DIR="/var/lib/mysql_restore" # 测试恢复目录 LATEST_FULL=$(ls -td $FULL_DIR/full_* | head -1) # 停止MySQL并清空测试环境 sudo systemctl stop mysql rm -rf $RESTORE_DIR/* # 恢复全量备份 xtrabackup --copy-back --target-dir=$LATEST_FULL \ --datadir=$RESTORE_DIR # 应用增量备份(按时间顺序) for inc_dir in $(ls -td $INC_DIR/inc_*); do xtrabackup --prepare --apply-log-only --target-dir=$LATEST_FULL \ --incremental-dir=$inc_dir done # 最终准备(引用[2]关键步骤) xtrabackup --prepare --target-dir=$LATEST_FULL # 启动测试实例(临时端口3307) mysqld_safe --datadir=$RESTORE_DIR --port=3307 & # 验证数据完整性 if mysql -uroot -pyour_password -P3307 -e "SHOW DATABASES"; then echo "[SUCCESS] 备份验证成功 $(date)" >> $BACKUP_ROOT/verify.log else echo "[FAILED] 备份验证失败 $(date)" >> $BACKUP_ROOT/verify.log fi # 清理 killall mysqld rm -rf $RESTORE_DIR sudo systemctl start mysql # 重启原服务 ``` #### 五、自动化配置 1. **定时任务**(crontab -e): ```bash # 每天凌晨2点备份 0 2 * * * /bin/bash /opt/mysql_backup/backup.sh # 每周日凌晨3点验证 0 3 * * 7 /bin/bash /opt/mysql_backup/verify.sh ``` 2. **目录权限**(引用[4]): ```bash mkdir -p /opt/mysql_backup/{full,inc} chown -R mysql:mysql /opt/mysql_backup # 确保MySQL用户可写 ``` #### 六、关键技术解析 1. **增量备份原理** 基于LSN(Log Sequence Number)识别数据页变化: $$ \Delta = LSN_{\text{current}} - LSN_{\text{base}}} $$ 仅复制$LSN_{\text{base}}$之后修改的页[^1] 2. **恢复流程** 必须按顺序合并增量备份: ```mermaid graph LR A[全量备份] --> B[增量1] B --> C[增量2] C --> D[--prepare] D --> E[可恢复状态] ``` #### 七、常见问题处理 1. **备份失败**:检查`backup.log`错误日志,常见于权限不足或磁盘满 2. **验证失败**:检查二进制日志是否启用(`show variables like 'log_bin';`) 3. **性能优化**:添加`--parallel=4`加速备份(多线程) > **关键安全提示**:密码应存储在配置文件中(`/etc/mysql/backup.cnf`),设置权限600: > ```ini > [xtrabackup] > user=root > password=your_password > ``` --- ### 相关问题 1. 如何验证增量备份的LSN连续性? 2. 备份过程中如何避免锁表影响业务? 3. 当全量备份损坏时如何恢复增量备份? 4. 如何监控备份系统的存储空间使用情况? 5. 在Docker容器中运行MySQL时备份有哪些特殊配置? [^1]: MySQL增量备份需要启用二进制日志(binlog),通过LSN机制跟踪数据页变化,确保备份一致性。 [^2]: 恢复时必须先准备全量备份,再按顺序应用增量备份,最后执行最终准备使数据文件处于一致状态。 [^3]: 大数据量场景优先选择物理备份工具(如XtraBackup),可避免锁表并提升备份效率。 [^4]: 备份目录需确保MySQL进程有写入权限,容器环境需挂载卷或调整权限映射。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值