Files
sqlite-backup-s3/scripts/backup.sh
T
vasyansk 5646ecd6dd
docker-build / Build image (push) Failing after 6s
fix cron after first run + add hc
2026-09-01 11:00:36 +07:00

80 lines
2.5 KiB
Bash

#!/bin/sh
# crond gives the job a bare environment (HOME/PATH/SHELL only), so the cron
# entry passes --from-cron and the env dumped by entrypoint.sh is restored here.
# A manual run keeps the environment it was invoked with.
if [ "${1:-}" = "--from-cron" ] && [ -f /tmp/container.env ]; then
. /tmp/container.env
fi
set -u
BACKUP_FILE="sqlite_$(date "+%F-%H%M%S").tar.gz"
DUMP=/tmp/db.sqlite
ARCHIVE="/tmp/${BACKUP_FILE}"
DEST="${MINIO_PATH%/}/"
log() { echo "[$(date '+%F %T')] $*"; }
# healthchecks.io ping. Self-hosted instance is supported via HEALTHCHECK_URL.
# Final url: ${HEALTHCHECK_URL}/${HEALTHCHECK_UUID}[/start|/fail]
hc_ping() {
[ -n "${HEALTHCHECK_URL:-}" ] || return 0
url="${HEALTHCHECK_URL%/}"
[ -n "${HEALTHCHECK_UUID:-}" ] && url="${url}/${HEALTHCHECK_UUID}"
[ -n "${1:-}" ] && url="${url}/$1"
curl -fsS -m 10 --retry 3 -o /dev/null "$url" \
|| log "WARN: healthcheck ping failed: ${url}"
}
cleanup() { rm -f "$DUMP" "$ARCHIVE"; }
fail() {
log "ERROR: $*"
cleanup
hc_ping fail
exit 1
}
[ -n "${DB_FILE:-}" ] || fail "DB_FILE is not set"
[ -f "$DB_FILE" ] || fail "database not found: $DB_FILE"
[ -n "${MINIO_PATH:-}" ] || fail "MINIO_PATH is not set"
hc_ping start
log "backup started: $DB_FILE -> ${DEST}${BACKUP_FILE}"
# 1. Consistent snapshot
rm -f "$DUMP"
sqlite3 "$DB_FILE" ".backup '$DUMP'" || fail "sqlite3 .backup failed"
[ -s "$DUMP" ] || fail "dump is empty"
# 2. Verify the snapshot before shipping it anywhere
INTEGRITY=$(sqlite3 "$DUMP" "PRAGMA integrity_check;" 2>&1) \
|| fail "integrity_check failed to run: $INTEGRITY"
[ "$INTEGRITY" = "ok" ] || fail "integrity_check: $INTEGRITY"
# 3. Pack
tar -C /tmp -zcf "$ARCHIVE" "$(basename "$DUMP")" || fail "tar failed"
LOCAL_SIZE=$(wc -c < "$ARCHIVE" | tr -d ' ')
[ "$LOCAL_SIZE" -gt 0 ] || fail "archive is empty"
# 4. Upload
/scripts/minio_uploader.sh copy "$ARCHIVE" "$DEST" || fail "upload failed"
# 5. Verify the remote object exists and matches the local size
REMOTE_SIZE=$(/scripts/minio_uploader.sh size "${DEST}${BACKUP_FILE}")
[ -n "$REMOTE_SIZE" ] || fail "uploaded file not found at ${DEST}${BACKUP_FILE}"
[ "$REMOTE_SIZE" = "$LOCAL_SIZE" ] \
|| fail "size mismatch: local=${LOCAL_SIZE} remote=${REMOTE_SIZE}"
log "uploaded and verified: ${DEST}${BACKUP_FILE} (${LOCAL_SIZE} bytes)"
cleanup
# 6. Rotate old backups
if [ -n "${DELETE_AFTER:-}" ] && [ "${DELETE_AFTER}" -gt 0 ] 2>/dev/null; then
/scripts/deleteold.sh || fail "rotation of old backups failed"
fi
log "backup finished successfully"
hc_ping