编写Bash脚本清理MySQL备份文件并保留指定版本
MySQL备份文件夹清理脚本分享与优化请求
需求说明
- 备份文件夹分为
daily、weekly、monthly三类 - 备份文件格式:
<db_table_name>_bkup_yyyy_mm_dd.sql.gz - 核心功能:指定目标文件夹和保留的备份版本数,当文件数量超过保留数时,自动删除最旧的文件
我已自行完成脚本编写,但认为仍有优化空间,现分享该脚本供大家使用,也希望有人能在保证可读性的前提下对其进行优化。
已完成的脚本代码
#!/bin/bash -l # CEM2 - 2023.01.18 new # db_backup_cleanup.sh (/home/link/intra/system/db/) # # Purpose: Deletes extra database table backup files. # In order to keep only x number of table backup files # # Backup files must be: # - in /backup/db/<database_name>/ # - subfolders of daily / weekly / monthly # - file format <table_name>_bkup_yyyy_mm_dd.sql.gz # #------------------------------------------------------------------------ do_cleanup() { #-------------------------------------------------------------------- # Reads each file from the path # Grabs the file prefix which contains the table name # Compares each incoming file until a change in table is found # Processes the table: # - Collects all file_date_suffixes in an array # - Calls routine to check how many files there are for this table # - Delete early ones if we have too many. #-------------------------------------------------------------------- myPath="/backup/db/$myDb/$myFreq" echo "==========================================" echo "== Ready to clean extra bckup files in:" echo " Folder = $myPath" echo " Keeping $keep number of versions" echo " " echo "------------------------------------------" #-- Looking for needle _bkup_ in filename. #-- This separates the path/table_name from date_suffix #-- ex. /path/mytable_bkup_2023_12_31.sql.gz prev_file="" files=("$myPath"/*) #-- counts files deleted cleaned_cntr=0; #-- counts files read in cntr=0 #=== Loop Through the files... for file in "${files[@]}"; do #--- Increment file counter cntr=$(($cntr+1)) echo "------------------- " echo "File Number : $cntr" echo "Backup File : $file" #--- get the file prefix (path and file name) #-- backup= path/db_tblname_bkup_yyyy_mm_dd.sql.gz #-- prefix= path/db_tblname prefix=${file%%$needle*} echo "Path and File : $prefix" #-- If prefix = whole file name then we didn't find _bkup_ #-- this is not a backup file so skip it. if [ "$prefix" == "$file" ] then echo " NOT a backup file. Not processing." continue fi #-- First time in, prev_file will be empty. #-- Set it to first file prefix before comparison is made. if [ "$prev_file" == "" ] then prev_file="$prefix" fi #-- in what position is the needle. mypos=${#prefix} #--- Debug only # echo "found $needle at $mypos" #-- get file date suffix #-- Last position of "_bkup_" x=$(($mypos+6)) file_date="${file:$x:10}" # echo "the suffix is $file_date" #-- Debug Only # echo "prefix: $prefix and prev_file: $prev_file" if [ "$prefix" != "$prev_file" ] then #-- Filename change - check file... echo "That's all the files for PREVIOUS table." echo "Going to see if we should delete some..." do_remove_extras #-- prepare for the next filename #-- Clear the Main Array for new files aryFiles=() prev_file="${prefix}" aryFiles+=($file_date) else aryFiles+=($file_date) fi echo " " done #-- Process last file which will not be triggered by a #-- change in file name. echo "Process Final File... " do_remove_extras echo " " echo "======================================================" echo "Summary for $myPath" echo "======================================================" echo "Deleted ${cleaned_cntr} files." echo "-----------------------------------" echo " " } #--------------------------------------- do_remove_extras() { #-- Empty ary that will hold the sorted file date suffixes arySorted=() #-- How many file date suffixes do we have nbrSuffixes=${#aryFiles[@]} echo " There are $nbrSuffixes suffixes for this file (keeping $keep)." #-- echo "Printing Original array" #-- for (( i=0; i<$nbrSuffixes; i++ )); do echo "${aryFiles[$i]}" ; done #-- Sort the suffixes by date yyyy-mm-dd - earliest first arySorted=($(echo "${aryFiles[@]}" | sed 's/ /\n/g' | sort)) echo " Printing Sorted array..." echo " ${arySorted[@]}" #-- Delete Extra files nbr_to_rm=$(($nbrSuffixes-$keep)) # echo " How many files to remove? $nbr_to_rm" if (( $nbr_to_rm > 0 )) then #-- need to delete some echo " We will delete $nbr_to_rm files..." del_cntr=0; for (( i=0; i<$nbrSuffixes; i++ )); do suff="${arySorted[$i]}"; del_fname="${prev_file}$needle${suff}" ; if [ $del_cntr -lt $nbr_to_rm ] then #-- debug echo " del_cntr = ${del_cntr} and nbr_to_rm = ${nbr_to_rm}" echo " DELETING filename = ${del_fname}.sql.gz" rm -f "${del_fname}.sql.gz" (( cleaned_cntr++ )) (( del_cntr++ )) else echo " Keeping ${del_fname}..." fi done fi } #======================================================================= # MAIN SCRIPT #======================================================================= echo "======================================================" echo "Starting $(basename $BASH_SOURCE) at `date`" echo " " #get general variables echo " Getting System variables..." source "./cemsoft.conf" #--- Was DB provided if [ -z "$1" ]; then echo "No Database Was provided" exit; #-- set Default? # COMP="cscs" else myDb=$1 fi echo " Managing DB Backup files at path=<LOG_PATH>" echo " " cleaned_cntr=0; aryFiles=() needle="_bkup_" #--------------------------------------------------- # Call as many times as needed #--------------------------------------------------- myFreq="daily" keep=2 do_cleanup myFreq="weekly" do_cleanup myFreq="monthly" do_cleanup echo " " echo " " echo "======================================================" echo "Finished with Backup Cleanup." echo "======================================================" echo " "
优化方向
希望能在保证脚本可读性的前提下,从以下方面优化:
- 简化循环与数组处理逻辑
- 提升脚本执行效率
- 增强错误处理与健壮性
- 优化参数传递方式,让脚本更灵活
内容的提问来源于stack exchange,提问作者user2103442
相关产品推荐
相关产品推荐

