我创建了一个脚本来在我的 CentOS 7 服务器上运行自动备份。备份存储在 /home/backup 目录中。该脚本有效,但现在我想采用一种方法在备份发生后对文件进行计数,如果数量超过 5,则删除最旧的备份。
以下是我的备份脚本。
#!/bin/bash
#mysqldump variables
FILE=/home/backup/databasebk_!`date +"Y-%m-%d_%H:%M"`.sql
DATABASE=database
USER=root
PASS=my password
#backup command process
mysqldump --opt --user=${USER} --password=${PASS} ${DATABASE} > ${FILE}
#zipping the backup file
gzip $FILE
#send message to the user with the results
echo "${FILE}.gz was created:"
ls -l ${FILE}.gz
# This is where I would like to count the number of files
# in the directory and if there are more than 5 I would like
# to delete the oldest file. Any help is greatly appreciated
谢谢-迈克
答案1
在没有循环的纯 Bash 中:
ls -t | tail -n +6 | xargs -d '\n' rm
解释:
ls -t
打印当前目录中的所有文件,按修改时间排序,最新的在前。tail -n +6
忽略前 5 行并打印第 6 行以后的行。xargs -d '\n' rm
删除传递给它的文件,每行一个。如果您绝对确定文件名中没有空格或引号,则可以仅使用xargs rm
.
请注意,这会根据需要删除尽可能多的文件,以便在目录中仅留下 5 个文件。如果您只想删除一个最旧的文件,请替换+6
为1
.
答案2
你可以看看set -- /home/backup/databasebk_*
,当$#
大于五个时,删除一个文件。
所以代码看起来类似于
set -- /home/backup/databasebk_*
while [ $# -gt 5 ]
do
echo "Removing old backup $1"
rm "$1"
shift
done
这是有效的,因为您选择的文件名会自动按“最旧的在前”顺序排列。
为了保持一致性,我会设置一个变量(我通常这样称呼它,BASE
但你可以随意称呼它)
所以
BASE=/home/backup/databasebk_
FILE=${BASE}!`date +"%Y-%m-%d_%H:%M"`.sql
....
set -- ${BASE}*
while [ $# -gt 5 ]
do
echo "Removing old backup $1"
rm "$1"
shift
done
答案3
我认为更好的方法是使用 logrotate,因为该应用程序已经执行了您尝试使用脚本实现的操作。我在我的测试服务器上测试了以下脚本。
- 手动备份数据库,这是必要的,因为如果文件不存在,logrotate 将不会运行。
$ mysqldump -uroot -pmy5trongpass database > mydatabase.sql
$ ls
$ mydatabase.sql
未创建第一个数据库时的错误示例。
#**logrotate -f** will force our new rule to run now and backup the database
#this is for testing purposes.
$ logrotate -f /etc/logrotate.d/mysql_backup
error: stat of /home/backups/mydatabase.sql failed: No such file or directory
- 创建 logrotate 文件/规则。这是我根据位于 /etc/logrotate.d/ 中的其他规则创建的规则
$ cat /etc/logrotate.d/mysql_backup
/home/backups/mydatabase.sql{
create 640 root mysql
daily
rotate 2
nocompress
postrotate
mysqldump -uroot -pmy5trongpass test > mydatabase.sql;
echo "done"
endscript
}
- 使用测试您的配置
$ logrotate -f /etc/logrotate.d/mysql_backup
$ logrotate -f /etc/logrotate.d/mysql_backup
done
$ ll
total 16
-rw-r-----. 1 root mysql 1261 Feb 3 21:46 mydatabase.sql
-rw-r-----. 1 root mysql 1261 Feb 3 21:44 mydatabase.sql.1
-rw-r-----. 1 root mysql 1261 Feb 3 21:44 mydatabase.sql.2
您将看到将创建一个新文件,后跟一个数字,可以使用以下选项将其更改为显示日期
https://linux.die.net/man/8/logrotate
dateext
Archive old versions of log files adding a daily extension like YYYYMMDD instead of simply adding a number. The extension may be configured using the dateformat option.
dateformat format_string
Specify the extension for dateext using the notation similar to strftime(3) function. Only %Y %m %d and %s specifiers are allowed. The default value is -%Y%m%d. Note that also the character separating log name from the extension is part of the dateformat string. The system clock must be set past Sep 9th 2001 for %s to work correctly. Note that the datestamps generated by this format must be lexically sortable (i.e., first the year, then the month then the day. e.g., 2001/12/01 is ok, but 01/12/2001 is not, since 01/11/2002 would sort lower while it is later). This is because when using the rotate option, logrotate sorts all rotated filenames to find out which logfiles are older and should be removed.
答案4
files=( /home/backup/* )
# files is now an array containing file names in the directory
oldest=""
if (( ${#files[@]} > 5 )) ## are there more than five?
then
for name in "${files[@]}" ## loop to find oldest
do
a=$( stat --printf=%Y "$name" )
if [ -z "$oldest" ] || (( a < age ))
then
age="$a"
oldest="$name"
fi
done
rm "$oldest"
fi
一些评论:
我说/home/backup/*
的是找到该目录中的所有文件,/home/backup/databasebk_*.sql.gz
而我可以说只是找到压缩转储
我正在使用“stat”根据文件系统查找最旧的文件,因为您的日期采用 YMDhm 格式顺序,我可以比较文件名
if [ -z "$oldest" ] || [ "$name" -lt "$oldest" ]
/home/backup/ 中存在子目录将破坏此脚本