diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..496ee2c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store \ No newline at end of file diff --git a/_删除备份/postgres-dump-zstd-via-docker-sock.sh b/_删除备份/postgres-dump-zstd-via-docker-sock.sh deleted file mode 100755 index e00b844..0000000 --- a/_删除备份/postgres-dump-zstd-via-docker-sock.sh +++ /dev/null @@ -1,189 +0,0 @@ -#!/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 <&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" diff --git a/database-dump-via-docker-sock.sh b/database-dump-via-docker-sock.sh index 48b0480..795e460 100755 --- a/database-dump-via-docker-sock.sh +++ b/database-dump-via-docker-sock.sh @@ -1,8 +1,8 @@ #!/bin/sh set -eu -# Generic database backup triggered through the Docker Engine unix socket. -# Supports PostgreSQL, MySQL/MariaDB, and Kingbase containers. +# 通过 Docker Engine unix socket 触发的通用数据库备份。 +# 支持 PostgreSQL, MySQL/MariaDB 和 Kingbase 容器。 log() { printf '%s\n' "$(date -u '+%Y-%m-%dT%H:%M:%SZ') $*" @@ -10,21 +10,21 @@ log() { print_usage() { cat <&2 -Usage: $0 [--socket=PATH] [--api-version=VERSION] --container=NAME \\ - [--type=postgres|mysql|kingbase] --backup-prefix=PREFIX [--backup-dir=DIR] \\ - [--mysql-user=USER] [--mysql-password=PASSWORD] [--exec-user=NAME] +用法: $0 [--socket=路径] [--api-version=版本] --container=名称 \\ + [--type=postgres|mysql|kingbase] --backup-prefix=前缀 [--backup-dir=目录] \\ + [--mysql-user=用户] [--mysql-password=密码] [--exec-user=名称] -Options: - --socket=PATH Docker Engine unix socket path (default: /var/run/docker.sock) - --api-version=VERSION Docker API version (default: v1.51) - --container=NAME Container name to execute the backup in - --type=TYPE Database type: postgres, mysql, or kingbase (auto-detected from container name if omitted) - --backup-dir=DIR Directory to store backups (default: /backups) - --backup-prefix=PREFIX Backup filename prefix - --mysql-user=USER MySQL user (default: root) - --mysql-password=PASSWORD MySQL password (optional) - --exec-user=NAME Force a specific user when running commands inside the container - --help Show this help message +选项: + --socket=PATH Docker Engine unix socket 路径 (默认: /var/run/docker.sock) + --api-version=VERSION Docker API 版本 (默认: v1.51) + --container=NAME 执行备份的容器名称 + --type=TYPE 数据库类型: postgres, mysql, 或 kingbase (如果省略,则从容器名称自动检测) + --backup-dir=DIR 存储备份的目录 (默认: /backups) + --backup-prefix=PREFIX 备份文件名前缀 + --mysql-user=USER MySQL 用户 (默认: root) + --mysql-password=PASSWORD MySQL 密码 (可选) + --exec-user=NAME 在容器内运行命令时强制使用特定用户 + --help 显示此帮助信息 EOF_USAGE } @@ -67,13 +67,13 @@ detect_db_type_from_name() { require_command() { if ! command -v "$1" >/dev/null 2>&1; then - printf '%s requires %s in PATH\n' "$0" "$1" >&2 + printf '%s 需要 PATH 中包含 %s\n' "$0" "$1" >&2 exit 1 fi } missing_value() { - printf 'Missing value for %s\n' "$1" >&2 + printf '缺少 %s 的值\n' "$1" >&2 print_usage exit 1 } @@ -189,7 +189,7 @@ while [ "$#" -gt 0 ]; do break ;; *) - printf 'Unknown option: %s\n' "$1" >&2 + printf '未知选项: %s\n' "$1" >&2 print_usage exit 1 ;; @@ -198,7 +198,7 @@ while [ "$#" -gt 0 ]; do done if [ "$#" -gt 0 ]; then - printf 'Unexpected positional arguments: %s\n' "$*" >&2 + printf '意外的位置参数: %s\n' "$*" >&2 print_usage exit 1 fi @@ -214,17 +214,17 @@ if [ -z "$DOCKER_SOCKET" ] || [ -z "$DOCKER_API_VERSION" ] || [ -z "$CONTAINER_N fi if [ ! -S "$DOCKER_SOCKET" ]; then - log "docker socket $DOCKER_SOCKET not found" + log "未找到 docker socket $DOCKER_SOCKET" exit 1 fi if [ -z "$DB_TYPE" ]; then if detected_type=$(detect_db_type_from_name "$CONTAINER_NAME"); then DB_TYPE=$detected_type - log "auto-detected database type '$DB_TYPE' from container name '$CONTAINER_NAME'" + log "从容器名称 '$CONTAINER_NAME' 自动检测到数据库类型 '$DB_TYPE'" else - printf 'Unable to detect database type from container name: %s\n' "$CONTAINER_NAME" >&2 - printf 'Please specify --type=postgres, --type=mysql, or --type=kingbase\n' >&2 + printf '无法从容器名称检测数据库类型: %s\n' "$CONTAINER_NAME" >&2 + printf '请指定 --type=postgres, --type=mysql 或 --type=kingbase\n' >&2 exit 1 fi fi @@ -257,7 +257,7 @@ case $DB_TYPE in EXEC_SHELL="sh" ;; *) - printf 'Unsupported database type: %s\n' "$DB_TYPE" >&2 + printf '不支持的数据库类型: %s\n' "$DB_TYPE" >&2 exit 1 ;; esac @@ -271,7 +271,7 @@ fi timestamp=$(date +%Y-%m-%d_%H-%M-%S) backup_path="$BACKUP_DIR/${BACKUP_PREFIX}${timestamp}${BACKUP_EXTENSION}" -log "preparing $DB_TYPE backup at $backup_path via docker unix socket" +log "正在通过 docker unix socket 准备 $DB_TYPE 备份到 $backup_path" cmd="mkdir -p \"${BACKUP_DIR}\" && set -o pipefail && ${DUMP_CMD} | ${COMPRESS_CMD} > \"${backup_path}\"" @@ -280,13 +280,13 @@ log_border="-------------------------------------------------------------------- printf '%s\n' "$log_border" >&2 if ! docker_exec "$CONTAINER_NAME" "$cmd" "${EXEC_USER:-}"; then printf '%s\n' "$log_border" >&2 - log "backup command failed" + log "备份命令失败" exit 1 fi printf '%s\n' "$log_border" >&2 printf '\n' >&2 -log "backup command finished, verifying file size inside container" +log "备份命令完成,正在验证容器内的文件大小" verify_cmd="du -h \"${backup_path}\" 2>/dev/null | awk 'NR==1{print \$1}'" @@ -296,16 +296,16 @@ printf '%s\n' "$log_border" >&2 printf '\n' >&2 if [ -n "$size" ]; then - log "backup completed inside container: $backup_path ($size)" + log "容器内备份完成: $backup_path ($size)" else - log "backup completed, but could not determine file size inside container." + log "备份完成,但无法确定容器内的文件大小。" fi printf '\n' >&2 -log "database backup finished" +log "数据库备份完成" -log "invoking remote cleanup script for prefix '$BACKUP_PREFIX' in $BACKUP_DIR" +log "正在调用远程清理脚本,前缀为 '$BACKUP_PREFIX',目录为 $BACKUP_DIR" if ! curl -fsSL "https://Git.1-H.CC/Scripts/Linux/raw/branch/main/database-dump-cleanup.sh" | \ sh -s -- --prefix="$BACKUP_PREFIX" --dir="$BACKUP_DIR"; then - log "cleanup script failed" + log "清理脚本失败" fi