CMD Master
Назад до блогу
•Оновлено•Arnošt Havelka

Як написати безпечніший Bash-скрипт резервного копіювання з tar

Створіть Bash-резервну копію, що перевіряє джерело, не перезаписує архів, видаляє частковий файл і перевіряє tar.

Почати інтерактивний урок
Як написати безпечніший Bash-скрипт резервного копіювання з tar

Корисний скрипт має відхиляти відсутнє джерело, тримати призначення поза ним, не перезаписувати наявний архів, видаляти частковий результат після помилки та перевіряти архів перед повідомленням про успіх. Навчальний приклад нижче створює стиснений tar-архів із цими запобіжниками. Це не повна система резервування. Урок зі скриптів Bash допоможе відпрацювати її складові.

Явно задайте джерело й призначення

Збережіть як backup.sh:

#!/usr/bin/env bash
set -euo pipefail

source_dir="${1:-$HOME/data}"
backup_dir="${2:-$HOME/backups}"

if [[ ! -d "$source_dir" ]]; then
  printf 'Source directory not found: %s\n' "$source_dir" >&2
  exit 1
fi

mkdir -p "$backup_dir"

source_parent=$(dirname "$source_dir")
source_name=$(basename "$source_dir")
timestamp=$(date '+%Y%m%d-%H%M%S')
archive="$backup_dir/${source_name}-${timestamp}.tar.gz"
partial="$archive.partial"

if [[ -e "$archive" || -e "$partial" ]]; then
  printf 'Backup destination already exists: %s\n' "$archive" >&2
  exit 1
fi

trap 'rm -f "$partial"' EXIT
tar -czf "$partial" -C "$source_parent" "$source_name"
tar -tzf "$partial" >/dev/null
mv "$partial" "$archive"
trap - EXIT

printf 'Backup created: %s\n' "$archive"

Перший аргумент задає джерело, другий — папку архівів. Без аргументів використовуються $HOME/data і $HOME/backups. Призначення має бути поза джерелом, щоб скрипт не архівував власний результат.

Зрозумійте перевірки

set -euo pipefail зупиняє цю послідовність через необроблену помилку, незадану змінну або збій у конвеєрі. Очікувані помилки все одно слід перевіряти явно.

Тест каталогу завершує роботу до tar, якщо джерела немає. Часова мітка запобігає звичайному повторенню назви, а перевірка існування відхиляє колізію. Спочатку створюється файл .partial. Пастка EXIT видаляє його після збою. Остаточну назву отримує лише читабельний архів.

Навіщо tar використовує -C

tar -czf "$partial" -C "$source_parent" "$source_name"

Параметри означають створення (c), gzip-стиснення (z) і запис у наступний файл (f). -C змінює каталог на час операції, тому абсолютний шлях не потрапляє в архів.

Перевірте структуру:

tar -tzf "$archive"

Це підтверджує читабельність, але не актуальність кожного файла й не успішність майбутнього відновлення.

Запустіть і перевірте відновлення

bash -n backup.sh
bash backup.sh "$HOME/data" "$HOME/backups"

Відновіть дані в тимчасову папку:

restore_dir=$(mktemp -d)
tar -xzf "$HOME/backups/data-YYYYMMDD-HHMMSS.tar.gz" -C "$restore_dir"
find "$restore_dir" -type f

Замініть приклад назви на виведену скриптом. Реальна стратегія також потребує незалежного сховища, правил зберігання, моніторингу, захищених облікових даних і регулярних тестів відновлення.

Перегляньте перший Bash-скрипт, якщо shebang чи дозволи незнайомі, і урок tar для практики. Повні правила містить довідник GNU tar.

Посилання

Ці посилання на документацію надають авторитетну інформацію про команди, використані в цій статті.

Далі

Основи Bash: Цикл CD

Практикуйте переміщення між дитячими та батьківськими директоріями, поки зміни шляху не стануть автоматичними.