Skip to content

Instantly share code, notes, and snippets.

@adrianbiro
Forked from bigbosst/BackupRotated
Last active March 7, 2025 18:56
Show Gist options
  • Save adrianbiro/22fa0362fe1a510eb00fe11dced759d4 to your computer and use it in GitHub Desktop.
Save adrianbiro/22fa0362fe1a510eb00fe11dced759d4 to your computer and use it in GitHub Desktop.

Revisions

  1. adrianbiro revised this gist Mar 7, 2025. 1 changed file with 44 additions and 29 deletions.
    73 changes: 44 additions & 29 deletions BackupRotated
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,5 @@
    #!/bin/bash

    # shellcheck disable=CS2010
    SRC_DIR="/srv/gits"
    BACKUP_DIR="/srv/backups"
    PROJECT_NAME="gits"
    @@ -20,12 +20,49 @@ DAYWEEK="$(date +%u)"
    [[ ($DAYWEEK -lt 7) && (-z $RATE) ]] && RATE='daily'

    DATE=$RATE-"$(date +"%Y:%m:%d")"
    : <<'END_COMMENT'
    Example $BACKUP_DIR structure:
    gits-hourly-2025:03:07-06:00:00.tar.gz
    ... # hour increments in hourly retention range
    gits-hourly-2025:03:07-17:00:00.tar.gz
    gits-daily-2025:03:07.tar.gz
    gits-daily-2025:03:06.tar.gz
    gits-daily-2025:03:05.tar.gz
    gits-daily-2025:03:04.tar.gz
    gits-daily-2025:03:03.tar.gz
    gits-weekly-2025:03:02.tar.gz # doubes as daily
    gits-daily-2025:03:01.tar.gz # in ocasion weekly doubles as daily, you have temporarrly +1 daily retention period
    gits-weekly-2025:02:23.tar.gz
    gits-weekly-2025:02:16.tar.gz
    gits-monthly-2025:03:01.tar.gz
    gits-monthly-2025:02:01.tar.gz
    gits-yearly-2025:01:01.tar.gz # doubles as monthly
    END_COMMENT
    BKP_FILE="${BACKUP_DIR}/${PROJECT_NAME}-${DATE}.tar.gz"

    function backup {
    _bkp_file="${BACKUP_DIR}/${PROJECT_NAME}-${DATE}.tar.gz"
    [[ -f "${_bkp_file}" ]] || {
    tar czf "${_bkp_file}" "${SRC_DIR}"
    function backup() {
    : <<'END_COMMENT'
    In the case backup is runned hourly, do not recreate daily, weekly, monthly, and yearly.
    In effect this part is running just onnce a day.
    END_COMMENT
    [[ -f "${BKP_FILE}" ]] || {
    echo -e "Creating:\t${BKP_FILE}"
    tar czf "${BKP_FILE}" "${SRC_DIR}"
    }
    : <<'END_COMMENT'
    Hourly backup
    Skip tar creation and compresion if eg. daily backup was created in less then 6 minutes (360 sec).
    Just cp previous one, to avoid unnecesery load.
    END_COMMENT
    [[ ($BACKUP_RETENTION_HOURLY -gt 0) ]] && {
    BKP_FILE_hourly="${BACKUP_DIR}/${PROJECT_NAME}-hourly-$(date +"%Y:%m:%d-%X").tr.gz"
    echo -e "Creating:\t${BKP_FILE_hourly}"
    [[ $(($(date +'%s') - $(stat -c '%W' ${BKP_FILE}))) -lt 360 ]] && cp "${BKP_FILE}" "${BKP_FILE_hourly}"
    [[ -f "${BKP_FILE_hourly}" ]] || tar czf "${BKP_FILE_hourly}" "${SRC_DIR}"
    }
    }

    function rotate_backups() {
    cd "${BACKUP_DIR}" || echo "${BACKUP_DIR}: does not exists"
    echo "Rotating old backups"
    ls -t | grep "${PROJECT_NAME}" | grep "hourly" | sed -e 1,"$BACKUP_RETENTION_HOURLY"d | xargs -d '\n' rm -vR 2>/dev/null
    @@ -37,27 +74,5 @@ function backup {
    fi
    }

    echo "Hourly Backup Run"
    [[ ($BACKUP_RETENTION_HOURLY -gt 0) ]] && {
    tar czf "${BACKUP_DIR}/${PROJECT_NAME}-hourly-$(date +"%Y:%m:%d-%X").tr.gz" "${SRC_DIR}"
    }
    echo $BACKUP_RETENTION_DAILY
    [[ ($BACKUP_RETENTION_DAILY -gt 0) && (-n "$BACKUP_RETENTION_DAILY") && ($BACKUP_RETENTION_DAILY -ne 0) && ($RATE == daily) ]] && {
    echo "Daily Backup Run"
    backup
    }
    echo $BACKUP_RETENTION_WEEKLY
    [[ ($BACKUP_RETENTION_WEEKLY -gt 0) && (-n "$BACKUP_RETENTION_WEEKLY") && ($BACKUP_RETENTION_WEEKLY -ne 0) && ($RATE == weekly) ]] && {
    echo "Weekly Backup Run"
    backup
    }
    echo $BACKUP_RETENTION_MONTHLY
    [[ ($BACKUP_RETENTION_MONTHLY -gt 0) && (-n "$BACKUP_RETENTION_MONTHLY") && ($BACKUP_RETENTION_MONTHLY -ne 0) && ($RATE == monthly) ]] && {
    echo "Monthly Backup Run"
    backup
    }
    echo $BACKUP_RETENTION_YEARLY
    [[ ($BACKUP_RETENTION_YEARLY -ge 0) && (-n "$BACKUP_RETENTION_YEARLY") && ($RATE == yearly) ]] && {
    echo "Yearly Backup Run"
    backup
    }
    backup
    rotate_backups
  2. adrianbiro revised this gist Mar 7, 2025. 1 changed file with 35 additions and 67 deletions.
    102 changes: 35 additions & 67 deletions BackupRotated
    Original file line number Diff line number Diff line change
    @@ -1,95 +1,63 @@
    #!/bin/bash

    SRC_DIR="/srv/backups"
    BACKUP_DIR="/srv/gits"
    SRC_DIR="/srv/gits"
    BACKUP_DIR="/srv/backups"
    PROJECT_NAME="gits"

    BACKUP_RETENTION_HOURLY=12
    BACKUP_RETENTION_DAILY=6
    BACKUP_RETENTION_WEEKLY=3
    BACKUP_RETENTION_MONTHLY=3
    BACKUP_RETENTION_YEARLY=0

    DAYYEAR=`date +%j`
    DAYMONTH=`date +%d`
    DAYWEEK=`date +%u`
    DAYYEAR="$(date +%j)"
    DAYMONTH="$(date +%d)"
    DAYWEEK="$(date +%u)"

    if [[ ( $DAYYEAR -eq 1 ) ]];
    then
    FN='yearly'
    elif [[ ( $DAYMONTH -eq 1 ) ]];
    then
    FN='monthly'
    elif [[ ( $DAYWEEK -eq 7 ) ]];
    then
    FN='weekly'
    elif [[ ( $DAYWEEK -lt 7 ) ]];
    then
    FN='daily'
    fi
    [[ ($DAYYEAR -eq 1) ]] && RATE='yearly'
    [[ ($DAYMONTH -eq 1) && (-z $RATE) ]] && RATE='monthly'
    [[ ($DAYWEEK -eq 7) && (-z $RATE) ]] && RATE='weekly'
    [[ ($DAYWEEK -lt 7) && (-z $RATE) ]] && RATE='daily'

    DATE=$FN-`date +"%Y%m%d"`
    echo $DATE
    DATE=$RATE-"$(date +"%Y:%m:%d")"

    function show_help {
    echo "BackupRotation available options are"
    echo
    echo "-s Sorce directroy to be backed up"
    echo "-b Destination forlder for the backups"
    echo "-n Name of the project being backuped"
    echo "-d Number of Daily backups to keep, negitve numbers will disable"
    echo "-w Number of Weekly backups to keep, negitve numbers will disable"
    echo "-m Number of Monthly backups to keep, negitve numbers will disable"
    echo "-y Number of Yearly backups to keep, negitve numbers will disable"
    echo "-h show this help text"
    }

    function backup
    {
    tar czf $BACKUP_DIR/$PROJECT_NAME-$DATE.tar.gz $SRC_DIR
    cd $BACKUP_DIR/
    function backup {
    _bkp_file="${BACKUP_DIR}/${PROJECT_NAME}-${DATE}.tar.gz"
    [[ -f "${_bkp_file}" ]] || {
    tar czf "${_bkp_file}" "${SRC_DIR}"
    }
    cd "${BACKUP_DIR}" || echo "${BACKUP_DIR}: does not exists"
    echo "Rotating old backups"
    ls -t | grep $PROJECT_NAME | grep daily | sed -e 1,"$BACKUP_RETENTION_DAILY"d | xargs -d '\n' rm -R > /dev/null 2>&1
    ls -t | grep $PROJECT_NAME | grep weekly | sed -e 1,"$BACKUP_RETENTION_WEEKLY"d | xargs -d '\n' rm -R > /dev/null 2>&1
    ls -t | grep $PROJECT_NAME | grep monthly | sed -e 1,"$BACKUP_RETENTION_MONTHLY"d | xargs -d '\n' rm -R > /dev/null 2>&1
    if [[ ( $BACKUP_RETENTION_YEARLY -gt 0 ) ]]; then
    ls -t | grep $PROJECT_NAME | grep yearly | sed -e 1,"$BACKUP_RETENTION_YEARLY"d | xargs -d '\n' rm -R > /dev/null 2>&1
    ls -t | grep "${PROJECT_NAME}" | grep "hourly" | sed -e 1,"$BACKUP_RETENTION_HOURLY"d | xargs -d '\n' rm -vR 2>/dev/null
    ls -t | grep "${PROJECT_NAME}" | grep "daily" | sed -e 1,"$BACKUP_RETENTION_DAILY"d | xargs -d '\n' rm -vR 2>/dev/null
    ls -t | grep "${PROJECT_NAME}" | grep "weekly" | sed -e 1,"$BACKUP_RETENTION_WEEKLY"d | xargs -d '\n' rm -vR 2>/dev/null
    ls -t | grep "${PROJECT_NAME}" | grep "monthly" | sed -e 1,"$BACKUP_RETENTION_MONTHLY"d | xargs -d '\n' rm -vR 2>/dev/null
    if [[ ($BACKUP_RETENTION_YEARLY -gt 0) ]]; then
    ls -t | grep "${PROJECT_NAME}" | grep yearly | sed -e 1,"$BACKUP_RETENTION_YEARLY"d | xargs -d '\n' rm -vR 2>/dev/null
    fi
    }

    while getopts s:b:n:d:w:m:y:h option
    do
    case "${option}"
    in
    s) SRC_DIR=${OPTARG};;
    b) BACKUP_DIR=${OPTARG};;
    n) PROJECT_NAME=${OPTARG};;
    d) BACKUP_RETENTION_DAILY=${OPTARG};;
    w) BACKUP_RETENTION_WEEKLY=${OPTARG};;
    m) BACKUP_RETENTION_MONTHLY=${OPTARG};;
    y) BACKUP_RETENTION_YEARLY=${OPTARG};;
    h) show_help
    exit 0
    ;;
    esac
    done

    echo "Hourly Backup Run"
    [[ ($BACKUP_RETENTION_HOURLY -gt 0) ]] && {
    tar czf "${BACKUP_DIR}/${PROJECT_NAME}-hourly-$(date +"%Y:%m:%d-%X").tr.gz" "${SRC_DIR}"
    }
    echo $BACKUP_RETENTION_DAILY
    if [[ ( $BACKUP_RETENTION_DAILY -gt 0 ) && ( ! -z "$BACKUP_RETENTION_DAILY" ) && ( $BACKUP_RETENTION_DAILY -ne 0 ) && ( $FN == daily ) ]]; then
    [[ ($BACKUP_RETENTION_DAILY -gt 0) && (-n "$BACKUP_RETENTION_DAILY") && ($BACKUP_RETENTION_DAILY -ne 0) && ($RATE == daily) ]] && {
    echo "Daily Backup Run"
    backup
    fi
    }
    echo $BACKUP_RETENTION_WEEKLY
    if [[ ( $BACKUP_RETENTION_WEEKLY -gt 0 ) && ( ! -z "$BACKUP_RETENTION_WEEKLY" ) && ( $BACKUP_RETENTION_WEEKLY -ne 0 ) && ( $FN == weekly ) ]]; then
    [[ ($BACKUP_RETENTION_WEEKLY -gt 0) && (-n "$BACKUP_RETENTION_WEEKLY") && ($BACKUP_RETENTION_WEEKLY -ne 0) && ($RATE == weekly) ]] && {
    echo "Weekly Backup Run"
    backup
    fi
    }
    echo $BACKUP_RETENTION_MONTHLY
    if [[ ( $BACKUP_RETENTION_MONTHLY -gt 0 ) && ( ! -z "$BACKUP_RETENTION_MONTHLY" ) && ( $BACKUP_RETENTION_MONTHLY -ne 0 ) && ( $FN == monthly ) ]]; then
    [[ ($BACKUP_RETENTION_MONTHLY -gt 0) && (-n "$BACKUP_RETENTION_MONTHLY") && ($BACKUP_RETENTION_MONTHLY -ne 0) && ($RATE == monthly) ]] && {
    echo "Monthly Backup Run"
    backup
    fi
    }
    echo $BACKUP_RETENTION_YEARLY
    if [[ ( $BACKUP_RETENTION_YEARLY -ge 0 ) && ( ! -z "$BACKUP_RETENTION_YEARLY" ) && ( $FN == yearly ) ]]; then
    [[ ($BACKUP_RETENTION_YEARLY -ge 0) && (-n "$BACKUP_RETENTION_YEARLY") && ($RATE == yearly) ]] && {
    echo "Yearly Backup Run"
    backup
    fi
    }
  3. adrianbiro renamed this gist Mar 7, 2025. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  4. adrianbiro revised this gist Mar 7, 2025. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion BackupRotated
    Original file line number Diff line number Diff line change
    @@ -52,7 +52,7 @@ function backup
    ls -t | grep $PROJECT_NAME | grep weekly | sed -e 1,"$BACKUP_RETENTION_WEEKLY"d | xargs -d '\n' rm -R > /dev/null 2>&1
    ls -t | grep $PROJECT_NAME | grep monthly | sed -e 1,"$BACKUP_RETENTION_MONTHLY"d | xargs -d '\n' rm -R > /dev/null 2>&1
    if [[ ( $BACKUP_RETENTION_YEARLY -gt 0 ) ]]; then
    ls -t | grep $PROJECT_NAME | grep htdocs | grep yearly | sed -e 1,"$BACKUP_RETENTION_YEARLY"d | xargs -d '\n' rm -R > /dev/null 2>&1
    ls -t | grep $PROJECT_NAME | grep yearly | sed -e 1,"$BACKUP_RETENTION_YEARLY"d | xargs -d '\n' rm -R > /dev/null 2>&1
    fi
    }

  5. adrianbiro revised this gist Mar 7, 2025. 3 changed files with 29 additions and 0 deletions.
    10 changes: 10 additions & 0 deletions gitsBackup.service
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,10 @@
    [Unit]
    Description=Backup of /srv/gits
    Wants=gitsBackup.timer

    [Service]
    Type=oneshot
    ExecStart=/srv/gits/git_server_administration/backup_script/backup.sh

    [Install]
    WantedBy=multi-user.target
    10 changes: 10 additions & 0 deletions gitsBackup.service.timer
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,10 @@
    [Unit]
    Description=Backup /srv/gits on hourly basis
    Requires=gitsBackup.service

    [Timer]
    Unit=gitsBackup.service
    OnCalendar=*-*-* *:00:00

    [Install]
    WantedBy=timers.target
    9 changes: 9 additions & 0 deletions install.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,9 @@
    https://www.freedesktop.org/software/systemd/man/latest/systemd.time.html#
    https://documentation.suse.com/smart/systems-management/html/systemd-working-with-timers/index.html
    systemd-analyze verify gitsBackup.*
    sudo systemctl edit --force --full gitsBackup.timer
    sudo systemctl edit --force --full gitsBackup.service
    sudo systemctl daemon-reload
    sudo systemctl enable --now gitsBackup.service
    sudo systemctl enable --now gitsBackup.timer
    systemctl status gitsBackup
  6. adrianbiro revised this gist Mar 7, 2025. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions BackupRotated
    Original file line number Diff line number Diff line change
    @@ -1,8 +1,8 @@
    #!/bin/bash

    SRC_DIR="/var/www/html"
    BACKUP_DIR="/mnt/backups"
    PROJECT_NAME="project"
    SRC_DIR="/srv/backups"
    BACKUP_DIR="/srv/gits"
    PROJECT_NAME="gits"

    BACKUP_RETENTION_DAILY=6
    BACKUP_RETENTION_WEEKLY=3
  7. @bigbosst bigbosst created this gist Aug 6, 2019.
    95 changes: 95 additions & 0 deletions BackupRotated
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,95 @@
    #!/bin/bash

    SRC_DIR="/var/www/html"
    BACKUP_DIR="/mnt/backups"
    PROJECT_NAME="project"

    BACKUP_RETENTION_DAILY=6
    BACKUP_RETENTION_WEEKLY=3
    BACKUP_RETENTION_MONTHLY=3
    BACKUP_RETENTION_YEARLY=0

    DAYYEAR=`date +%j`
    DAYMONTH=`date +%d`
    DAYWEEK=`date +%u`

    if [[ ( $DAYYEAR -eq 1 ) ]];
    then
    FN='yearly'
    elif [[ ( $DAYMONTH -eq 1 ) ]];
    then
    FN='monthly'
    elif [[ ( $DAYWEEK -eq 7 ) ]];
    then
    FN='weekly'
    elif [[ ( $DAYWEEK -lt 7 ) ]];
    then
    FN='daily'
    fi

    DATE=$FN-`date +"%Y%m%d"`
    echo $DATE

    function show_help {
    echo "BackupRotation available options are"
    echo
    echo "-s Sorce directroy to be backed up"
    echo "-b Destination forlder for the backups"
    echo "-n Name of the project being backuped"
    echo "-d Number of Daily backups to keep, negitve numbers will disable"
    echo "-w Number of Weekly backups to keep, negitve numbers will disable"
    echo "-m Number of Monthly backups to keep, negitve numbers will disable"
    echo "-y Number of Yearly backups to keep, negitve numbers will disable"
    echo "-h show this help text"
    }

    function backup
    {
    tar czf $BACKUP_DIR/$PROJECT_NAME-$DATE.tar.gz $SRC_DIR
    cd $BACKUP_DIR/
    echo "Rotating old backups"
    ls -t | grep $PROJECT_NAME | grep daily | sed -e 1,"$BACKUP_RETENTION_DAILY"d | xargs -d '\n' rm -R > /dev/null 2>&1
    ls -t | grep $PROJECT_NAME | grep weekly | sed -e 1,"$BACKUP_RETENTION_WEEKLY"d | xargs -d '\n' rm -R > /dev/null 2>&1
    ls -t | grep $PROJECT_NAME | grep monthly | sed -e 1,"$BACKUP_RETENTION_MONTHLY"d | xargs -d '\n' rm -R > /dev/null 2>&1
    if [[ ( $BACKUP_RETENTION_YEARLY -gt 0 ) ]]; then
    ls -t | grep $PROJECT_NAME | grep htdocs | grep yearly | sed -e 1,"$BACKUP_RETENTION_YEARLY"d | xargs -d '\n' rm -R > /dev/null 2>&1
    fi
    }

    while getopts s:b:n:d:w:m:y:h option
    do
    case "${option}"
    in
    s) SRC_DIR=${OPTARG};;
    b) BACKUP_DIR=${OPTARG};;
    n) PROJECT_NAME=${OPTARG};;
    d) BACKUP_RETENTION_DAILY=${OPTARG};;
    w) BACKUP_RETENTION_WEEKLY=${OPTARG};;
    m) BACKUP_RETENTION_MONTHLY=${OPTARG};;
    y) BACKUP_RETENTION_YEARLY=${OPTARG};;
    h) show_help
    exit 0
    ;;
    esac
    done

    echo $BACKUP_RETENTION_DAILY
    if [[ ( $BACKUP_RETENTION_DAILY -gt 0 ) && ( ! -z "$BACKUP_RETENTION_DAILY" ) && ( $BACKUP_RETENTION_DAILY -ne 0 ) && ( $FN == daily ) ]]; then
    echo "Daily Backup Run"
    backup
    fi
    echo $BACKUP_RETENTION_WEEKLY
    if [[ ( $BACKUP_RETENTION_WEEKLY -gt 0 ) && ( ! -z "$BACKUP_RETENTION_WEEKLY" ) && ( $BACKUP_RETENTION_WEEKLY -ne 0 ) && ( $FN == weekly ) ]]; then
    echo "Weekly Backup Run"
    backup
    fi
    echo $BACKUP_RETENTION_MONTHLY
    if [[ ( $BACKUP_RETENTION_MONTHLY -gt 0 ) && ( ! -z "$BACKUP_RETENTION_MONTHLY" ) && ( $BACKUP_RETENTION_MONTHLY -ne 0 ) && ( $FN == monthly ) ]]; then
    echo "Monthly Backup Run"
    backup
    fi
    echo $BACKUP_RETENTION_YEARLY
    if [[ ( $BACKUP_RETENTION_YEARLY -ge 0 ) && ( ! -z "$BACKUP_RETENTION_YEARLY" ) && ( $FN == yearly ) ]]; then
    echo "Yearly Backup Run"
    backup
    fi