123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- #!/usr/bin/env bash
- # Copyright © 2018 Anton Tsyganenko
- #
- # Permission is hereby granted, free of charge, to any person obtaining
- # a copy of this software and associated documentation files (the
- # "Software"), to deal in the Software without restriction, including
- # without limitation the rights to use, copy, modify, merge, publish,
- # distribute, sublicense, and/or sell copies of the Software, and to
- # permit persons to whom the Software is furnished to do so, subject to
- # the following conditions:
- #
- # The above copyright notice and this permission notice shall be
- # included in all copies or substantial portions of the Software.
- #
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- # ВАЖНО: файлы в бэкапах не предназначены для изменения. Изменяя один
- # файл, вы изменяете этот файл во всех бэкапах, где он был таким-же. Это
- # же жесткие ссылки. Если хотите изменять -- создавайте копию
- # (где-нибудь подальше от бэкапов).
- # Скрипт-документация написан Антоном Цыганенко 2018-03-26, с
- # использованием идей из
- # https://earlruby.org/2013/05/creating-differential-backups-with-hard-links-and-rsync/
- # "LATEST_BACKUP" - имя файла, в котором хранится имя папки с последним
- # успешно созданным бэкапом. Если этот файл удалить, бэкап будет
- # создаваться чистый, без жестких ссылок.
- # Осбождение диска можно производить удалением папок со старыми бэкапами
- # вручную, при этом освободится столько места, сколько занимали inode и
- # файлы, отсутствующие в новых бэкапах. Имеет смысл удалять старые бэкапы
- # или такие бэкапы, файлы из которых отсутствуют в других. Если удаляется
- # последняя жесткая ссылка на файл, это место освобождается.
- # rsync по умолчанию определяет изменения по размеру и дате модификации.
- # Если они не изменились, файл может быть не добавлен в новый бэкап,
- # хотя такой вариант не слишком вероятен. Можно защититься, сравнивая
- # хеши (опция -c), но это может быть дольше.
- # коды возврата скрипта:
- # 1 -- Бэкап $NEW уже существует
- # 2 -- rsync вернул не 0 или 24
- # 0 -- иное (обычно успешно созданный бэкап)
- # Рекомендуется хранить копию этого файла с прописанными настройками в BACKUP_DIR
- ######################################################
- ### НАСТРОЙКИ ###
- # тут можно изменять как надо
- # кроме этого стоит обратить внимание на ключи rsync ниже,
- # например, чтобы исключить ненужное из бэкапов или не писать логи
- # определяем папку, куда складываем бэкапы
- BACKUP_DIR=/run/media/tsyg/f31eb047-4a69-497f-a09f-26a2029b248d/tsyg-pc_bkps
- # папка, которую нужно копировать
- # Если ставить / в конце, то содержимое будет прямо в папке бэкапов, иначе
- # внутри каждого бэкапа будет папка с названием как SOURCE
- # /bkps/2018-01-01/... vs /bkps/2018-01-01/tsyg/...
- SOURCE=/home/tsyg
- # устанавливаем название папки для нового бэкапа.
- # экранирование теперь вроде учтено.
- ## нормальные варианты:
- #NEW=`date --iso-8601` # 2018-03-27
- #NEW=`date --iso-8601=seconds` # 2018-03-27T21:05:54+03:00
- NEW=`date +%Y-%m-%d_%H-%M` # 2018-03-27_17-30
- #NEW=`date +%Y%m%d%H%M%S` # 20180327173032
- #NEW=`uuidgen` # d5baa846-f916-43da-9fb0-820e2e680c49
- ######################################################
- ### СОЗДАНИЕ БЭКАПА ###
- echo "Бэкапим $SOURCE в $BACKUP_DIR, бэкап: $NEW"
- # Проверяем, были ли бэкапы, в процессе создания которых произошли сбои rsync.
- # их можно переименовать, это будет быстрее, чем копировать жесткими ссылками.
- if [ -f "$BACKUP_DIR/BAD_BACKUP" ]; then
- BAD=$(cat $BACKUP_DIR/BAD_BACKUP)
- mv "$BACKUP_DIR/$BAD" "$BACKUP_DIR/$NEW"
- mv "$BACKUP_DIR/rsync-logs/$BAD.log" "$BACKUP_DIR/rsync-logs/$NEW.log"
- rm "$BACKUP_DIR/BAD_BACKUP"
- # если начатых бэкапов нет, проверяем, на основе какого можно сделать
- elif [ -f "$BACKUP_DIR/LATEST_BACKUP" ]; then
- LATEST=$(cat $BACKUP_DIR/LATEST_BACKUP)
- # надо проверить, что такого бэкапа еще нет, иначе они засрутся и
- # потом придется разгребать
- if [ $NEW != $LATEST ]; then
- # копируем поледний бэкап с сохранением всех атрибутов и
- # использованием жестких ссылок
- cp -al "$BACKUP_DIR/$LATEST" "$BACKUP_DIR/$NEW"
- else
- echo "Ошибка! Бэкап $NEW уже существует."
- exit 1
- fi
- fi
- # готовим папку для логов, на случай, если ее еще нет
- mkdir -p "$BACKUP_DIR/rsync-logs/"
- # создаем бэкап. Если rsync видит, что старый и новый файлы отличаются
- # -- создает копию не изменяя содержимое старого бэкапа, иначе -- не
- # трогает. Файлы, удаленные в бэкапируемой бапке, удаляются из бэкапа.
- rsync -a --delete --info=PROGRESS2 \
- --log-file="$BACKUP_DIR/rsync-logs/$NEW.log" \
- "$SOURCE" "$BACKUP_DIR/$NEW"
- # Ключи добавлять перед строчкой "$SOURCE" "$BACKUP_DIR/$NEW"
- # --exclude "BAD/trash_dir"\ # можно исключить ненужные папки
- # --exclude "*.zip"\ # и/или все файлы по шаблону
- # --delete-excluded\ # и удалять их из создаваемых бэкапов,
- # а иначе они останутся как были до исключения
- rsync_exit_code=$?
- # если бэкап создан успешно (или в момент его создания какие-то файлы
- # пропали -- код 24), прописываем его в файл LATEST_BACKUP
- if [ $rsync_exit_code -eq 0 ] || [ $rsync_exit_code -eq 24 ]; then
- echo $NEW > "$BACKUP_DIR/LATEST_BACKUP"
- else
- echo $NEW > "$BACKUP_DIR/BAD_BACKUP"
- echo "Ошибка: бэкап создан некорректно и будет перезаписан при следующем запуске"
- echo "Если вы хотите его оставить, удалите файл BAD_BACKUP"
- exit 2
- fi
- # Создание заготовки для следующего бэкапа, можно отключить флагом --fast
- if [[ $* != *--fast* ]]
- then
- echo "Бэкап создан. Создаем основу для следующего."
- cp -al "$BACKUP_DIR/$NEW" "$BACKUP_DIR/COPY"
- echo "COPY" > "$BACKUP_DIR/BAD_BACKUP"
- fi
|