feat(postgres-backup): 删除通过 Docker Socket 备份 PostgreSQL 的脚本
This commit is contained in:
189
_删除备份/postgres-dump-zstd-via-docker-sock.sh
Executable file
189
_删除备份/postgres-dump-zstd-via-docker-sock.sh
Executable file
@@ -0,0 +1,189 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
# PostgreSQL backup triggered through the Docker Engine unix socket.
|
||||
# Example: ./postgres-dump-zstd-via-docker-sock.sh --container=postgres17 --backup-prefix=pgvector17_all_databases_zstd_ --socket=/var/run/docker.sock --api-version=v1.51 --backup-dir=/backups
|
||||
# Remote example: curl -fsSL https://git.1-h.cc/Scripts/Linux/raw/branch/main/postgres-dump-zstd-via-docker-sock.sh | sh -s -- --container=postgres17 --backup-prefix=pgvector17_all_databases_zstd_ --socket=/var/run/docker.sock --api-version=v1.51 --backup-dir=/backups
|
||||
log() {
|
||||
printf '%s\n' "$(date -u '+%Y-%m-%dT%H:%M:%SZ') $*"
|
||||
}
|
||||
|
||||
log_stream() {
|
||||
log_stream_prefix=$1
|
||||
log_stream_payload=$2
|
||||
|
||||
if [ -n "$log_stream_payload" ]; then
|
||||
printf '%s\n' "$log_stream_payload" | while IFS= read -r log_stream_line; do
|
||||
log "$log_stream_prefix: $log_stream_line"
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
print_usage() {
|
||||
cat <<EOF >&2
|
||||
Usage: $0 [--socket=PATH] [--api-version=VERSION] --container=NAME [--backup-dir=DIR] --backup-prefix=PREFIX
|
||||
|
||||
Options:
|
||||
--socket=PATH Docker Engine unix socket path (default: /var/run/docker.sock)
|
||||
--api-version=VERSION Docker API version (default: v1.51)
|
||||
--container=NAME PostgreSQL container name
|
||||
--backup-dir=DIR Directory to store backups (default: /backups)
|
||||
--backup-prefix=PREFIX Backup filename prefix
|
||||
--help Show this help message
|
||||
EOF
|
||||
}
|
||||
|
||||
DOCKER_SOCKET="/var/run/docker.sock"
|
||||
DOCKER_API_VERSION="v1.51"
|
||||
PG_CONTAINER_NAME=""
|
||||
BACKUP_DIR="/backups"
|
||||
BACKUP_PREFIX=""
|
||||
|
||||
require_command() {
|
||||
if ! command -v "$1" >/dev/null 2>&1; then
|
||||
printf '%s requires %s in PATH\n' "$0" "$1" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
missing_value() {
|
||||
printf 'Missing value for %s\n' "$1" >&2
|
||||
print_usage
|
||||
exit 1
|
||||
}
|
||||
|
||||
docker_exec() {
|
||||
exec_container_name=$1
|
||||
exec_cmd=$2
|
||||
|
||||
curl -fsSL "https://Git.1-H.CC/Scripts/Linux/raw/branch/main/docker-exec-via-sock.sh" | sh -s -- \
|
||||
--socket="$DOCKER_SOCKET" \
|
||||
--api-version="$DOCKER_API_VERSION" \
|
||||
--container="$exec_container_name" \
|
||||
--cmd="$exec_cmd"
|
||||
}
|
||||
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case $1 in
|
||||
--socket=*)
|
||||
DOCKER_SOCKET="${1#*=}"
|
||||
;;
|
||||
--socket)
|
||||
if [ "$#" -lt 2 ]; then
|
||||
missing_value '--socket'
|
||||
fi
|
||||
shift
|
||||
DOCKER_SOCKET="$1"
|
||||
;;
|
||||
--api-version=*)
|
||||
DOCKER_API_VERSION="${1#*=}"
|
||||
;;
|
||||
--api-version)
|
||||
if [ "$#" -lt 2 ]; then
|
||||
missing_value '--api-version'
|
||||
fi
|
||||
shift
|
||||
DOCKER_API_VERSION="$1"
|
||||
;;
|
||||
--container=*)
|
||||
PG_CONTAINER_NAME="${1#*=}"
|
||||
;;
|
||||
--container)
|
||||
if [ "$#" -lt 2 ]; then
|
||||
missing_value '--container'
|
||||
fi
|
||||
shift
|
||||
PG_CONTAINER_NAME="$1"
|
||||
;;
|
||||
--backup-dir=*)
|
||||
BACKUP_DIR="${1#*=}"
|
||||
;;
|
||||
--backup-dir)
|
||||
if [ "$#" -lt 2 ]; then
|
||||
missing_value '--backup-dir'
|
||||
fi
|
||||
shift
|
||||
BACKUP_DIR="$1"
|
||||
;;
|
||||
--backup-prefix=*)
|
||||
BACKUP_PREFIX="${1#*=}"
|
||||
;;
|
||||
--backup-prefix)
|
||||
if [ "$#" -lt 2 ]; then
|
||||
missing_value '--backup-prefix'
|
||||
fi
|
||||
shift
|
||||
BACKUP_PREFIX="$1"
|
||||
;;
|
||||
--help)
|
||||
print_usage
|
||||
exit 0
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
*)
|
||||
printf 'Unknown option: %s\n' "$1" >&2
|
||||
print_usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
|
||||
done
|
||||
|
||||
if [ "$#" -gt 0 ]; then
|
||||
printf 'Unexpected positional arguments: %s\n' "$*" >&2
|
||||
print_usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
require_command curl
|
||||
require_command jq
|
||||
|
||||
if [ -z "$DOCKER_SOCKET" ] || [ -z "$DOCKER_API_VERSION" ] || [ -z "$PG_CONTAINER_NAME" ] || [ -z "$BACKUP_DIR" ] || [ -z "$BACKUP_PREFIX" ]; then
|
||||
print_usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -S "$DOCKER_SOCKET" ]; then
|
||||
log "docker socket $DOCKER_SOCKET not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
timestamp=$(date +%Y-%m-%d_%H-%M-%S)
|
||||
backup_path="$BACKUP_DIR/${BACKUP_PREFIX}${timestamp}.sql.zst"
|
||||
|
||||
log "preparing database backup at $backup_path via docker unix socket"
|
||||
|
||||
cmd="set -o pipefail && pg_dumpall --username=\"\${POSTGRES_USER:-postgres}\" --clean | zstd > ${backup_path}"
|
||||
|
||||
log_border="----------------------------------------------------------------------"
|
||||
|
||||
printf '%s\n' "$log_border" >&2
|
||||
if ! docker_exec "$PG_CONTAINER_NAME" "$cmd"; then
|
||||
printf '%s\n' "$log_border" >&2
|
||||
log "backup command failed"
|
||||
exit 1
|
||||
fi
|
||||
printf '%s\n' "$log_border" >&2
|
||||
|
||||
printf '\n' >&2 # Add a blank line for visual grouping
|
||||
log "backup command finished, verifying file size inside container"
|
||||
|
||||
verify_cmd="du -h \"${backup_path}\" 2>/dev/null | awk 'NR==1{print \$1}'"
|
||||
|
||||
printf '%s\n' "$log_border" >&2
|
||||
size=$(docker_exec "$PG_CONTAINER_NAME" "$verify_cmd" | tr -d '\r')
|
||||
printf '%s\n' "$log_border" >&2
|
||||
|
||||
printf '\n' >&2 # Add a blank line for visual grouping
|
||||
if [ -n "$size" ]; then
|
||||
log "backup completed inside container: $backup_path ($size)"
|
||||
else
|
||||
log "backup completed, but could not determine file size inside container."
|
||||
fi
|
||||
|
||||
printf '\n' >&2 # Add a blank line for visual grouping
|
||||
log "database backup finished"
|
||||
Reference in New Issue
Block a user