我想制作一个备份脚本,每周进行一次完整备份,否则每天进行增量备份。
我将如何根据已经过去的天数设置条件?因此,如果一周过去了,它将执行完整备份,否则它将覆盖上次增量备份。
我会将相同的脚本添加到 /etc/cron.weekly 和 /etc/cron.daily
答案1
你可以这样做:
day_of_week=$(date '+%w')
# or with recent bash
printf -v day_of_week '%(%w)T' -1
然后
case $day_of_week in
0) do_full_backup ;;
*) do_incremental_backup ;;
esac
然后,您每天运行备份脚本,它可以确定是否应该执行完整备份或增量备份。
答案2
我将如何根据已经过去的天数设置条件?
如果您想检查自上次完整备份以来已经过去的实际天数,而不仅仅是当天,则需要保存上次完整备份的时间戳并进行检查。
最简单的可能是只检查 unix 时间戳,即已经过去的秒数:
#!/bin/bash
file=last_full
elapsed=999999999
min_interval=$((6*86400 + 12*3600)) # 6 d + 12 h
now=$(date +%s)
if [[ -f "$file" ]]; then
elapsed=$(( now - $(< "$file") ))
fi
if (( elapsed > min_interval )); then
echo run full backup...
echo "$now" > "$file"
else
echo run incremental backup...
fi
days=$(( elapsed / 86400 ))
或者首先使用例如或 四舍五入将秒数转换为天数days_rounded=$(( (elapsed + 86400/2) / 86400 ))
。
这样,如果脚本在某个周日丢失也没关系,它会在下次运行时(例如周一)运行下一个完整备份。缺点是接下来的所有完整备份也将转移到星期一。虽然你可以绕过它还检查工作日,例如:
if (( elapsed > min_interval )) || [[ $(date +%w) = 0 ]]; then
echo run full backup...
...
fi
(6.5 天的截止时间是为了避免出现问题,如果脚本的执行由于某一天的系统负载而稍微延迟,导致下一个间隔比全天短几秒钟。)
我会将相同的脚本添加到 /etc/cron.weekly 和 /etc/cron.daily
如果您从两者都运行它,它将在周日运行两次。 (或者无论当天cron.weekly
运行的是什么。)如果脚本本身检查它需要执行哪一项操作,您可以从 运行它cron.daily
。
使用cron.daily
and的另一种方法cron.weekly
是在 中创建两行crontab
:
0 4 * * 0 /path/to/mybackup.sh full
0 4 * * 1-6 /path/to/mybackup.sh incremental
然后检查$1
脚本中的第一个命令行参数。这将避免周日的双重运行,但会遇到与以前相同的问题:错过周日的运行将错过一周的完整备份。
答案3
我的备份脚本做了类似的事情。早些时候,它设置了两个全局变量:dayno
哪个是该月的“第一”..“第四”周,dayname
哪个是“星期日”..“星期六”。然后,以下函数返回0
0 级转储、1
仅当星期几匹配时返回 1 级转储以及2
其他日期的 2 级转储。相关函数是:
# get_level calculates the appropriate level for the dump from
# the day or the week and the day of the month.
#
function get_level {
put_trace "$trace" "$this_shell" "Calculating level"
day_of_week=$(date $today +%A)
put_debug "$debug" "Today is $day_of_week $(date $today +%d)"
if [[ "$dayname" == "${day_of_week,,}" ]] # Force to lowercase
then
case $(date $today +%d) in
01|02|03|04|05|06|07) week="first" ;;
08|09|10|11|12|13|14) week="second" ;;
15|16|17|18|19|20|21) week="third" ;;
*) week="fourth" ;;
esac
if [[ "$week" == "$dayno" ]]
then
echo 0
else
echo 1
fi
else
echo 2
fi
}
忽略put_trace
和put_debug
行,您需要有我的支持 bash 库才能使用它们。
date $today +%A
返回日期名称($today
可以从命令行更改,只需将其读取为当前日期)。如果一周中的某一天与要完成级别 1 和级别 0 备份的时间相匹配,则确定是该月的哪一周,否则返回级别 2。 case 语句可能很粗糙,但很明显并且有效!
您可以根据需要随意复制。该脚本的一部分已经在各种机器上运行了大约 3 年,并且生成的转储有时已恢复,因此它可以工作。
答案4
我会这样设置:
if [ "$(date '+%w')" -eq 0 ]; then
backup_full
else
backup_incremental
fi