AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 575163
Accepted
Florin Andrei
Florin Andrei
Asked: 2014-02-13 13:10:11 +0800 CST2014-02-13 13:10:11 +0800 CST 2014-02-13 13:10:11 +0800 CST

如何保存:一周的每日备份,一个月的每周备份,一年的每月备份,之后每年备份

  • 772

我需要每天在此服务器上备份数据和配置文件。我需要保留:

  • 一周的每日备份
  • 一个月的每周备份
  • 一年的每月备份
  • 之后的年度备份

所有这些都是通过每天从 cron 运行的 shell 脚本完成的。

这是运行 10 年后备份文件的外观:

blog-20050103.tar.bz2
blog-20060102.tar.bz2
blog-20070101.tar.bz2
blog-20080107.tar.bz2
blog-20090105.tar.bz2
blog-20100104.tar.bz2
blog-20110103.tar.bz2
blog-20120102.tar.bz2
blog-20130107.tar.bz2
blog-20130902.tar.bz2
blog-20131007.tar.bz2
blog-20131104.tar.bz2
blog-20131202.tar.bz2
blog-20140106.tar.bz2
blog-20140203.tar.bz2
blog-20140303.tar.bz2
blog-20140407.tar.bz2
blog-20140505.tar.bz2
blog-20140602.tar.bz2
blog-20140707.tar.bz2
blog-20140728.tar.bz2
blog-20140804.tar.bz2
blog-20140811.tar.bz2
blog-20140816.tar.bz2
blog-20140817.tar.bz2
blog-20140818.tar.bz2
blog-20140819.tar.bz2
blog-20140820.tar.bz2
blog-20140821.tar.bz2
blog-20140822.tar.bz2
linux
  • 5 5 个回答
  • 38038 Views

5 个回答

  • Voted
  1. Best Answer
    MikeyB
    2014-02-13T13:21:01+08:002014-02-13T13:21:01+08:00

    你严重过度设计了这个。很糟糕。

    这是一些伪代码:

    • 每天:
      • 备份,放入daily目录
      • 删除除最后 7 个daily备份之外的所有内容
    • 每周:
      • 备份,放入weekly目录
      • 删除除最后 5 个weekly备份之外的所有内容
    • 每个月:
      • 备份,放入monthly目录
      • 删除除最后 12 个monthly备份之外的所有内容
    • 每年:
      • 备份,放入yearly目录

    您必须实现的逻辑量大致相同,是吗?吻。

    这看起来更容易:

    s3cmd ls s3://backup-bucket/daily/ | \
        awk '$1 < "'$(date +%F -d '1 week ago')'" {print $4;}' | \
        xargs --no-run-if-empty s3cmd del
    

    或者,按文件计数而不是年龄:

    s3cmd ls s3://backup-bucket/daily/ | \
        awk '$1 != "DIR"' | \
        sort -r | \
        awk 'NR > 7 {print $4;}' | \
        xargs --no-run-if-empty s3cmd del
    
    • 32
  2. powpow
    2014-11-11T11:01:09+08:002014-11-11T11:01:09+08:00

    例如,如果您只想保留 8 次每日备份和 5 次每周(每个星期日)备份,它的工作方式如下:

    for i in {0..7}; do ((keep[$(date +%Y%m%d -d "-$i day")]++)); done
    for i in {0..4}; do ((keep[$(date +%Y%m%d -d "sunday-$((i+1)) week")]++)); done
    echo ${!keep[@]}
    

    截至今天(2014-11-10),这将输出:

    20141012 20141019 20141026 20141102 20141103 20141104
    20141105 20141106 20141107 20141108 20141109 20141110
    

    作为留给您的练习,您只需删除名称未出现在keep-array 中的所有备份文件。

    如果您还想保留 13 个每月备份(每个月的第一个星期日)和 6 个年度备份(每年的第一个星期日),事情会变得有点复杂:

    for i in {0..7}; do ((keep[$(date +%Y%m%d -d "-$i day")]++)); done
    for i in {0..4}; do ((keep[$(date +%Y%m%d -d "sunday-$((i+1)) week")]++)); done
    for i in {0..12}; do
            DW=$(($(date +%-W)-$(date -d $(date -d "$(date +%Y-%m-15) -$i month" +%Y-%m-01) +%-W)))
            for (( AY=$(date -d "$(date +%Y-%m-15) -$i month" +%Y); AY < $(date +%Y); AY++ )); do
                    ((DW+=$(date -d $AY-12-31 +%W)))
            done
            ((keep[$(date +%Y%m%d -d "sunday-$DW weeks")]++))
    done
    for i in {0..5}; do
            DW=$(date +%-W)
            for (( AY=$(($(date +%Y)-i)); AY < $(date +%Y); AY++ )); do
                    ((DW+=$(date -d $AY-12-31 +%W)))
            done
            ((keep[$(date +%Y%m%d -d "sunday-$DW weeks")]++))
    done
    echo ${!keep[@]}
    

    截至今天(2014-11-10),这将输出:

    20090104 20100103 20110102 20120101 20130106 20131103
    20131201 20140105 20140202 20140302 20140406 20140504
    20140601 20140706 20140803 20140907 20141005 20141012
    20141019 20141026 20141102 20141103 20141104 20141105
    20141106 20141107 20141108 20141109 20141110
    

    同上,只需删除该数组中未找到的所有备份文件即可。

    • 8
  3. aggieNick02
    2020-10-17T09:52:28+08:002020-10-17T09:52:28+08:00

    我最近遇到了同样的问题。恕我直言,尝试编写一个 shell 脚本来做这件事是很痛苦的,而且使用带有内置函数(如集合、字典等)的高级语言编写一些可重用的逻辑要容易得多。一般的想法是采用配置来指示有多少文件您要保留的每个时期,然后决定是否应保留每个文件。

    有一个相当流行的基于 python 的脚本,它看起来非常漂亮,并且有一些易于理解的源代码。再加上基于 python 而不是基于 shell 赋予了它跨平台的优势: https ://github.com/xolox/python-rotate-backups

    • 3
  4. Joyce Babu
    2018-11-01T03:26:13+08:002018-11-01T03:26:13+08:00

    正如评论中提到的,通常最好将管理备份的任务委托给备份管理软件。

    但这是 bash 中根据您的要求删除旧备份的逻辑

    #!/bin/sh
    
    delete() {
        echo "Deleting $1"
    }
    
    DOW=$(date +%u)
    
    if [ $DOW -eq 1 ]; then
        DATE_DAY=$(date -d "-28 days" +"%d")
        if [ $DATE_DAY -gt 7 ]; then
            DATE=$(date -d "-28 days" +"%Y-%m-%d")
            delete $DATE
        fi
    
        DATE_DAY=$(date -d "-364 days" +"%d")
        DATE_MONTH=$(date -d "-364 days" +"%m")
        if [ $DATE_DAY -le 7 ] && [ $DATE_MONTH -gt 1 ]; then
            DATE=$(date -d "-364 days" +"%Y-%m-%d")
            delete $DATE
        fi
    else
        DATE=$(date -d "-7 days" +"%Y-%m-%d")
        delete $DATE
    fi
    

    显示运行 3520 天后哪些文件将保留的 PHP 代码

    https://ideone.com/n2ymQy

    Array
    (
        [0] => 2005-01-03
        [1] => 2006-01-02
        [2] => 2007-01-01
        [3] => 2008-01-07
        [4] => 2009-01-05
        [5] => 2010-01-04
        [6] => 2011-01-03
        [7] => 2012-01-02
        [8] => 2013-01-07
        [9] => 2013-09-02
        [10] => 2013-10-07
        [11] => 2013-11-04
        [12] => 2013-12-02
        [13] => 2014-01-06
        [14] => 2014-02-03
        [15] => 2014-03-03
        [16] => 2014-04-07
        [17] => 2014-05-05
        [18] => 2014-06-02
        [19] => 2014-07-07
        [20] => 2014-07-28
        [21] => 2014-08-04
        [22] => 2014-08-11
        [23] => 2014-08-16
        [24] => 2014-08-17
        [25] => 2014-08-18
        [26] => 2014-08-19
        [27] => 2014-08-20
        [28] => 2014-08-21
        [29] => 2014-08-22
    )
    
    • 0
  5. user50052
    2021-09-27T06:08:24+08:002021-09-27T06:08:24+08:00

    我也遇到过同样的问题。基本上需要运行每日完整备份的文件系统上的空间。

    我写了一个只打印 rm -f 命令的脚本。

    基本但对我来说已经足够了。易于适应/改进。

    好处:

    • 超级简单(基于find)
    • 易于通过管道传输到文件中,或者只是复制/粘贴相关的输出部分以供交互使用
    • 可能审查、执行并可能保留删除(清理)操作的痕迹

    限制:

    • 如果您的文件格式不同,您需要调整正则表达式
    • 由于它仅基于文件计数,因此当月内没有运行或启动备份时,可能会有一个月的转变。
    • 需要一些重写,因为它将在第二次运行时删除每周备份。所以只能使用一次。如果每月仅在同一天运行一次,则可能会起作用。
    #!/bin/bash
    # Build for this file format: 
    # ./YYYYmmdd-HHhMM_container_name.tar.xz
    # example: ./20210923-06h00_petrussewp.tar.xz
    
    DELETE_DAILY_AFTER=30   # days
    DELETE_WEEKLY_AFTER=180 # days (so keep only one monthly)
    
    # List the backup sources to group them:
    sourcename=$( ls -1 20*.tar.?z | sed -E 's/^[-h0-9]+_(.+)\.tar\.[gbx]z$/\1/' | sort | uniq )
    
    for ctname in ${sourcename}
    do
        echo "## ${ctname} backups :"
        for month in {01..12}
        do
            # Delete daily backups older than DELETE_DAILY_AFTER days.
            echo "# Obsolete daily backups for ${ctname} for the month ${month}:"
            find ./ -maxdepth 1 -type f -name "20??${month}*${ctname}*" -mtime +${DELETE_DAILY_AFTER} -printf "rm -f %p\n" | sort -n | awk 'NR % 7 != 1'
            # Delete all but the first matching backup of the month after DELETE_WEEKLY_AFTER days.
            echo "# Obsolete weekly backups for ${ctname} for the month ${month}:"
            find ./ -maxdepth 1 -type f -name "20??${month}*${ctname}*" -mtime +${DELETE_WEEKLY_AFTER} -printf "rm -f %p\n" | sort -n | awk 'NR % 7 == 1' | tail -n+2
        done
    done
    

    脚本输出示例:

    ## wekan-db backups :
    # Obsolete daily backups for wekan-db for the month 01:
    # Obsolete weekly backups for wekan-db for the month 01:
    # Obsolete daily backups for wekan-db for the month 02:
    rm -f ./20210206-06h00_wekan-db.tar.xz
    rm -f ./20210207-06h00_wekan-db.tar.xz
    rm -f ./20210208-06h00_wekan-db.tar.xz
    rm -f ./20210209-06h00_wekan-db.tar.xz
    rm -f ./20210210-06h00_wekan-db.tar.xz
    rm -f ./20210211-06h00_wekan-db.tar.xz
    rm -f ./20210213-06h00_wekan-db.tar.xz
    rm -f ./20210214-06h00_wekan-db.tar.xz
    rm -f ./20210215-06h00_wekan-db.tar.xz
    rm -f ./20210216-06h00_wekan-db.tar.xz
    rm -f ./20210217-06h00_wekan-db.tar.xz
    rm -f ./20210218-06h00_wekan-db.tar.xz
    rm -f ./20210220-06h00_wekan-db.tar.xz
    rm -f ./20210221-06h00_wekan-db.tar.xz
    rm -f ./20210222-06h00_wekan-db.tar.xz
    rm -f ./20210223-06h00_wekan-db.tar.xz
    rm -f ./20210224-06h00_wekan-db.tar.xz
    rm -f ./20210225-06h00_wekan-db.tar.xz
    rm -f ./20210227-06h00_wekan-db.tar.xz
    rm -f ./20210228-06h00_wekan-db.tar.xz
    # Obsolete weekly backups for wekan-db for the month 02:
    rm -f ./20210212-06h00_wekan-db.tar.xz
    rm -f ./20210219-06h00_wekan-db.tar.xz
    rm -f ./20210226-06h00_wekan-db.tar.xz
    
    • 0

相关问题

  • Linux 主机到主机迁移

  • 如何在 Linux 机器上找到有关硬件的详细信息?

  • 如何在 Linux 下监控每个进程的网络 I/O 使用情况?

  • 在 RHEL4 上修改 CUPS 中的现有打印机设置

  • 为本地网络中的名称解析添加自定义 dns 条目

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    新安装后 postgres 的默认超级用户用户名/密码是什么?

    • 5 个回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve