fix: odstranit emoji ze vsech souboru
Kompletne odstraneno: - Emoji (smajliky, symboly, boxes, arrows) z README - Emoji ze skriptu (sipky, symboly) - Emoji z docker-compose (adresare) Nahrano za: - Textove alternativy (sipky -> '->', boxes -> '+', atd.) - ASCII pouze kde to slo Ciste vsechny 7 repo (overeno Python skriptem).
This commit is contained in:
+97
-97
@@ -1,30 +1,30 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# docker-backup.sh — bezpečná záloha Docker projektů a named volumes
|
||||
# docker-backup.sh -- bezpečná záloha Docker projektů a named volumes
|
||||
#
|
||||
# - vytvoří timestamp složku v <backup-root>/
|
||||
# - pro každý projekt v <docker-projects-root> zastaví kontejnery,
|
||||
# zálohuje tar.zst, ověří integritu, znovu spustí
|
||||
# zálohuje tar.zst, ověří integritu, znovu spustí
|
||||
# - zvlášť zálohuje Docker named volumes
|
||||
# - ponechá posledních N záloh (default 3)
|
||||
#
|
||||
# Použití:
|
||||
# ./docker-backup.sh # všechny projekty + named volumes
|
||||
# ./docker-backup.sh nginx mattermost # vybrané projekty (volumes vždy)
|
||||
# BACKUP_KEEP=7 ./docker-backup.sh # ponechá 7 záloh
|
||||
# ./docker-backup.sh --help # nápověda
|
||||
# ./docker-backup.sh # všechny projekty + named volumes
|
||||
# ./docker-backup.sh nginx mattermost # vybrané projekty (volumes vždy)
|
||||
# BACKUP_KEEP=7 ./docker-backup.sh # ponechá 7 záloh
|
||||
# ./docker-backup.sh --help # nápověda
|
||||
#
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
sed -n '2,15p' "$0" | sed 's/^# \{0,1\}//'
|
||||
sed -n '2,15p' "$0" | sed 's/^# \{0,1\}//'
|
||||
}
|
||||
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--help|-h) usage; exit 0 ;;
|
||||
esac
|
||||
case "$arg" in
|
||||
--help|-h) usage; exit 0 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
DOCKERY="${DOCKERY:-<docker-projects-root>}"
|
||||
@@ -35,9 +35,9 @@ DEST="${BACKUP_ROOT}/${TS}"
|
||||
|
||||
# Barevné výstupy
|
||||
if [ -t 1 ]; then
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
|
||||
else
|
||||
RED=''; GREEN=''; YELLOW=''; NC=''
|
||||
RED=''; GREEN=''; YELLOW=''; NC=''
|
||||
fi
|
||||
|
||||
log() { printf '%s[%s]%s %s\n' "$GREEN" "$(date '+%H:%M:%S')" "$NC" "$*"; }
|
||||
@@ -46,31 +46,31 @@ err() { printf '%s[%s]%s %s\n' "$RED" "$(date '+%H:%M:%S')" "$NC" "$*"; }
|
||||
|
||||
# Kontrola
|
||||
if ! docker info >/dev/null 2>&1; then
|
||||
err "Docker není dostupný."
|
||||
exit 1
|
||||
err "Docker není dostupný."
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -d "$DOCKERY" ]; then
|
||||
err "Dockery adresář neexistuje: $DOCKERY"
|
||||
exit 1
|
||||
err "Dockery adresář neexistuje: $DOCKERY"
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -d "$BACKUP_ROOT" ]; then
|
||||
err "Backup adresář neexistuje: $BACKUP_ROOT"
|
||||
exit 1
|
||||
err "Backup adresář neexistuje: $BACKUP_ROOT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$DEST"
|
||||
|
||||
# Najdi projekty
|
||||
if [ "$#" -gt 0 ]; then
|
||||
PROJECTS=("$@")
|
||||
PROJECTS=("$@")
|
||||
else
|
||||
PROJECTS=()
|
||||
for d in "$DOCKERY"/*/; do
|
||||
[ -d "$d" ] || continue
|
||||
if compgen -G "$d/docker-compose.y*ml" > /dev/null; then
|
||||
PROJECTS+=("$(basename "$d")")
|
||||
fi
|
||||
done
|
||||
PROJECTS=()
|
||||
for d in "$DOCKERY"/*/; do
|
||||
[ -d "$d" ] || continue
|
||||
if compgen -G "$d/docker-compose.y*ml" > /dev/null; then
|
||||
PROJECTS+=("$(basename "$d")")
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
log "Projektů k záloze: ${#PROJECTS[@]}"
|
||||
@@ -81,13 +81,13 @@ log "Uchovat posledních: $KEEP záloh"
|
||||
log ""
|
||||
log "=== STOP: zastavuji všechny kontejnery v ${PROJECTS[*]} ==="
|
||||
for project in "${PROJECTS[@]}"; do
|
||||
cd "$DOCKERY/$project"
|
||||
if [ -f docker-compose.yml ] || [ -f docker-compose.yaml ]; then
|
||||
if docker compose ps -q 2>/dev/null | grep -q .; then
|
||||
log " [$project] docker compose stop"
|
||||
docker compose stop 2>&1 || true
|
||||
fi
|
||||
fi
|
||||
cd "$DOCKERY/$project"
|
||||
if [ -f docker-compose.yml ] || [ -f docker-compose.yaml ]; then
|
||||
if docker compose ps -q 2>/dev/null | grep -q .; then
|
||||
log " [$project] docker compose stop"
|
||||
docker compose stop 2>&1 || true
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# === FÁZE 2: záloha projektů (paralelně pro velké projekty) ===
|
||||
@@ -95,78 +95,78 @@ log ""
|
||||
log "=== BACKUP projekty (tar.zst) ==="
|
||||
FAILED=()
|
||||
for project in "${PROJECTS[@]}"; do
|
||||
cd "$DOCKERY/$project"
|
||||
ARCHIVE="$DEST/${project}.tar.zst"
|
||||
log " [$project] tar -c <docker-projects-root>/$project/ → $ARCHIVE"
|
||||
# absolutní cesta (background tar pitfall: vždy absolutní)
|
||||
if /usr/bin/tar --exclude='._*' --exclude='.DS_Store' \
|
||||
--use-compress-program='/opt/homebrew/bin/zstd -1 -T0' \
|
||||
-cf "$ARCHIVE" \
|
||||
"<docker-projects-root>/$project/" 2>>"$DEST/.errors"; then
|
||||
# Ověření
|
||||
if /opt/homebrew/bin/zstd -t "$ARCHIVE" >/dev/null 2>&1; then
|
||||
SIZE=$(stat -f '%z' "$ARCHIVE")
|
||||
log " OK ($(numfmt --to=iec --suffix=B "$SIZE" 2>/dev/null || echo "$SIZE B"))"
|
||||
else
|
||||
err " zstd -t selhal pro $ARCHIVE"
|
||||
FAILED+=("$project")
|
||||
fi
|
||||
else
|
||||
err " tar selhal pro $project"
|
||||
FAILED+=("$project")
|
||||
fi
|
||||
cd "$DOCKERY/$project"
|
||||
ARCHIVE="$DEST/${project}.tar.zst"
|
||||
log " [$project] tar -c <docker-projects-root>/$project/ -> $ARCHIVE"
|
||||
# absolutní cesta (background tar pitfall: vždy absolutní)
|
||||
if /usr/bin/tar --exclude='._*' --exclude='.DS_Store' \
|
||||
--use-compress-program='/opt/homebrew/bin/zstd -1 -T0' \
|
||||
-cf "$ARCHIVE" \
|
||||
"<docker-projects-root>/$project/" 2>>"$DEST/.errors"; then
|
||||
# Ověření
|
||||
if /opt/homebrew/bin/zstd -t "$ARCHIVE" >/dev/null 2>&1; then
|
||||
SIZE=$(stat -f '%z' "$ARCHIVE")
|
||||
log " OK ($(numfmt --to=iec --suffix=B "$SIZE" 2>/dev/null || echo "$SIZE B"))"
|
||||
else
|
||||
err " zstd -t selhal pro $ARCHIVE"
|
||||
FAILED+=("$project")
|
||||
fi
|
||||
else
|
||||
err " tar selhal pro $project"
|
||||
FAILED+=("$project")
|
||||
fi
|
||||
done
|
||||
|
||||
# === FÁZE 3: named volumes (per-volume záloha přes Docker) ===
|
||||
log ""
|
||||
log "=== BACKUP named volumes ==="
|
||||
VOLUMES=$(docker volume ls --format '{{.Name}}' \
|
||||
| grep -vE '^(host-services|docker-desktop)$' || true)
|
||||
| grep -vE '^(host-services|docker-desktop)$' || true)
|
||||
|
||||
for vol in $VOLUMES; do
|
||||
ARCHIVE="$DEST/${vol}.tar.zst"
|
||||
log " [volume:$vol] → $ARCHIVE"
|
||||
# Nejdřív dekomprimuj na hostiteli, pak pošli do kontejneru (alpine tar neumí zstd)
|
||||
if docker run --rm \
|
||||
-v "${vol}:/src:ro" \
|
||||
-v "$DEST:/dest" \
|
||||
alpine:3.20 \
|
||||
sh -c "cd /src && tar --exclude='._*' --exclude='.DS_Store' -cf - ." \
|
||||
> "$DEST/${vol}.tar" 2>>"$DEST/.errors"; then
|
||||
/opt/homebrew/bin/zstd -1 -T0 -f "$DEST/${vol}.tar" -o "$ARCHIVE" 2>>"$DEST/.errors"
|
||||
rm -f "$DEST/${vol}.tar"
|
||||
if /opt/homebrew/bin/zstd -t "$ARCHIVE" >/dev/null 2>&1; then
|
||||
SIZE=$(stat -f '%z' "$ARCHIVE")
|
||||
log " OK ($(numfmt --to=iec --suffix=B "$SIZE" 2>/dev/null || echo "$SIZE B"))"
|
||||
else
|
||||
err " zstd -t selhal pro $ARCHIVE"
|
||||
FAILED+=("volume:$vol")
|
||||
fi
|
||||
else
|
||||
err " docker run selhal pro volume $vol"
|
||||
FAILED+=("volume:$vol")
|
||||
fi
|
||||
ARCHIVE="$DEST/${vol}.tar.zst"
|
||||
log " [volume:$vol] -> $ARCHIVE"
|
||||
# Nejdřív dekomprimuj na hostiteli, pak pošli do kontejneru (alpine tar neumí zstd)
|
||||
if docker run --rm \
|
||||
-v "${vol}:/src:ro" \
|
||||
-v "$DEST:/dest" \
|
||||
alpine:3.20 \
|
||||
sh -c "cd /src && tar --exclude='._*' --exclude='.DS_Store' -cf - ." \
|
||||
> "$DEST/${vol}.tar" 2>>"$DEST/.errors"; then
|
||||
/opt/homebrew/bin/zstd -1 -T0 -f "$DEST/${vol}.tar" -o "$ARCHIVE" 2>>"$DEST/.errors"
|
||||
rm -f "$DEST/${vol}.tar"
|
||||
if /opt/homebrew/bin/zstd -t "$ARCHIVE" >/dev/null 2>&1; then
|
||||
SIZE=$(stat -f '%z' "$ARCHIVE")
|
||||
log " OK ($(numfmt --to=iec --suffix=B "$SIZE" 2>/dev/null || echo "$SIZE B"))"
|
||||
else
|
||||
err " zstd -t selhal pro $ARCHIVE"
|
||||
FAILED+=("volume:$vol")
|
||||
fi
|
||||
else
|
||||
err " docker run selhal pro volume $vol"
|
||||
FAILED+=("volume:$vol")
|
||||
fi
|
||||
done
|
||||
|
||||
# === FÁZE 4: znovu spustit projekty ===
|
||||
log ""
|
||||
log "=== UP: spouštím projekty ==="
|
||||
for project in "${PROJECTS[@]}"; do
|
||||
cd "$DOCKERY/$project"
|
||||
if [ -f docker-compose.yml ] || [ -f docker-compose.yaml ]; then
|
||||
log " [$project] docker compose up -d"
|
||||
docker compose up -d 2>&1 || warn " [$project] up -d selhal (zkontroluj)"
|
||||
fi
|
||||
cd "$DOCKERY/$project"
|
||||
if [ -f docker-compose.yml ] || [ -f docker-compose.yaml ]; then
|
||||
log " [$project] docker compose up -d"
|
||||
docker compose up -d 2>&1 || warn " [$project] up -d selhal (zkontroluj)"
|
||||
fi
|
||||
done
|
||||
|
||||
# === FÁZE 5: hash report ===
|
||||
log ""
|
||||
log "=== SHA-256 hashe ==="
|
||||
for f in "$DEST"/*.tar.zst; do
|
||||
[ -f "$f" ] || continue
|
||||
H=$(shasum -a 256 "$f" | awk '{print $1}')
|
||||
S=$(stat -f '%z' "$f")
|
||||
log " $(basename "$f") sha256=$H size=$S"
|
||||
[ -f "$f" ] || continue
|
||||
H=$(shasum -a 256 "$f" | awk '{print $1}')
|
||||
S=$(stat -f '%z' "$f")
|
||||
log " $(basename "$f") sha256=$H size=$S"
|
||||
done
|
||||
|
||||
# === FÁZE 6: retention ===
|
||||
@@ -175,29 +175,29 @@ log "=== RETENTION: ponechávám posledních $KEEP záloh ==="
|
||||
# set -u a prázdné pole
|
||||
existing=()
|
||||
while IFS= read -r d; do
|
||||
[ -d "$d" ] && existing+=("$d")
|
||||
[ -d "$d" ] && existing+=("$d")
|
||||
done < <(find "$BACKUP_ROOT" -maxdepth 1 -mindepth 1 -type d | sort)
|
||||
|
||||
# Pokud něco selhalo, nepromazávej
|
||||
if [ "${#FAILED[@]}" -gt 0 ]; then
|
||||
warn "Některé zálohy selhaly (${#FAILED[@]}), RETENTION se neprovádí"
|
||||
warn "Některé zálohy selhaly (${#FAILED[@]}), RETENTION se neprovádí"
|
||||
else
|
||||
if [ "${#existing[@]}" -gt "$KEEP" ]; then
|
||||
for old in "${existing[@]:0:${#existing[@]}-KEEP}"; do
|
||||
log " mažu starou zálohu: $(basename "$old")"
|
||||
rm -rf "$old"
|
||||
done
|
||||
fi
|
||||
if [ "${#existing[@]}" -gt "$KEEP" ]; then
|
||||
for old in "${existing[@]:0:${#existing[@]}-KEEP}"; do
|
||||
log " mažu starou zálohu: $(basename "$old")"
|
||||
rm -rf "$old"
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
log ""
|
||||
log "======================================"
|
||||
log " HOTOVO"
|
||||
log " HOTOVO"
|
||||
log "======================================"
|
||||
log "Záloha: $DEST"
|
||||
if [ "${#FAILED[@]}" -gt 0 ]; then
|
||||
err "Selhalo: ${#FAILED[@]}"
|
||||
for f in "${FAILED[@]}"; do err " ✗ $f"; done
|
||||
exit 1
|
||||
err "Selhalo: ${#FAILED[@]}"
|
||||
for f in "${FAILED[@]}"; do err " [FAIL] $f"; done
|
||||
exit 1
|
||||
fi
|
||||
log "Vše OK."
|
||||
Reference in New Issue
Block a user