systools

System management tools
git clone git://git.meso-star.fr/systools.git
Log | Files | Refs | README | LICENSE

backup (3719B)


      1 #!/bin/sh
      2 # Copyright (C) 2023, 2024 Vincent Forest (vaplv@posteo.net)
      3 #
      4 # This program is free software: you can redistribute it and/or modify
      5 # it under the terms of the GNU General Public License as published by
      6 # the Free Software Foundation, either version 3 of the License, or
      7 # (at your option) any later version.
      8 #
      9 # This program is distributed in the hope that it will be useful,
     10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     12 # GNU General Public License for more details.
     13 #
     14 # You should have received a copy of the GNU General Public License
     15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
     16 
     17 set -e
     18 
     19 [ -z "${NEXTBACKUP}" ] && NEXTBACKUP="/etc/nextbackup"
     20 
     21 ################################################################################
     22 # Helper functions
     23 ################################################################################
     24 usage()
     25 {
     26   printf "usage: %s backup_dir files_to_backup\n" "${0##*/}"
     27 }
     28 
     29 badseq()
     30 {
     31   printf "%s: invalid sequence %d\n" "${NEXTBACKUP}" "$1" >&2
     32 }
     33 
     34 ################################################################################
     35 # The script
     36 ################################################################################
     37 if [ $# -lt 2 ]; then
     38   usage >&2
     39   exit 1
     40 fi
     41 
     42 # Ensure that the directory in which backup files are saved exists
     43 dir="$1"
     44 mkdir -p "${dir}"
     45 shift 1
     46 
     47 # Retrieves the identifiers of the next backup files, i.e. the expected
     48 # dump level and the current Hanoi sequence in the backup cycle.
     49 entry=""
     50 [ -f "${NEXTBACKUP}" ] && entry="$(head -1 "${NEXTBACKUP}")"
     51 lvl="$(echo "${entry}" | cut -d' ' -f1)"
     52 seq="$(echo "${entry}" | cut -d' ' -f2)"
     53 
     54 # Invalid level or invalid Hanoi sequence => full backup
     55 if ! echo "${lvl}" | grep -qe "^[0-9]" \
     56 || ! echo "${seq}" | grep -qe "^[0-2]"; then
     57   lvl=0
     58   seq=0
     59 fi
     60 
     61 suffix=""
     62 
     63 # Define the suffix of level 0 backup files by the date on which it is
     64 # issued. In this way, each level 0 does not overwrite a previous level
     65 # 0. So, the administrator can archive level 0s according to his or her
     66 # backup strategy. It's a simple, elegant way of keeping a backup
     67 # history.
     68 if [ "${lvl}" -eq 0 ]; then
     69   suffix="_$(date +"%Y%m%d%H%M")"
     70 
     71 # Define the suffix for level 1 backup files; this is the only level
     72 # that will have several files during a complete backup cycle. Sequence
     73 # 0 has no level 1, since it starts with a full backup (i.e. level 0).
     74 # In sequence 1, the backup file is suffixed with 'a', while in sequence
     75 # 2, it is suffixed with 'b'.
     76 elif [ "${lvl}" -eq 1 ]; then
     77   case "${seq}" in
     78     1) suffix="a" ;;
     79     2) suffix="b" ;;
     80     *) badseq "${seq}"; exit 1 ;;
     81   esac
     82 fi
     83 
     84 # Perform backup
     85 backup="${dir}/backup${lvl}${suffix}.dump"
     86 dump "-${lvl}" -u -f "${backup}" "$@"
     87 
     88 # Test the archive and write log
     89 {
     90   printf "[%s]\n" "${backup##*/}"
     91   restore -f "${backup}" -t
     92 } > "${backup%.*}.txt"
     93 
     94 sync
     95 
     96 # Configure the identifiers of the next backup file. A full backup cycle
     97 # is built on ordered dump levels relative to 3 Hanoi sequences. The
     98 # first Hanoi sequence begins with a full backup, and the other two are
     99 # built incrementally from it.
    100 #
    101 # The levels of a full backup cycle are as follows:
    102 #
    103 #   0  -> 3 -> 2 -> 5 -> 4 -> 7 -> 6 -> 9 -> 8
    104 #   1a -> 3 -> 2 -> 5 -> 4 -> 7 -> 6 -> 9 -> 8
    105 #   1b -> 3 -> 2 -> 5 -> 4 -> 7 -> 6 -> 9 -> 8 -> 0
    106 case "${lvl}" in
    107   0|2|4|6) printf "%d %d" "$((lvl+3))" "${seq}" ;;
    108   3|5|7|9) printf "%d %d" "$((lvl-1))" "${seq}" ;;
    109   1) printf "3 %d" "${seq}" ;;
    110   8)
    111     case "${seq}" in
    112       0|1)  printf "1 %d" "$((seq+1))" ;;
    113       2) printf "0 0" ;;
    114       *) badseq "${seq}"; exit 1 ;;
    115     esac
    116     ;;
    117   *) badseq "${seq}"; exit 1 ;;
    118 esac > "${NEXTBACKUP}"